@atomic-ehr/codegen 0.0.8 → 0.0.9-canary.20260312182458.1c26a02

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 CHANGED
@@ -1,11 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import S from'picocolors';import at from'yargs';import {hideBin}from'yargs/helpers';import {mkdir,writeFile}from'fs/promises';import {dirname}from'path';import {createHash}from'crypto';import Ue from'assert';import {CanonicalManager}from'@atomic-ehr/fhir-canonical-manager';import*as pe from'@atomic-ehr/fhirschema';import {isStructureDefinition}from'@atomic-ehr/fhirschema';var T=class t{options;dryWarnSet=new Set;constructor(e={}){this.options={timestamp:false,level:1,...e};}shouldLog(e){let i=this.options.level??1;return e>=i}static consoleLevelsMap={1:console.log,2:console.warn,3:console.error,0:console.log,4:()=>{}};formatMessage(e,i,n){let o=this.options.timestamp?`${S.gray(new Date().toLocaleTimeString())} `:"",r=this.options.prefix?`${S.cyan(`[${this.options.prefix}]`)} `:"";return `${o}${n(e)} ${r}${i}`}isSuppressed(e){return this.options.suppressLoggingLevel==="all"||this.options.suppressLoggingLevel?.includes(e)||false}tryWriteToConsole(e,i){if(this.isSuppressed(e)||!this.shouldLog(e))return;(t.consoleLevelsMap[e]||console.log)(i);}success(e){this.tryWriteToConsole(1,this.formatMessage("",e,S.green));}error(e,i){if(this.isSuppressed(3)||!this.shouldLog(3))return;console.error(this.formatMessage("X",e,S.red));let n=this.options.level===0;i&&n&&(console.error(S.red(` ${i.message}`)),i.stack&&console.error(S.gray(i.stack)));}warn(e){this.tryWriteToConsole(2,this.formatMessage("!",e,S.yellow));}dryWarn(e){this.dryWarnSet.has(e)||(this.warn(e),this.dryWarnSet.add(e));}info(e){this.tryWriteToConsole(1,this.formatMessage("i",e,S.blue));}debug(e){this.shouldLog(0)&&this.tryWriteToConsole(0,this.formatMessage("\u{1F41B}",e,S.magenta));}step(e){this.tryWriteToConsole(1,this.formatMessage("\u{1F680}",e,S.cyan));}progress(e){this.tryWriteToConsole(1,this.formatMessage("\u23F3",e,S.blue));}plain(e,i=n=>n){let n=this.options.timestamp?`${S.gray(new Date().toLocaleTimeString())} `:"",o=this.options.prefix?`${S.cyan(`[${this.options.prefix}]`)} `:"";this.tryWriteToConsole(1,`${n}${o}${i(e)}`);}dim(e){this.plain(e,S.gray);}child(e){return new t({...this.options,prefix:this.options.prefix?`${this.options.prefix}:${e}`:e})}configure(e){this.options={...this.options,...e};}getLevel(){return this.options.level??1}setLevel(e){this.options.level=e;}},I=new T;function Ee(t){I.success(t);}function R(t,e){I.error(t,e);}function $(t){I.info(t);}function Te(t){I.dim(t);}function Y(t){I.configure(t);}function Z(t={}){return new T(t)}function ee(t){console.log(),console.log(S.cyan(S.bold(`\u2501\u2501\u2501 ${t} \u2501\u2501\u2501`)));}function te(t,e,i){let n=t;e&&(n+=` ${S.gray(`(${e}ms)`)}`),Ee(n),i&&Object.entries(i).forEach(([o,r])=>{Te(` ${o}: ${r}`);});}function k(t,e="\u2022"){t.forEach(i=>{console.log(S.gray(` ${e} ${i}`));});}var v="Use CodeableReference which is not provided by FHIR R4.",De="Use Availability which is not provided by FHIR R4.",j={"hl7.fhir.uv.extensions.r4":{"http://hl7.org/fhir/StructureDefinition/extended-contact-availability":De,"http://hl7.org/fhir/StructureDefinition/immunization-procedure":v,"http://hl7.org/fhir/StructureDefinition/specimen-additive":v,"http://hl7.org/fhir/StructureDefinition/workflow-barrier":v,"http://hl7.org/fhir/StructureDefinition/workflow-protectiveFactor":v,"http://hl7.org/fhir/StructureDefinition/workflow-reason":v},"hl7.fhir.r5.core#5.0.0":{"http://hl7.org/fhir/StructureDefinition/shareablecodesystem":"FIXME: CodeSystem.concept.concept defined by ElementReference. FHIR Schema generator output broken value in it, so we just skip it for now.","http://hl7.org/fhir/StructureDefinition/publishablecodesystem":"Uses R5-only base types not available in R4 generation."}};function C(t,e){let i=`${t.name}#${t.version}`,n=j[i]?.[e];if(n)return {shouldSkip:true,reason:n};let o=j[t.name]?.[e];return o?{shouldSkip:true,reason:o}:{shouldSkip:false}}var x=t=>`${t.name}#${t.version}`,ne=t=>`${t.name}@${t.version}`;var ie=t=>{let e=JSON.stringify(t);return createHash("sha256").update(e).digest("hex").slice(0,16)},oe=(t,e)=>({...t,package_meta:t.package_meta||e,name:t.name,url:t.url,base:t.base});var re=t=>t?.kind==="nested",se=t=>t?.kind==="profile",F=(...t)=>{let e=t.filter(n=>n!==void 0).flatMap(n=>n.map(o=>[o.url,o]));return e.length===0?void 0:Object.values(Object.fromEntries(e)).sort((n,o)=>n.url.localeCompare(o.url))};var ae=(t,e)=>{if(!t.url)throw new Error("ValueSet must have a URL");if(!t.name)throw new Error("ValueSet must have a name");return {...t,package_meta:t.package_meta||e,name:t.name,url:t.url}};function M(t){let e=t.split("|")[0];return e||t}function we(t){return t.split("|")[1]}function Pe(t){return t.derivation==="constraint"?"profile":t.kind==="primitive-type"?"primitive-type":t.kind==="complex-type"?"complex-type":t.kind==="resource"?"resource":t.kind==="logical"?"logical":"resource"}function b(t){return {kind:Pe(t),package:t.package_meta.name,version:t.package_meta.version,name:t.name,url:t.url}}var Ne=t=>{let e=t.split("/"),i=e[e.length-1];return i&&i.length>0?i.split(/[-_]/).map(n=>n.charAt(0).toUpperCase()+n.slice(1).toLowerCase()).join(""):t};function D(t,e,i){let n=M(i),o=Ne(n),r={package_meta:{name:"missing_valuesets",version:we(n)||"0.0.0"},id:i},s=t.resolveVs(e,n)||r,a=s?.id&&!/^[a-zA-Z0-9_-]{20,}$/.test(s.id)?s.id:o;return {kind:"value-set",package:s.package_meta.name,version:s.package_meta.version,name:a,url:n}}function L(t,e,i){let n=i.binding?.bindingName,o=e.join("."),[r,s,a]=n?[{name:"shared",version:"1.0.0"},n,`urn:fhir:binding:${n}`]:[t.package_meta,`${t.name}.${o}_binding`,`${t.url}#${o}_binding`];return {kind:"binding",package:r.name,version:r.version,name:s,url:a}}function B(t,e,i,n){let o=M(i)||i,r=t.resolveVs(e,o);if(r)return He(t,r)}function He(t,e,i){if(e.expansion?.contains)return e.expansion.contains.filter(o=>o.code!==void 0).map(o=>(Ue(o.code),{code:o.code,display:o.display,system:o.system}));let n=[];if(e.compose?.include){for(let o of e.compose.include)if(o.concept)for(let r of o.concept)n.push({system:o.system,code:r.code,display:r.display});else if(o.system&&!o.filter)try{let r=t.resolveAny(o.system);if(r?.concept){let s=(a,c)=>{for(let l of a)n.push({system:c,code:l.code,display:l.display}),l.concept&&s(l.concept,c);};s(r.concept,o.system);}}catch{}}return n.length>0?n:void 0}var ce=100,_=new Set(["code","Coding","CodeableConcept","CodeableReference","Quantity","string","uri","Duration"]);function A(t,e,i,n){if(!i.binding)return;let o=i.binding.strength,r=i.binding.valueSet;if(!r)return;if(!_.has(i.type??"")){n?.dryWarn(`eld-11: Binding on non-bindable type '${i.type}' (valueSet: ${r})`);return}if(!(o==="required"||o==="extensible"||o==="preferred"))return;let a=B(t,e.package_meta,r);if(!a||a.length===0)return;let c=a.map(l=>l.code).filter(l=>l&&typeof l=="string"&&l.trim().length>0);if(c.length>ce){n?.dryWarn(`Value set ${r} has ${c.length} which is more than ${ce} codes, which may cause issues with code generation.`);return}if(c.length!==0)return {isOpen:o!=="required",values:c}}function Ve(t,e,i,n,o){if(!n.binding?.valueSet)return;let r=L(e,i,n),s=D(t,e.package_meta,n.binding.valueSet),a=A(t,e,n,o);return {identifier:r,valueset:s,strength:n.binding.strength,enum:a,dependencies:[s]}}function le(t,e,i){let n=new Set;if(!e.elements)return [];let o=[];function r(c,l){for(let[d,m]of Object.entries(c)){let y=[...l,d],p=y.join("."),u=t.resolveElementSnapshot(e,y);if(!n.has(p)){if(n.add(p),u.binding){let f=Ve(t,e,y,u,i);f&&o.push(f);}m.elements&&r(m.elements,y);}}}r(e.elements,[]),o.sort((c,l)=>c.identifier.name.localeCompare(l.identifier.name));let s=[],a=new Set;for(let c of o)a.has(c.identifier.url)||(a.add(c.identifier.url),s.push(c));return s}var G=t=>t!==null&&typeof t=="object"&&t.resourceType==="CodeSystem";var w=t=>t!==null&&typeof t=="object"&&t.resourceType==="ValueSet";var $e=async(t,e)=>{let i=await t.packageJson(e.name);if(!i)return [];let n=i.dependencies;return n!==void 0?Object.entries(n).map(([o,r])=>({name:o,version:r})):[]},de=t=>({pkg:t,canonicalResolution:{},fhirSchemas:{},valueSets:{}}),ue=async(t,e,i,n,o)=>{let r=x(e);if(o?.info(`${" ".repeat(i*2)}+ ${r}`),n[r])return n[r];let s=de(e);for(let c of await t.search({package:e})){let l=c.url;if(!l||!(isStructureDefinition(c)||w(c)||G(c)))continue;let d=l;s.canonicalResolution[d]&&o?.dryWarn(`Duplicate canonical URL: ${d} at ${r}.`),s.canonicalResolution[d]=[{deep:i,pkg:e,pkgId:r,resource:c}];}let a=await $e(t,e);for(let c of a){let{canonicalResolution:l}=await ue(t,c,i+1,n,o);for(let[d,m]of Object.entries(l)){let y=d;s.canonicalResolution[y]=[...s.canonicalResolution[y]||[],...m];}}for(let c of Object.values(s.canonicalResolution))c.sort((l,d)=>l.deep-d.deep);return n[r]=s,s},je=(t,e)=>{for(let{pkg:i,canonicalResolution:n}of Object.values(t)){let o=x(i);if(!t[o])throw new Error(`Package ${o} not found`);for(let[s,a]of Object.entries(n)){let c=a[0];if(!c)throw new Error("Resource not found");let l=c.resource,d=c.pkg;if(isStructureDefinition(l)){let m=pe.translate(l),y=oe(m,d);t[o].fhirSchemas[y.url]=y;}if(w(l)){let m=ae(l,d);t[o].valueSets[m.url]=m;}}}},Me=(t,e,i)=>{let n=Object.values(t).flatMap(o=>o.canonicalResolution[e]);if(!n)throw new Error(`No canonical resolution found for ${e} in any package`);return n[0]?.resource},Be=async(t,{logger:e,focusedPackages:i})=>{let n=i??await t.packages(),o={};for(let p of n)await ue(t,p,0,o,e);je(o);let r=(p,u)=>{let f=o[x(p)];if(f){let g=f.canonicalResolution[u]?.[0];if(g)return o[g.pkgId]?.fhirSchemas[u]}for(let g of Object.values(o)){let h=g.fhirSchemas[u];if(h&&h.package_meta.name===p.name)return h}for(let g of Object.values(o)){let h=g.fhirSchemas[u];if(h)return h}},s=(p,u)=>{let f=o[x(p)];if(f){let g=f.canonicalResolution[u]?.[0];if(g)return o[g.pkgId]?.valueSets[u]}for(let g of Object.values(o)){let h=g.valueSets[u];if(h&&h.package_meta.name===p.name)return h}for(let g of Object.values(o)){let h=g.valueSets[u];if(h)return h}},a=p=>(p.includes("|")&&(p=p.split("|")[0]),p.match(/^[a-zA-Z0-9]+$/)?`http://hl7.org/fhir/StructureDefinition/${p}`:p),c=(p,u)=>{let f=r(p,u);if(f===void 0)throw new Error(`Failed to resolve FHIR Schema: '${u}'`);let g=[f];for(;f?.base;){let h=f.package_meta,E=a(f.base);if(f=r(h,E),f===void 0)throw new Error(`Failed to resolve FHIR Schema base for '${u}'. Problem: '${E}' from '${x(h)}'`);g.push(f);}return g},l=(p,u)=>c(p,u).filter(f=>f.derivation==="specialization"),d=(p,u)=>{let f=c(p.package_meta,p.url),g=N(f,u);return W(g)},m=p=>{let u=new Set;for(let[f,g]of Object.entries(p)){u.add(f);for(let h of g?.choices||[])p[h]||u.add(h);}return Array.from(u)},y;return {testAppendFs(p){let u=x(p.package_meta);o[u]||(o[u]=de(p.package_meta)),o[u].fhirSchemas[p.url]=p,y=void 0;},resolveFs:r,resolveFsGenealogy:c,resolveFsSpecializations:l,ensureSpecializationCanonicalUrl:a,resolveSd:(p,u)=>{let f=o[x(p)]?.canonicalResolution[u]?.[0]?.resource;if(isStructureDefinition(f))return f},allSd:()=>Object.values(o).flatMap(p=>Object.values(p.canonicalResolution).flatMap(u=>u.map(f=>{let g=f.resource;return g.package_name?g:{...g,package_name:p.pkg.name,package_version:p.pkg.version}}))).filter(p=>isStructureDefinition(p)).sort((p,u)=>p.url.localeCompare(u.url)),allFs:()=>Object.values(o).flatMap(p=>Object.values(p.fhirSchemas)),allVs:()=>Object.values(o).flatMap(p=>Object.values(p.valueSets)),resolveVs:s,resolveAny:p=>Me(o,p),resolveElementSnapshot:d,getAllElementKeys:m,resolver:o,resolutionTree:()=>{if(y)return y;let p={};for(let[u,f]of Object.entries(o)){let g=f.pkg.name;p[g]={};for(let[h,E]of Object.entries(f.canonicalResolution)){let Q=h;p[g][Q]=[];for(let X of E)p[g][Q].push({deep:X.deep,pkg:X.pkg});}}return y=p,p}}},me=async(t,e)=>{let i=t.map(ne);e?.logger?.step(`Loading FHIR packages: ${i.join(", ")}`);let n=CanonicalManager({packages:i,workingDir:"tmp/fhir",registry:e.registry||void 0});return await n.init(),await Be(n,{...e,focusedPackages:t})},N=(t,e)=>{let[i,...n]=e;return i===void 0?[]:t.map(o=>{if(!o.elements)return;let r=o.elements?.[i];for(let s of n)r=r?.elements?.[s];return r}).filter(o=>o!==void 0)};function W(t){let e=t.reverse(),i=Object.assign({},...e);return i.elements=void 0,i}var fe=(t,e,i)=>{let n=t.resolveFsSpecializations(e.package_meta,e.url),o=N(n,i),r=W(o).type,s;if(r){let a=t.ensureSpecializationCanonicalUrl(r),l=t.resolveFsGenealogy(e.package_meta,a).flatMap(d=>Object.keys(d.elements??{}));l.length>0&&(s=new Set(l));}for(let a of o)if(!(!a.elements||Object.keys(a.elements).length===0)&&!(s&&!Object.keys(a.elements).some(c=>!s.has(c))))return true;return false},q=(t,e,i,n,o)=>n.type==="BackboneElement"?true:!o?.elements||o.choiceOf!==void 0?false:fe(t,e,i),_e=t=>t.elements?new Set(z(t,[],t.elements).filter(([e,i])=>i.elements&&Object.keys(i.elements).length>0).map(([e])=>e.join("."))):new Set;function U(t,e,i){let n={},o=e.derivation==="constraint"?t.resolveFsSpecializations(e.package_meta,e.url):t.resolveFsGenealogy(e.package_meta,e.url);for(let d of [...o].reverse()){let m=_e(d);for(let y of m)n[y]=`${d.url}#${y}`;}let r=i.join("."),s=n[r]??`${e.url}#${r}`,a=s.split("#")[0],l=t.resolveFs(e.package_meta,a)?.package_meta??e.package_meta;return {kind:"nested",package:l.name,version:l.version,name:r,url:s}}function z(t,e,i){let n=[];for(let[o,r]of Object.entries(i)){let s=[...e,o];r.elements&&r.choiceOf===void 0&&n.push([s,r]),r.elements&&n.push(...z(t,s,r.elements));}return n}function Ae(t,e,i,n,o){let r={},s=t.resolveFsGenealogy(e.package_meta,e.url),a=N(s,i),c=new Set;for(let l of a)if(l.elements)for(let d of Object.keys(l.elements))c.add(d);for(let l of c){let d=[...i,l],m=t.resolveElementSnapshot(e,d);q(t,e,d,m,n[l])?r[l]=V(t,e,d,m):r[l]=H(t,e,d,m,o);}return r}function ge(t,e,i){if(!e.elements)return;let n=z(e,[],e.elements).filter(([r,s])=>!s.elements||Object.keys(s.elements).length===0?false:s.type!=="BackboneElement"?fe(t,e,r):true),o=[];for(let[r,s]of n){let a=U(t,e,r),c;s.type==="BackboneElement"||!s.type?c="BackboneElement":c=s.type;let l=t.ensureSpecializationCanonicalUrl(c),d=t.resolveFs(e.package_meta,l);if(!d)throw new Error(`Could not resolve base type ${c}`);let m={kind:"complex-type",package:d.package_meta.name,version:d.package_meta.version,name:c,url:l},y=Ae(t,e,r,s.elements??{},i),p={identifier:a,base:m,fields:y};o.push(p);}return o.sort((r,s)=>r.identifier.url.localeCompare(s.identifier.url)),o.length===0?void 0:o}function ye(t){let e=[];for(let i of t){i.base&&e.push(i.base);for(let n of Object.values(i.fields||{}))"type"in n&&n.type&&e.push(n.type),"binding"in n&&n.binding&&e.push(n.binding);}return e}function he(t,e,i){let n=i[i.length-1];if(!n)throw new Error(`Internal error: fieldName is missing for path ${i.join("/")}`);let o=i.slice(0,-1),r=t.resolveFsGenealogy(e.package_meta,e.url).flatMap(s=>{if(o.length===0)return s.required||[];if(!s.elements)return [];let a=s;for(let c of o)a=a?.elements?.[c];return a?.required||[]});return new Set(r).has(n)}function Se(t,e,i){let n=i[i.length-1];if(!n)throw new Error(`Internal error: fieldName is missing for path ${i.join("/")}`);let o=i.slice(0,-1),r=t.resolveFsGenealogy(e.package_meta,e.url).flatMap(s=>{if(o.length===0)return s.excluded||[];if(!s.elements)return [];let a=s;for(let c of o)a=a?.elements?.[c];return a?.excluded||[]});return new Set(r).has(n)}var Ge=(t,e,i)=>{if(i.refers)return i.refers.map(n=>{let o=t.ensureSpecializationCanonicalUrl(n),r=t.resolveFs(e.package_meta,o);if(!r)throw new Error(`Failed to resolve fs for ${o}`);return b(r)})},We=t=>{let e=new Set,i=new Set;if(t.required)for(let o of t.required)e.add(o);if(t.excluded)for(let o of t.excluded)i.add(o);if(t.elements)for(let[o,r]of Object.entries(t.elements))r.min!==void 0&&r.min>0&&e.add(o);let n=t.elements?Object.keys(t.elements):void 0;return {required:e.size>0?Array.from(e):void 0,excluded:i.size>0?Array.from(i):void 0,elements:n&&n.length>0?n:void 0}},qe=t=>!t||typeof t=="object"&&Object.keys(t).length===0,K=(t,e,i)=>{let n=t;for(let r=0;r<e.length-1;r++){let s=e[r];(!n[s]||typeof n[s]!="object")&&(n[s]={}),n=n[s];}let o=e[e.length-1];n[o]=i;},ze=(t,e)=>{let i=t;for(let n of e)if(i&&typeof i=="object"&&!Array.isArray(i))i=i[n];else return;return i},xe=(t,e,i,n)=>{if(i>=e.length||!t.elements)return;let o=e[i],r=t.elements[o];if(r){if(i===e.length-1&&r.fixed?.value!==void 0){K(n,e,r.fixed.value);return}if(r.slicing?.slices){let s=e.slice(i+1);for(let a of Object.values(r.slicing.slices)){if(!a.min||a.min<1||!a.match||typeof a.match!="object")continue;let c=a.match;if(Object.keys(c).length!==0)if(s.length>0){let l=ze(c,s);l!==void 0&&K(n,e,l);}else K(n,e.slice(0,i+1),c);}return}xe(r,e,i+1,n);}},Ke=(t,e)=>{if(!e?.elements||!t||t.length===0)return;let i={};for(let n of t){let o=n.path.split(".");xe(e,o,0,i);}return Object.keys(i).length>0?i:void 0},Re=t=>{let e=t.slicing;if(!e)return;let i={};for(let[n,o]of Object.entries(e.slices??{})){if(!o)continue;let{required:r,excluded:s,elements:a}=o.schema?We(o.schema):{};i[n]={min:o.min,max:o.max,match:qe(o.match)?Ke(e.discriminator??[],o.schema):o.match,required:r,excluded:s,elements:a};}return {discriminator:e.discriminator,rules:e.rules,ordered:e.ordered,slices:Object.keys(i).length>0?i:void 0}};function O(t,e,i,n,o){if(n.elementReference){let r=n.elementReference.slice(1).filter((s,a)=>a%2===1);return U(t,e,r)}else if(n.type){let r=t.ensureSpecializationCanonicalUrl(n.type),s=t.resolveFs(e.package_meta,r);if(!s)throw new Error(`Could not resolve field type: <${e.url}>.${i.join(".")}: <${n.type}> (pkg: '${x(e.package_meta)}'))`);return b(s)}else {if(n.choices)return;if(e.derivation==="constraint")return;o?.dryWarn(`Can't recognize element type: <${e.url}>.${i.join(".")} (pkg: '${x(e.package_meta)}'): missing type info`);return}}var H=(t,e,i,n,o,r)=>{let s,a;n.binding&&(s=L(e,i,n),_.has(n.type??"")&&(a=A(t,e,n,o)));let c=O(t,e,i,n,o);c||o?.dryWarn(`Field type not found for '${e.url}#${i.join(".")}' (${e.derivation})`);let l;n.pattern?l={kind:"pattern",type:n.pattern.type,value:n.pattern.value}:n.fixed&&(l={kind:"fixed",type:n.fixed.type,value:n.fixed.value});let d=r??n;if(!l&&d.elements?.coding?.slicing?.slices){let m=d.elements.coding.slicing.slices,y=Object.values(m);if(y.length>0&&y.every(u=>u.min!==void 0&&u.min>=1&&u.match&&typeof u.match=="object"&&Object.keys(u.match).length>0)){let u=y.map(f=>f.match);l={kind:"fixed",type:"CodeableConcept",value:{coding:u.length===1?[u[0]]:u}};}}return {type:c,required:he(t,e,i),excluded:Se(t,e,i),reference:Ge(t,e,n),array:n.array||false,min:n.min,max:n.max,slicing:Re(n),choices:n.choices,choiceOf:n.choiceOf,binding:s,enum:a,valueConstraint:l}};function V(t,e,i,n){return {type:U(t,e,i),array:n.array||false,required:he(t,e,i),excluded:Se(t,e,i),slicing:Re(n)}}var Je=(t,e,i,n)=>{let o=t.resolveFs(e.package_meta,i);if(!o?.elements)return;let r=[];for(let[s,a]of Object.entries(o.elements)){if(a.choiceOf!=="value"&&!s.startsWith("value"))continue;let c=O(t,o,[s],a,n);c&&r.push(c);}return F(r)},Qe=(t,e,i)=>{let n=[];if(!e.elements)return n;for(let[o,r]of Object.entries(e.elements)){if(!o.startsWith("extension:"))continue;let s=o.split(":")[1];if(!s)continue;let a;for(let[c,l]of Object.entries(r.elements??{}))if(!(l.choiceOf!=="value"&&!c.startsWith("value"))&&(a=O(t,e,[o,c],l,i),a))break;n.push({name:s,url:r.url??s,valueType:a,min:r.min,max:r.max!==void 0?String(r.max):void 0});}return n},Xe=t=>{let e=[],n=t.elements?.extension?.slicing?.slices;if(!n||typeof n!="object")return e;for(let[o,r]of Object.entries(n)){let s=r,a=s.schema;if(!a)continue;let c;for(let[l,d]of Object.entries(a.elements??{})){let m=d;if(!(m.choiceOf!=="value"&&!l.startsWith("value"))&&m.type){c={kind:"complex-type",package:t.package_meta.name,version:t.package_meta.version,name:m.type,url:`http://hl7.org/fhir/StructureDefinition/${m.type}`};break}}e.push({name:o,url:s.match?.url??o,valueType:c,min:a._required?1:a.min??0,max:a.max!==void 0?String(a.max):a.array?"*":"1"});}return e},Ye=(t,e,i,n)=>{let o=t.resolveFs(e.package_meta,i);if(!o?.elements)return;let r=Qe(t,o,n),s=Xe(o),a=[...r,...s];return a.length>0?a:void 0},ke=(t,e,i)=>{let n=[],o=(s,a,c)=>{let l=c.url,d=l?Je(t,e,l,i):void 0,m=l?Ye(t,e,l,i):void 0;if(!l){let p=e.elements?.extension?.slicing?.slices?.[a]?.schema;if(p){l=p.elements?.url?.fixed?.value??a;for(let[u,f]of Object.entries(p.elements??{})){let g=f;if(g.choiceOf==="value"&&g.type){d=[{kind:"complex-type",package:e.package_meta.name,version:e.package_meta.version,name:g.type,url:`http://hl7.org/fhir/StructureDefinition/${g.type}`}];break}}}}let y=m&&m.length>0;n.push({name:a,path:[...s,"extension"].join("."),url:l,min:c.min,max:c.max!==void 0?String(c.max):void 0,mustSupport:c.mustSupport,valueTypes:d,subExtensions:m,isComplex:y});},r=(s,a)=>{if(a.extensions)for(let[c,l]of Object.entries(a.extensions))o(s,c,l);if(a.elements)for(let[c,l]of Object.entries(a.elements))r([...s,c],l);};return r([],e),n.length===0?void 0:n};function Ze(t,e,i,n,o){if(!n)return;let r={};for(let s of t.getAllElementKeys(n)){let a=[...i,s],c=t.resolveElementSnapshot(e,a),l=c.type?t.ensureSpecializationCanonicalUrl(c.type):void 0;if(l&&C(e.package_meta,l).shouldSkip){o?.warn(`Skipping field ${a} for ${l} due to skip hack ${C(e.package_meta,l).reason}`);continue}q(t,e,a,c,n[s])?r[s]=V(t,e,a,c):r[s]=H(t,e,a,c,o,n[s]);}return r}function et(t){let e=[];for(let i of Object.values(t))"type"in i&&i.type&&e.push(i.type),"binding"in i&&i.binding&&e.push(i.binding);return e}async function Ce(t,e,i){if(!e.url)throw new Error("ValueSet URL is required");let n=D(t,e.package_meta,e.url),o=B(t,e.package_meta,e.url);return {identifier:n,description:e.description,concept:o,compose:o?void 0:e.compose}}function tt(t,e,i,n){let o=[];e&&o.push(e),i&&o.push(...et(i)),n&&o.push(...ye(n));let r=new Set(n?.map(a=>a.identifier.url)),s=o.filter(a=>a.url===t.url?false:se(t)||!re(a)?true:!r.has(a.url));return F(s)}function nt(t,e,i){let n=b(e),o;if(e.base){let y=t.resolveFs(e.package_meta,t.ensureSpecializationCanonicalUrl(e.base));if(!y)throw new Error(`Base resource not found '${e.base}' for <${e.url}> from ${x(e.package_meta)}`);o=b(y);}let r=Ze(t,e,[],e.elements,i),s=ge(t,e,i),a=e.derivation==="constraint"?ke(t,e,i):void 0,c=a?.flatMap(y=>y.valueTypes??[])??[],l=tt(n,o,r,s),d={identifier:n,base:o,fields:r,nested:s,description:e.description,dependencies:F(l,c),extensions:a},m=le(t,e,i);return [d,...m]}async function be(t,e,i){return nt(t,e,i)}var it=(t,e)=>{let i={};for(let r of t){let s=`${r.schema.identifier.url}|${r.schema.identifier.package}`,a=ie(r.schema);i[s]??={},i[s][a]??={typeSchema:r.schema,sources:[]},i[s][a].sources.push(r);}let n=[],o={};for(let r of Object.values(i)){let s=Object.values(r).sort((c,l)=>l.sources.length-c.sources.length),a=s[0];if(a&&(n.push(a.typeSchema),s.length>1)){let c=a.typeSchema.identifier.package,l=a.typeSchema.identifier.url;e?.dryWarn(`'${l}' from '${c}'' has ${s.length} versions`),o[c]??={},o[c][l]=s.flatMap(d=>d.sources.map(m=>({typeSchema:d.typeSchema,sourcePackage:m.sourcePackage,sourceCanonical:m.sourceCanonical})));}}return {schemas:n,collisions:o}},Ie=async(t,e)=>{let i=[];for(let n of t.allFs()){let o=x(n.package_meta),r=C(n.package_meta,n.url);if(r.shouldSkip){e?.dryWarn(`Skip ${n.url} from ${o}. Reason: ${r.reason}`);continue}for(let s of await be(t,n,e))i.push({schema:s,sourcePackage:o,sourceCanonical:n.url});}for(let n of t.allVs())i.push({schema:await Ce(t,n),sourcePackage:x(n.package_meta),sourceCanonical:n.url});return it(i,e)};var ve={command:"generate <packages..>",describe:"Generate TypeSchema files from FHIR packages",builder:{packages:{type:"string",array:true,demandOption:true,describe:"FHIR packages to process (e.g., hl7.fhir.r4.core@4.0.1)"},output:{alias:"o",type:"string",describe:"Output file or directory",default:"./schemas.ndjson"},format:{alias:"f",type:"string",choices:["ndjson","json"],default:"ndjson",describe:"Output format for TypeSchema files"},treeshake:{alias:"t",type:"string",array:true,describe:"Only generate TypeSchemas for specific ResourceTypes (treeshaking)"},singleFile:{alias:"s",type:"boolean",default:false,describe:"Generate single TypeSchema file instead of multiple files (NDJSON format)"},verbose:{alias:"v",type:"boolean",default:false,describe:"Enable verbose output"},registry:{alias:"r",type:"string",describe:"Custom FHIR package registry URL (default: https://fs.get-ig.org/pkgs/)"}},handler:async t=>{let e=Z({prefix:"TypeSchema"});try{e.step("Generating TypeSchema from FHIR packages"),e.info(`Packages: ${t.packages.join(", ")}`),e.info(`Output: ${t.output}`);let i=t.singleFile?"ndjson":t.format;e.debug(`Format: ${i}${t.singleFile&&t.format==="json"?" (forced from json due to singleFile)":""}`),t.treeshake&&t.treeshake.length>0&&e.info(`Treeshaking enabled for ResourceTypes: ${t.treeshake.join(", ")}`),t.singleFile&&e.info("Single file output enabled (NDJSON format)"),t.registry&&e.info(`Using custom registry: ${t.registry}`);let n=Date.now(),o=t.packages.map(d=>{if(d.includes("@")){let m=d.lastIndexOf("@");return {name:d.slice(0,m),version:d.slice(m+1)||"latest"}}return {name:d,version:"latest"}});e.progress(`Processing packages: ${o.map(d=>`${d.name}@${d.version}`).join(", ")}`);let r=await me(o,{logger:e,registry:t.registry,focusedPackages:o}),{schemas:s}=await Ie(r,e);if(s.length===0)throw new Error("No schemas were generated from the specified packages");let a=t.output;if(!a)throw new Error("Output format not specified");await mkdir(dirname(a),{recursive:!0});let c;i==="json"?c=JSON.stringify(s,null,2):c=s.map(d=>JSON.stringify(d)).join(`
3
- `),await writeFile(a,c,"utf-8");let l=Date.now()-n;if(te(`Generated ${s.length} TypeSchema definitions`,l,{schemas:s.length}),e.dim(`Output: ${a}`),t.verbose){e.debug("Generated schemas:");let d=s.map(m=>`${m.identifier?.name||"Unknown"} (${m.identifier?.kind||"unknown"})`);k(d);}}catch(i){e.error("Failed to generate TypeSchema",i instanceof Error?i:new Error(String(i))),process.exit(1);}}};var Fe={command:"typeschema [subcommand]",describe:"TypeSchema operations - generate, validate and merge schemas",builder:t=>t.command(ve).help().example("$0 typeschema generate hl7.fhir.r4.core@4.0.1","Generate TypeSchema from FHIR R4 core package"),handler:t=>{if(!t.subcommand&&t._.length===1){$("Available typeschema subcommands:"),k(["generate Generate TypeSchema files from FHIR packages"]),console.log(`
2
+ import b from'picocolors';import an from'yargs';import {hideBin}from'yargs/helpers';import {mkdir,writeFile}from'fs/promises';import {dirname}from'path';import {createHash}from'crypto';import Ne from'assert';import {CanonicalManager}from'@atomic-ehr/fhir-canonical-manager';import*as pe from'@atomic-ehr/fhirschema';import {isStructureDefinition}from'@atomic-ehr/fhirschema';var Z=e=>{console.log(),console.log(b.cyan(b.bold(`\u2501\u2501\u2501 ${e} \u2501\u2501\u2501`)));},ee=(e,n,i)=>{let t=e;if(n&&(t+=` ${b.gray(`(${n}ms)`)}`),console.log(`${b.green("")} ${t}`),i)for(let[o,r]of Object.entries(i))console.log(b.gray(` ${o}: ${r}`));},I=(e,n="\u2022")=>{for(let i of e)console.log(b.gray(` ${n} ${i}`));};var ne={DEBUG:0,INFO:1,WARN:2,ERROR:3,SILENT:4};function C(e={}){let n=e.prefix??"",i=new Set(e.suppressTags??[]),t={},o=[],r=new Set,a=e.level??"INFO",s=p=>ne[p]>=ne[a],c={DEBUG:p=>p,INFO:p=>p,WARN:b.yellow,ERROR:b.red,SILENT:p=>p},l=(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)=>{o.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,k=y.length===2?y[1]:y[0];S&&(t[S]=(t[S]??0)+1);let R=S!==void 0&&i.has(S);if(d(p,k,S,R),!R&&s(p)){if(g){let Y=`${p}::${S??""}::${k}`;if(r.has(Y))return;r.add(Y);}f(l(p,m,k,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=[...i,...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])=>!i.has(y)),g=p.filter(([y])=>i.has(y));if(f.length>0){let y=f.reduce((k,[,R])=>k+R,0),S=f.map(([k,R])=>`${k}: ${R}`).join(", ");console.warn(b.yellow(`! ${m}${y} warnings (${S})`));}if(g.length>0){let y=g.reduce((k,[,R])=>k+R,0),S=g.map(([k,R])=>`${k}: ${R}`).join(", ");console.log(b.dim(`i ${m}${y} suppressed (${S})`));}},buffer(){return o},bufferClear(){o.length=0;}};return h}var E="Use CodeableReference which is not provided by FHIR R4.",Te="Use Availability which is not provided by FHIR R4.",M={"hl7.fhir.uv.extensions.r4":{"http://hl7.org/fhir/StructureDefinition/extended-contact-availability":Te,"http://hl7.org/fhir/StructureDefinition/immunization-procedure":E,"http://hl7.org/fhir/StructureDefinition/specimen-additive":E,"http://hl7.org/fhir/StructureDefinition/workflow-barrier":E,"http://hl7.org/fhir/StructureDefinition/workflow-protectiveFactor":E,"http://hl7.org/fhir/StructureDefinition/workflow-reason":E},"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 F(e,n){let i=`${e.name}#${e.version}`,t=M[i]?.[n];if(t)return {shouldSkip:true,reason:t};let o=M[e.name]?.[n];return o?{shouldSkip:true,reason:o}:{shouldSkip:false}}var x=e=>`${e.name}#${e.version}`,te=e=>`${e.name}@${e.version}`;var oe=e=>{let n=JSON.stringify(e);return createHash("sha256").update(n).digest("hex").slice(0,16)},ie=(e,n)=>({...e,package_meta:e.package_meta||n,name:e.name,url:e.url,base:e.base});var re=e=>e?.kind==="nested",ae=e=>e?.kind==="profile",D=(...e)=>{let n=e.filter(t=>t!==void 0).flatMap(t=>t.map(o=>[o.url,o]));return n.length===0?void 0:Object.values(Object.fromEntries(n)).sort((t,o)=>t.url.localeCompare(o.url))};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 B(e){let n=e.split("|")[0];return n||e}function De(e){return e.split("|")[1]}function Pe(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 v(e){return {kind:Pe(e),package:e.package_meta.name,version:e.package_meta.version,name:e.name,url:e.url}}var Le=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 P(e,n,i){let t=B(i),o=Le(t),r={package_meta:{name:"missing_valuesets",version:De(t)||"0.0.0"},id:i},a=e.resolveVs(n,t)||r,s=a?.id&&!/^[a-zA-Z0-9_-]{20,}$/.test(a.id)?a.id:o;return {kind:"value-set",package:a.package_meta.name,version:a.package_meta.version,name:s,url:t}}function L(e,n,i){let t=i.binding?.bindingName,o=n.join("."),[r,a,s]=t?[{name:"shared",version:"1.0.0"},t,`urn:fhir:binding:${t}`]:[e.package_meta,`${e.name}.${o}_binding`,`${e.url}#${o}_binding`];return {kind:"binding",package:r.name,version:r.version,name:a,url:s}}function _(e,n,i,t){let o=B(i)||i,r=e.resolveVs(n,o);if(r)return we(e,r)}function we(e,n,i){if(n.expansion?.contains)return n.expansion.contains.filter(o=>o.code!==void 0).map(o=>(Ne(o.code),{code:o.code,display:o.display,system:o.system}));let t=[];if(n.compose?.include){for(let o of n.compose.include)if(o.concept)for(let r of o.concept)t.push({system:o.system,code:r.code,display:r.display});else if(o.system&&!o.filter)try{let r=e.resolveAny(o.system);if(r?.concept){let a=(s,c)=>{for(let l of s)t.push({system:c,code:l.code,display:l.display}),l.concept&&a(l.concept,c);};a(r.concept,o.system);}}catch{}}return t.length>0?t:void 0}var ce=100,A=new Set(["code","Coding","CodeableConcept","CodeableReference","Quantity","string","uri","Duration"]);function G(e,n,i,t){if(!i.binding)return;let o=i.binding.strength,r=i.binding.valueSet;if(!r)return;if(!A.has(i.type??"")){t?.dryWarn("#binding",`eld-11: Binding on non-bindable type '${i.type}' (valueSet: ${r})`);return}if(!(o==="required"||o==="extensible"||o==="preferred"))return;let s=_(e,n.package_meta,r);if(!s||s.length===0)return;let c=s.map(l=>l.code).filter(l=>l&&typeof l=="string"&&l.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:o!=="required",values:c}}function Ue(e,n,i,t,o){if(!t.binding?.valueSet)return;let r=L(n,i,t),a=P(e,n.package_meta,t.binding.valueSet),s=G(e,n,t,o);return {identifier:r,valueset:a,strength:t.binding.strength,enum:s,dependencies:[a]}}function le(e,n,i){let t=new Set;if(!n.elements)return [];let o=[];function r(c,l){for(let[d,u]of Object.entries(c)){let h=[...l,d],p=h.join("."),m=e.resolveElementSnapshot(n,h);if(!t.has(p)){if(t.add(p),m.binding){let f=Ue(e,n,h,m,i);f&&o.push(f);}u.elements&&r(u.elements,h);}}}r(n.elements,[]),o.sort((c,l)=>c.identifier.name.localeCompare(l.identifier.name));let a=[],s=new Set;for(let c of o)s.has(c.identifier.url)||(s.add(c.identifier.url),a.push(c));return a}var q=e=>e!==null&&typeof e=="object"&&e.resourceType==="CodeSystem";var N=e=>e!==null&&typeof e=="object"&&e.resourceType==="ValueSet";var $e=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(([o,r])=>({name:o,version:r})):[]},de=e=>({pkg:e,canonicalResolution:{},fhirSchemas:{},valueSets:{}}),me=async(e,n,i,t,o)=>{let r=x(n);if(o?.info(`${" ".repeat(i*2)}+ ${r}`),t[r])return t[r];let a=de(n);for(let c of await e.search({package:n})){let l=c.url;if(!l||!(isStructureDefinition(c)||N(c)||q(c)))continue;let d=l;a.canonicalResolution[d]&&o?.dryWarn("#duplicateCanonical",`Duplicate canonical URL: ${d} at ${r}.`),a.canonicalResolution[d]=[{deep:i,pkg:n,pkgId:r,resource:c}];}let s=await $e(e,n);for(let c of s){let{canonicalResolution:l}=await me(e,c,i+1,t,o);for(let[d,u]of Object.entries(l)){let h=d;a.canonicalResolution[h]=[...a.canonicalResolution[h]||[],...u];}}for(let c of Object.values(a.canonicalResolution))c.sort((l,d)=>l.deep-d.deep);return t[r]=a,a},He=(e,n)=>{for(let{pkg:i,canonicalResolution:t}of Object.values(e)){let o=x(i);if(!e[o])throw new Error(`Package ${o} not found`);let r=0;n?.info(`FHIR Schema conversion for '${x(i)}' begins...`);for(let[a,s]of Object.entries(t)){let c=s[0];if(!c)throw new Error("Resource not found");let l=c.resource,d=c.pkg;if(isStructureDefinition(l)){let u=pe.translate(l),h=ie(u,d);r++,e[o].fhirSchemas[h.url]=h;}if(N(l)){let u=se(l,d);e[o].valueSets[u.url]=u;}}n?.info(`FHIR Schema conversion for '${x(i)}' completed: ${r} successful`);}},Oe=(e,n,i)=>{let t=Object.values(e).flatMap(o=>o.canonicalResolution[n]);if(!t)throw new Error(`No canonical resolution found for ${n} in any package`);return t[0]?.resource},je=async(e,{logger:n,focusedPackages:i})=>{let t=i??await e.packages(),o={};for(let p of t)await me(e,p,0,o,n);He(o,n);let r=(p,m)=>{let f=o[x(p)];if(f){let g=f.canonicalResolution[m]?.[0];if(g)return o[g.pkgId]?.fhirSchemas[m]}for(let g of Object.values(o)){let y=g.fhirSchemas[m];if(y&&y.package_meta.name===p.name)return y}for(let g of Object.values(o)){let y=g.fhirSchemas[m];if(y)return y}},a=(p,m)=>{let f=o[x(p)];if(f){let g=f.canonicalResolution[m]?.[0];if(g)return o[g.pkgId]?.valueSets[m]}for(let g of Object.values(o)){let y=g.valueSets[m];if(y&&y.package_meta.name===p.name)return y}for(let g of Object.values(o)){let y=g.valueSets[m];if(y)return y}},s=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=s(f.base);if(f=r(y,S),f===void 0)throw new Error(`Failed to resolve FHIR Schema base for '${m}'. Problem: '${S}' from '${x(y)}'`);g.push(f);}return g},l=(p,m)=>c(p,m).filter(f=>f.derivation==="specialization"),d=(p,m)=>{let f=c(p.package_meta,p.url),g=U(f,m);return z(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=x(p.package_meta);o[m]||(o[m]=de(p.package_meta)),o[m].fhirSchemas[p.url]=p,h=void 0;},resolveFs:r,resolveFsGenealogy:c,resolveFsSpecializations:l,ensureSpecializationCanonicalUrl:s,resolveSd:(p,m)=>{let f=o[x(p)]?.canonicalResolution[m]?.[0]?.resource;if(isStructureDefinition(f))return f},allSd:()=>Object.values(o).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(o).flatMap(p=>Object.values(p.fhirSchemas)),allVs:()=>Object.values(o).flatMap(p=>Object.values(p.valueSets)),resolveVs:a,resolveAny:p=>Oe(o,p),resolveElementSnapshot:d,getAllElementKeys:u,resolver:o,resolutionTree:()=>{if(h)return h;let p={};for(let[m,f]of Object.entries(o)){let g=f.pkg.name;p[g]={};for(let[y,S]of Object.entries(f.canonicalResolution)){let k=y;p[g][k]=[];for(let R of S)p[g][k].push({deep:R.deep,pkg:R.pkg});}}return h=p,p}}},ue=async(e,n)=>{let i=e.map(te);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 je(t,{...n,focusedPackages:e})},U=(e,n)=>{let[i,...t]=n;return i===void 0?[]:e.map(o=>{if(!o.elements)return;let r=o.elements?.[i];for(let a of t)r=r?.elements?.[a];return r}).filter(o=>o!==void 0)};function z(e){let n=e.reverse(),i=Object.assign({},...n);return i.elements=void 0,i}var fe=(e,n,i)=>{let t=e.resolveFsSpecializations(n.package_meta,n.url),o=U(t,i),r=z(o).type,a;if(r){let s=e.ensureSpecializationCanonicalUrl(r),l=e.resolveFsGenealogy(n.package_meta,s).flatMap(d=>Object.keys(d.elements??{}));l.length>0&&(a=new Set(l));}for(let s of o)if(!(!s.elements||Object.keys(s.elements).length===0)&&!(a&&!Object.keys(s.elements).some(c=>!a.has(c))))return true;return false},W=(e,n,i,t,o)=>t.type==="BackboneElement"?true:!o?.elements||o.choiceOf!==void 0?false:fe(e,n,i),Me=e=>e.elements?new Set(K(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={},o=n.derivation==="constraint"?e.resolveFsSpecializations(n.package_meta,n.url):e.resolveFsGenealogy(n.package_meta,n.url);for(let d of [...o].reverse()){let u=Me(d);for(let h of u)t[h]=`${d.url}#${h}`;}let r=i.join("."),a=t[r]??`${n.url}#${r}`,s=a.split("#")[0],l=e.resolveFs(n.package_meta,s)?.package_meta??n.package_meta;return {kind:"nested",package:l.name,version:l.version,name:r,url:a}}function K(e,n,i){let t=[];for(let[o,r]of Object.entries(i)){let a=[...n,o];r.elements&&r.choiceOf===void 0&&t.push([a,r]),r.elements&&t.push(...K(e,a,r.elements));}return t}function Be(e,n,i,t,o){let r={},a=e.resolveFsGenealogy(n.package_meta,n.url),s=U(a,i),c=new Set;for(let l of s)if(l.elements)for(let d of Object.keys(l.elements))c.add(d);for(let l of c){let d=[...i,l],u=e.resolveElementSnapshot(n,d);W(e,n,d,u,t[l])?r[l]=H(e,n,d,u):r[l]=$(e,n,d,u,o);}return r}function ge(e,n,i){if(!n.elements)return;let t=K(n,[],n.elements).filter(([r,a])=>!a.elements||Object.keys(a.elements).length===0?false:a.type!=="BackboneElement"?fe(e,n,r):true),o=[];for(let[r,a]of t){let s=V(e,n,r),c;a.type==="BackboneElement"||!a.type?c="BackboneElement":c=a.type;let l=e.ensureSpecializationCanonicalUrl(c),d=e.resolveFs(n.package_meta,l);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:l},h=Be(e,n,r,a.elements??{},i),p={identifier:s,base:u,fields:h};o.push(p);}return o.sort((r,a)=>r.identifier.url.localeCompare(a.identifier.url)),o.length===0?void 0:o}function ye(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 he(e,n,i){let t=i[i.length-1];if(!t)throw new Error(`Internal error: fieldName is missing for path ${i.join("/")}`);let o=i.slice(0,-1),r=e.resolveFsGenealogy(n.package_meta,n.url).flatMap(a=>{if(o.length===0)return a.required||[];if(!a.elements)return [];let s=a;for(let c of o)s=s?.elements?.[c];return s?.required||[]});return new Set(r).has(t)}function Se(e,n,i){let t=i[i.length-1];if(!t)throw new Error(`Internal error: fieldName is missing for path ${i.join("/")}`);let o=i.slice(0,-1),r=e.resolveFsGenealogy(n.package_meta,n.url).flatMap(a=>{if(o.length===0)return a.excluded||[];if(!a.elements)return [];let s=a;for(let c of o)s=s?.elements?.[c];return s?.excluded||[]});return new Set(r).has(t)}var _e=(e,n,i)=>{if(i.refers)return i.refers.map(t=>{let o=e.ensureSpecializationCanonicalUrl(t),r=e.resolveFs(n.package_meta,o);if(!r)throw new Error(`Failed to resolve fs for ${o}`);return v(r)})},Ae=e=>{let n=new Set,i=new Set;if(e.required)for(let o of e.required)n.add(o);if(e.excluded)for(let o of e.excluded)i.add(o);if(e.elements)for(let[o,r]of Object.entries(e.elements))r.min!==void 0&&r.min>0&&n.add(o);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}},Ge=e=>!e||typeof e=="object"&&Object.keys(e).length===0,J=(e,n,i)=>{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 o=n[n.length-1];t[o]=i;},qe=(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},xe=(e,n,i,t)=>{if(i>=n.length||!e.elements)return;let o=n[i],r=e.elements[o];if(r){if(i===n.length-1&&r.fixed?.value!==void 0){J(t,n,r.fixed.value);return}if(r.slicing?.slices){let a=n.slice(i+1);for(let s of Object.values(r.slicing.slices)){if(!s.min||s.min<1||!s.match||typeof s.match!="object")continue;let c=s.match;if(Object.keys(c).length!==0)if(a.length>0){let l=qe(c,a);l!==void 0&&J(t,n,l);}else J(t,n.slice(0,i+1),c);}return}xe(r,n,i+1,t);}},ze=(e,n)=>{if(!n?.elements||!e||e.length===0)return;let i={};for(let t of e){let o=t.path.split(".");xe(n,o,0,i);}return Object.keys(i).length>0?i:void 0},ke=e=>{let n=e.slicing;if(!n)return;let i={};for(let[t,o]of Object.entries(n.slices??{})){if(!o)continue;let{required:r,excluded:a,elements:s}=o.schema?Ae(o.schema):{};i[t]={min:o.min,max:o.max,match:Ge(o.match)?ze(n.discriminator??[],o.schema):o.match,required:r,excluded:a,elements:s};}return {discriminator:n.discriminator,rules:n.rules,ordered:n.ordered,slices:Object.keys(i).length>0?i:void 0}};function O(e,n,i,t,o){if(t.elementReference){let r=t.elementReference.slice(1).filter((a,s)=>s%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}>.${i.join(".")}: <${t.type}> (pkg: '${x(n.package_meta)}'))`);return v(a)}else {if(t.choices)return;if(n.derivation==="constraint")return;o?.dryWarn("#fieldTypeNotFound",`Can't recognize element type: <${n.url}>.${i.join(".")} (pkg: '${x(n.package_meta)}'): missing type info`);return}}var $=(e,n,i,t,o,r)=>{let a,s;t.binding&&(a=L(n,i,t),A.has(t.type??"")&&(s=G(e,n,t,o)));let c=O(e,n,i,t,o);c||o?.dryWarn("#fieldTypeNotFound",`Field type not found for '${n.url}#${i.join(".")}' (${n.derivation})`);let l;t.pattern?l={kind:"pattern",type:t.pattern.type,value:t.pattern.value}:t.fixed&&(l={kind:"fixed",type:t.fixed.type,value:t.fixed.value});let d=r??t;if(!l&&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);l={kind:"fixed",type:"CodeableConcept",value:{coding:m.length===1?[m[0]]:m}};}}return {type:c,required:he(e,n,i),excluded:Se(e,n,i),reference:_e(e,n,t),array:t.array||false,min:t.min,max:t.max,slicing:ke(t),choices:t.choices,choiceOf:t.choiceOf,binding:a,enum:s,valueConstraint:l,mustSupport:t.mustSupport}};function H(e,n,i,t){return {type:V(e,n,i),array:t.array||false,required:he(e,n,i),excluded:Se(e,n,i),slicing:ke(t)}}var We=(e,n,i,t)=>{let o=e.resolveFs(n.package_meta,i);if(!o?.elements)return;let r=[];for(let[a,s]of Object.entries(o.elements)){if(s.choiceOf!=="value"&&!a.startsWith("value"))continue;let c=O(e,o,[a],s,t);c&&r.push(c);}return D(r)},Ke=(e,n,i)=>{let t=[];if(!n.elements)return t;for(let[o,r]of Object.entries(n.elements)){if(!o.startsWith("extension:"))continue;let a=o.split(":")[1];if(!a)continue;let s;for(let[c,l]of Object.entries(r.elements??{}))if(!(l.choiceOf!=="value"&&!c.startsWith("value"))&&(s=O(e,n,[o,c],l,i),s))break;t.push({name:a,url:r.url??a,valueType:s,min:r.min,max:r.max!==void 0?String(r.max):void 0});}return t},Je=e=>{let n=[],t=e.elements?.extension?.slicing?.slices;if(!t||typeof t!="object")return n;for(let[o,r]of Object.entries(t)){let a=r,s=a.schema;if(!s)continue;let c;for(let[l,d]of Object.entries(s.elements??{})){let u=d;if(!(u.choiceOf!=="value"&&!l.startsWith("value"))&&u.type){c={kind:"complex-type",package:e.package_meta.name,version:e.package_meta.version,name:u.type,url:`http://hl7.org/fhir/StructureDefinition/${u.type}`};break}}n.push({name:o,url:a.match?.url??o,valueType:c,min:s._required?1:s.min??0,max:s.max!==void 0?String(s.max):s.array?"*":"1"});}return n},Qe=(e,n,i,t)=>{let o=e.resolveFs(n.package_meta,i);if(!o?.elements)return;let r=Ke(e,o,t),a=Je(o),s=[...r,...a];return s.length>0?s:void 0},Re=(e,n,i)=>{let t=[],o=(c,l,d)=>{let u=d.url,h=u?We(e,n,u,i):void 0,p=u?Qe(e,n,u,i):void 0;if(!u){let f=n.elements?.extension?.slicing?.slices?.[l]?.schema;if(f){u=f.elements?.url?.fixed?.value??l;for(let[g,y]of Object.entries(f.elements??{})){let S=y;if(S.choiceOf==="value"&&S.type){h=[{kind:"complex-type",package:n.package_meta.name,version:n.package_meta.version,name:S.type,url:`http://hl7.org/fhir/StructureDefinition/${S.type}`}];break}}}}let m=p&&p.length>0;t.push({name:l,path:[...c,"extension"].join("."),url:u,min:d.min,max:d.max!==void 0?String(d.max):void 0,mustSupport:d.mustSupport,valueTypes:h,subExtensions:p,isComplex:m});},r=(c,l)=>{if(l.extensions)for(let[d,u]of Object.entries(l.extensions))o(c,d,u);if(l.elements)for(let[d,u]of Object.entries(l.elements))r([...c,d],u);};r([],n);let a=new Set,s=t.filter(c=>{let l=`${c.url}:${c.path}`;return a.has(l)?false:(a.add(l),true)});return s.length===0?void 0:s};function Xe(e,n,i,t,o){if(!t)return;let r={};for(let a of e.getAllElementKeys(t)){let s=[...i,a],c=e.resolveElementSnapshot(n,s),l=c.type?e.ensureSpecializationCanonicalUrl(c.type):void 0;if(l&&F(n.package_meta,l).shouldSkip){o?.warn("#skipCanonical",`Skipping field ${s} for ${l} due to skip hack ${F(n.package_meta,l).reason}`);continue}W(e,n,s,c,t[a])?r[a]=H(e,n,s,c):r[a]=$(e,n,s,c,o,t[a]);}return r}function Ye(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 Ce(e,n,i){if(!n.url)throw new Error("ValueSet URL is required");let t=P(e,n.package_meta,n.url),o=_(e,n.package_meta,n.url);return {identifier:t,description:n.description,concept:o,compose:o?void 0:n.compose}}function Ze(e,n,i,t){let o=[];n&&o.push(n),i&&o.push(...Ye(i)),t&&o.push(...ye(t));let r=new Set(t?.map(s=>s.identifier.url)),a=o.filter(s=>s.url===e.url?false:ae(e)||!re(s)?true:!r.has(s.url));return D(a)}function en(e,n,i){let t=v(n),o;if(n.base){let h=e.resolveFs(n.package_meta,e.ensureSpecializationCanonicalUrl(n.base));if(!h)throw new Error(`Base resource not found '${n.base}' for <${n.url}> from ${x(n.package_meta)}`);o=v(h);}let r=Xe(e,n,[],n.elements,i),a=ge(e,n,i),s=n.derivation==="constraint"?Re(e,n,i):void 0,c=s?.flatMap(h=>h.valueTypes??[])??[],l=Ze(t,o,r,a),d={identifier:t,base:o,fields:r,nested:a,description:n.description,dependencies:D(l,c),extensions:s},u=le(e,n,i);return [d,...u]}async function be(e,n,i){return en(e,n,i)}var nn=(e,n)=>{let i={};for(let r of e){let a=`${r.schema.identifier.url}|${r.schema.identifier.package}`,s=oe(r.schema);i[a]??={},i[a][s]??={typeSchema:r.schema,sources:[]},i[a][s].sources.push(r);}let t=[],o={};for(let r of Object.values(i)){let a=Object.values(r).sort((c,l)=>l.sources.length-c.sources.length),s=a[0];if(s&&(t.push(s.typeSchema),a.length>1)){let c=s.typeSchema.identifier.package,l=s.typeSchema.identifier.url;n?.dryWarn("#duplicateSchema",`'${l}' from '${c}' has ${a.length} versions`),o[c]??={},o[c][l]=a.flatMap(d=>d.sources.map(u=>({typeSchema:d.typeSchema,sourcePackage:u.sourcePackage,sourceCanonical:u.sourceCanonical})));}}return {schemas:t,collisions:o}},Ie=async(e,n)=>{let i=[];for(let t of e.allFs()){let o=x(t.package_meta),r=F(t.package_meta,t.url);if(r.shouldSkip){n?.dryWarn("#skipCanonical",`Skip ${t.url} from ${o}. Reason: ${r.reason}`);continue}for(let a of await be(e,t,n))i.push({schema:a,sourcePackage:o,sourceCanonical:t.url});}for(let t of e.allVs())i.push({schema:await Ce(e,t),sourcePackage:x(t.package_meta),sourceCanonical:t.url});return nn(i,n)};var Fe={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 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(),o=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: ${o.map(d=>`${d.name}@${d.version}`).join(", ")}`);let r=await ue(o,{logger:n,registry:e.registry,focusedPackages:o}),{schemas:a}=await Ie(r,n);if(a.length===0)throw new Error("No schemas were generated from the specified packages");let s=e.output;if(!s)throw new Error("Output format not specified");await mkdir(dirname(s),{recursive:!0});let c;i==="json"?c=JSON.stringify(a,null,2):c=a.map(d=>JSON.stringify(d)).join(`
3
+ `),await writeFile(s,c,"utf-8");let l=Date.now()-t;if(ee(`Generated ${a.length} TypeSchema definitions`,l,{schemas:a.length}),n.info(`Output: ${s}`),e.verbose){n.debug("Generated schemas:");let d=a.map(u=>`${u.identifier?.name||"Unknown"} (${u.identifier?.kind||"unknown"})`);I(d);}}catch(i){n.error(`Failed to generate TypeSchema: ${i instanceof Error?i.message:String(i)}`),process.exit(1);}}};var Q=C({prefix:"typeschema"}),ve={command:"typeschema [subcommand]",describe:"TypeSchema operations - generate, validate and merge schemas",builder:e=>e.command(Fe).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){Q.info("Available typeschema subcommands:"),I(["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:`),k(["atomic-codegen typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson","atomic-codegen typeschema validate schemas.ndjson","atomic-codegen typeschema merge schema1.ndjson schema2.ndjson -o merged.ndjson"]);return}t.subcommand&&!["generate","validate","merge"].includes(t.subcommand)&&(R(`Unknown typeschema subcommand: ${t.subcommand}
6
- `),$("Available typeschema subcommands:"),k(["generate Generate TypeSchema files from FHIR packages","validate Validate TypeSchema files for correctness and consistency","merge Merge multiple TypeSchema files into a single file"]),console.log(`
7
- Use 'atomic-codegen typeschema <subcommand> --help' for more information about a subcommand.`),process.exit(1));}};function lt(t){return t?{debug:0,info:1,warn:2,error:3,silent:4}[t.toLowerCase()]:void 0}async function pt(t){let e=lt(t.logLevel);e===void 0&&(t.debug||t.verbose?e=0:e=1),Y({timestamp:t.debug,level:e});}function dt(){return at(hideBin(process.argv)).scriptName("atomic-codegen").usage("$0 <command> [options]").middleware(pt).command(Fe).option("verbose",{alias:"v",type:"boolean",description:"Enable verbose output",default:false,global:true}).option("debug",{alias:"d",type:"boolean",description:"Enable debug output with detailed logging",default:false,global:true}).option("log-level",{alias:"l",type:"string",choices:["debug","info","warn","error","silent"],description:"Set the log level (default: info)",global:true}).demandCommand(0).middleware(t=>{t._.length===0&&(ee("Welcome to Atomic Codegen!"),console.log("Available commands:"),console.log(" typeschema Generate, validate and merge TypeSchema files"),console.log(`
5
+ Examples:`),I(["atomic-codegen typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson","atomic-codegen typeschema validate schemas.ndjson","atomic-codegen typeschema merge schema1.ndjson schema2.ndjson -o merged.ndjson"]);return}e.subcommand&&!["generate","validate","merge"].includes(e.subcommand)&&(Q.error(`Unknown typeschema subcommand: ${e.subcommand}`),Q.info("Available typeschema subcommands:"),I(["generate Generate TypeSchema files from FHIR packages","validate Validate TypeSchema files for correctness and consistency","merge Merge multiple TypeSchema files into a single file"]),console.log(`
6
+ Use 'atomic-codegen typeschema <subcommand> --help' for more information about a subcommand.`),process.exit(1));}};var j=C({prefix:"cli"});async function cn(e){let n=e.logLevel??(e.debug||e.verbose?"DEBUG":"INFO");j=C({prefix:"cli",level:n});}function ln(){return an(hideBin(process.argv)).scriptName("atomic-codegen").usage("$0 <command> [options]").middleware(cn).command(ve).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&&(Z("Welcome to Atomic Codegen!"),console.log("Available commands:"),console.log(" typeschema Generate, validate and merge TypeSchema files"),console.log(`
8
7
  Use 'atomic-codegen <command> --help' for more information about a command.`),console.log(`
9
8
  Quick examples:`),console.log(" atomic-codegen typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson"),console.log(`
10
- Use 'atomic-codegen --help' to see all options.`),process.exit(0));}).help().version("0.1.0").example("$0 typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson","Generate TypeSchemas from FHIR package").fail((t,e,i)=>{e?R(e.message,e):R(t),R(`
11
- Use --help for usage information`),process.exit(1);}).wrap(Math.min(120,process.stdout.columns||80))}async function J(){await dt().parseAsync();}import.meta.main&&J().catch(t=>{t("Unexpected error:",t),process.exit(1);});J().catch(t=>{console.error("CLI Error:",t instanceof Error?t.message:t),process.exit(1);});
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)=>{j.error(n?n.message:e),j.error("Use --help for usage information"),process.exit(1);}).wrap(Math.min(120,process.stdout.columns||80))}async function X(){await ln().parseAsync();}import.meta.main&&X().catch(e=>{j.error(String(e)),process.exit(1);});X().catch(e=>{console.error("CLI Error:",e instanceof Error?e.message:e),process.exit(1);});
package/dist/index.d.ts CHANGED
@@ -2,90 +2,6 @@ import * as FS from '@atomic-ehr/fhirschema';
2
2
  import { FHIRSchema, StructureDefinition as StructureDefinition$1, FHIRSchemaElement } from '@atomic-ehr/fhirschema';
3
3
  import { CanonicalManager, PreprocessContext } from '@atomic-ehr/fhir-canonical-manager';
4
4
 
5
- /**
6
- * CodeGen Logger
7
- *
8
- * Clean, colorful logging designed for code generation tools
9
- */
10
- declare enum LogLevel {
11
- DEBUG = 0,
12
- INFO = 1,
13
- WARN = 2,
14
- ERROR = 3,
15
- SILENT = 4
16
- }
17
- type LogLevelString = keyof typeof LogLevel;
18
- interface LogOptions {
19
- prefix?: string;
20
- timestamp?: boolean;
21
- suppressLoggingLevel?: LogLevel[] | "all";
22
- /** Minimum log level to display. Messages below this level are suppressed. Default: INFO */
23
- level?: LogLevel;
24
- }
25
- /**
26
- * Simple code generation logger with pretty colors and clean formatting
27
- */
28
- declare class CodegenLogger {
29
- private options;
30
- private dryWarnSet;
31
- constructor(options?: LogOptions);
32
- /**
33
- * Check if a message at the given level should be logged
34
- */
35
- private shouldLog;
36
- private static consoleLevelsMap;
37
- private formatMessage;
38
- private isSuppressed;
39
- private tryWriteToConsole;
40
- /**
41
- * Success message with checkmark
42
- */
43
- success(message: string): void;
44
- /**
45
- * Error message with X mark
46
- */
47
- error(message: string, error?: Error): void;
48
- /**
49
- * Warning message with warning sign
50
- */
51
- warn(message: string): void;
52
- dryWarn(message: string): void;
53
- /**
54
- * Info message with info icon
55
- */
56
- info(message: string): void;
57
- /**
58
- * Debug message (only shows when log level is DEBUG or verbose is true)
59
- */
60
- debug(message: string): void;
61
- /**
62
- * Step message with rocket
63
- */
64
- step(message: string): void;
65
- /**
66
- * Progress message with clock
67
- */
68
- progress(message: string): void;
69
- /**
70
- * Plain message (no icon, just colored text)
71
- */
72
- plain(message: string, color?: (str: string) => string): void;
73
- /**
74
- * Dimmed/gray text for less important info
75
- */
76
- dim(message: string): void;
77
- /**
78
- * Create a child logger with a prefix
79
- */
80
- child(prefix: string): CodegenLogger;
81
- /**
82
- * Update options
83
- */
84
- configure(options: Partial<LogOptions>): void;
85
- getLevel(): LogLevel;
86
- setLevel(level: LogLevel): void;
87
- }
88
-
89
5
  interface Extension extends Element {
90
6
  url: string;
91
7
  valueCode?: string;
@@ -752,6 +668,47 @@ interface ValueSet extends DomainResource {
752
668
  version?: string;
753
669
  }
754
670
 
671
+ type LogLevel = "DEBUG" | "INFO" | "WARN" | "ERROR" | "SILENT";
672
+ type LogEntry<T extends string = string> = {
673
+ level: LogLevel;
674
+ tag?: T;
675
+ message: string;
676
+ suppressed: boolean;
677
+ prefix: string;
678
+ timestamp: number;
679
+ };
680
+ type Log<T extends string = string> = {
681
+ warn: TaggedLogFn<T>;
682
+ dryWarn: TaggedLogFn<T>;
683
+ info: TaggedLogFn<T>;
684
+ error: TaggedLogFn<T>;
685
+ debug: TaggedLogFn<T>;
686
+ };
687
+ type LogManager<T extends string = string> = Log<T> & {
688
+ fork(prefix: string, opts?: Partial<LoggerOptions<T>>): LogManager<T>;
689
+ as<Narrower extends string>(): LogManager<Narrower>;
690
+ tagCounts(): Readonly<Record<string, number>>;
691
+ printTagSummary(): void;
692
+ buffer(): readonly LogEntry<T>[];
693
+ bufferClear(): void;
694
+ };
695
+ type TaggedLogFn<T extends string> = (...args: [string] | [T, string]) => void;
696
+ type LoggerOptions<T extends string> = {
697
+ prefix?: string;
698
+ suppressTags?: T[];
699
+ level?: LogLevel;
700
+ };
701
+
702
+ type CodegenTag = "#binding" | "#largeValueSet" | "#fieldTypeNotFound" | "#skipCanonical" | "#duplicateSchema" | "#duplicateCanonical" | "#resolveBase";
703
+ type CodegenLog = Log<CodegenTag>;
704
+ type CodegenLogManager = LogManager<CodegenTag>;
705
+ declare const mkCodegenLogger: (opts?: LoggerOptions<CodegenTag>) => LogManager<CodegenTag>;
706
+
707
+ /**
708
+ * A code generation friendly representation of FHIR StructureDefinition and
709
+ * FHIR Schema designed to simplify SDK resource classes/types generation.
710
+ */
711
+
755
712
  type Name = string & {
756
713
  readonly __brand: unique symbol;
757
714
  };
@@ -832,17 +789,18 @@ type ResolutionTree = Record<PkgName, Record<CanonicalUrl, {
832
789
  pkg: PackageMeta;
833
790
  }[]>>;
834
791
  type RegisterConfig = {
835
- logger?: CodegenLogger;
792
+ logger?: CodegenLog;
836
793
  focusedPackages?: PackageMeta[];
837
794
  /** Custom FHIR package registry URL */
838
795
  registry?: string;
839
796
  };
797
+ declare const registerFromManager: (manager: ReturnType<typeof CanonicalManager>, { logger, focusedPackages }: RegisterConfig) => Promise<Register>;
840
798
  declare const registerFromPackageMetas: (packageMetas: PackageMeta[], conf: RegisterConfig) => Promise<Register>;
841
799
 
842
800
  type FileSystemWriterOptions = {
843
801
  outputDir: string;
844
802
  inMemoryOnly?: boolean;
845
- logger?: CodegenLogger;
803
+ logger?: CodegenLog;
846
804
  resolveAssets?: (fn: string) => string;
847
805
  };
848
806
  type WriterOptions = FileSystemWriterOptions & {
@@ -928,6 +886,7 @@ type FileBasedMustacheGeneratorOptions = {
928
886
  };
929
887
 
930
888
  type TypeScriptOptions = {
889
+ lineWidth?: number;
931
890
  /** openResourceTypeSet -- for resource families (Resource, DomainResource) use open set for resourceType field.
932
891
  *
933
892
  * - when openResourceTypeSet is false: `type Resource = { resourceType: "Resource" | "DomainResource" | "Patient" }`
@@ -935,6 +894,8 @@ type TypeScriptOptions = {
935
894
  */
936
895
  openResourceTypeSet: boolean;
937
896
  primitiveTypeExtension: boolean;
897
+ extensionGetterDefault?: "flat" | "profile" | "raw";
898
+ sliceGetterDefault?: "flat" | "raw";
938
899
  } & WriterOptions;
939
900
 
940
901
  /**
@@ -953,8 +914,6 @@ interface APIBuilderOptions {
953
914
  throwException: boolean;
954
915
  treeShake: TreeShakeConf | undefined;
955
916
  promoteLogical: LogicalPromotionConf | undefined;
956
- /** Log level for the logger. Default: INFO */
957
- logLevel: LogLevel;
958
917
  /** Custom FHIR package registry URL (default: https://fs.get-ig.org/pkgs/) */
959
918
  registry: string | undefined;
960
919
  /** Drop the canonical manager cache */
@@ -991,7 +950,7 @@ declare class APIBuilder {
991
950
  manager?: ReturnType<typeof CanonicalManager>;
992
951
  register?: Register;
993
952
  preprocessPackage?: (context: PreprocessContext) => PreprocessContext;
994
- logger?: CodegenLogger;
953
+ logger?: CodegenLogManager;
995
954
  });
996
955
  fromPackage(packageName: string, version?: string): APIBuilder;
997
956
  fromPackageRef(packageRef: string): APIBuilder;
@@ -1006,7 +965,6 @@ declare class APIBuilder {
1006
965
  * Set the output directory for all generators
1007
966
  */
1008
967
  outputTo(directory: string): APIBuilder;
1009
- setLogLevel(level: LogLevel | LogLevelString): APIBuilder;
1010
968
  throwException(enabled?: boolean): APIBuilder;
1011
969
  cleanOutput(enabled?: boolean): APIBuilder;
1012
970
  typeSchema(cfg: IrConf): this;
@@ -1023,4 +981,4 @@ declare class APIBuilder {
1023
981
  private executeGenerators;
1024
982
  }
1025
983
 
1026
- export { APIBuilder, type APIBuilderOptions, type CSharpGeneratorOptions, type IrConf, type LocalStructureDefinitionConfig, LogLevel, type LogicalPromotionConf, type TreeShakeConf, type TypeScriptOptions, prettyReport, registerFromPackageMetas };
984
+ export { APIBuilder, type APIBuilderOptions, type CSharpGeneratorOptions, type CodegenLog, type CodegenLogManager, type CodegenTag, type IrConf, type LocalStructureDefinitionConfig, type LogLevel, type LogicalPromotionConf, type TreeShakeConf, type TypeScriptOptions, mkCodegenLogger, prettyReport, registerFromManager, registerFromPackageMetas };