UNPKG

fhir-package-explorer

Version:

Explore and resolve FHIR conformance resources across package contexts

1 lines 8.34 kB
import*as e from"fhir-package-installer";import{createRequire as t}from"module";import*as r from"fs-extra";var i={};(()=>{i.n=e=>{var t=e&&e.__esModule?()=>e["default"]:()=>e;i.d(t,{a:t});return t}})();(()=>{i.d=(e,t)=>{for(var r in t){if(i.o(t,r)&&!i.o(e,r)){Object.defineProperty(e,r,{enumerable:true,get:t[r]})}}}})();(()=>{i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t)})();if(typeof i!=="undefined")i.ab=new URL(".",import.meta.url).pathname.slice(import.meta.url.match(/^file:\/\/\/\w:/)?1:0,-1)+"/";var a={};i.d(a,{Z:()=>FhirPackageExplorer});var x=e=>{var t={};i.d(t,e);return t};var y=e=>()=>e;const s=x({["FhirPackageInstaller"]:()=>e.FhirPackageInstaller});const n=t(import.meta.url)("path");var o=i.n(n);var external_fs_extra_x=e=>{var t={};i.d(t,e);return t};var external_fs_extra_y=e=>()=>e;const c=external_fs_extra_x({["default"]:()=>r["default"]});const sortPackages=e=>e.slice().sort(((e,t)=>{const r=`${e.id}@${e.version}`;const i=`${t.id}@${t.version}`;return r<i?-1:r>i?1:0}));const normalizePipedFilter=e=>{const t={...e};const r=["url","name","id"];for(const i of r){const r=e[i];if(typeof r==="string"&&r.includes("|")){const[e,a]=r.split("|");t[i]=e;t.version=a;break}}return t};const matchesFilter=(e,t)=>{for(const[r,i]of Object.entries(t)){if(r==="package")continue;if(e[r]!==i)return false}return true};const prethrow=e=>{if(e instanceof Error){return e}const t=new Error(e);return t};const tryResolveDuplicates=async(e,t,r)=>{if(t.package){const i=await r.toPackageObject(t.package);const a=e.filter((e=>e.__packageId===i.id&&e.__packageVersion===i.version));if(a.length===1)return a}const i=new Map;for(const t of e){const e=t.__packageId;const r=t.version;if(!r||!/^\d+\.\d+\.\d+(-[\w.-]+)?$/.test(r))return[];if(!i.has(e))i.set(e,[]);i.get(e).push(r)}if(i.size!==1)return[];const[a,s]=Array.from(i.entries())[0];function compareSemver(e,t){const parse=e=>{const[t]=e.split("-");const[r,i,a]=t.split(".").map(Number);return{major:r,minor:i,patch:a}};const r=parse(e);const i=parse(t);if(r.major!==i.major)return r.major-i.major;if(r.minor!==i.minor)return r.minor-i.minor;if(r.patch!==i.patch)return r.patch-i.patch;return 0}const n=s.slice().sort(compareSemver).pop();return e.filter((e=>e.__packageId===a&&e.version===n))};const loadJson=async e=>await c["default"].readJson(e);const getAllFastIndexKeys=e=>{const{__packageId:t,__packageVersion:r,resourceType:i,url:a,id:s,name:n,version:o,derivation:c}=e;const h=[];if(t&&r&&i&&s&&c)h.push(`pkg:${t}#${r}|resourceType:${i}|id:${s}|derivation:${c}`);if(t&&r&&i&&a)h.push(`pkg:${t}#${r}|resourceType:${i}|url:${a}`);if(i&&a&&o)h.push(`resourceType:${i}|url:${a}|version:${o}`);if(i&&a)h.push(`resourceType:${i}|url:${a}`);if(a&&o)h.push(`url:${a}|version:${o}`);if(a)h.push(`url:${a}`);if(i&&n&&o)h.push(`resourceType:${i}|name:${n}|version:${o}`);if(i&&s&&o)h.push(`resourceType:${i}|id:${s}|version:${o}`);if(i&&n)h.push(`resourceType:${i}|name:${n}`);if(i&&s)h.push(`resourceType:${i}|id:${s}`);return h};class FhirPackageExplorer{static async create(e){const t=new FhirPackageExplorer(e);try{await t._loadContext(e.context);return t}catch(e){t.logger.error("Error loading context packages");throw t.prethrow(e)}}constructor(e){this.indexCache=new Map;this.contentCache=new Map;this.fastIndex=new Map;this.contextPackages=[];this.skipExamples=false;this.prethrow=prethrow;const{logger:t,registryUrl:r,cachePath:i,skipExamples:a}=e||{};this.fpi=new s.FhirPackageInstaller({logger:t,registryUrl:r,cachePath:i,skipExamples:a});this.logger=this.fpi.getLogger();if(this.logger)this.prethrow=e=>{if(!(e instanceof Error)){e=new Error(e)}this.logger.error(e.message);this.logger.error(JSON.stringify(e,null,2));return e};this.cachePath=this.fpi.getCachePath();if(a)this.skipExamples=a}getCachePath(){return this.cachePath}getLogger(){return this.logger}getContextPackages(){return this.contextPackages}async getDirectDependencies(e){try{const t=typeof e==="string"?await this.fpi.toPackageObject(e):e;const r=await this.fpi.getDependencies(t);return Object.entries(r).map((([e,t])=>({id:e,version:t})))}catch(t){this.logger.error(`Error reading package dependencies for ${String(e)}`);throw this.prethrow(t)}}async expandPackageDependencies(e){try{const t=typeof e==="string"?await this.fpi.toPackageObject(e):e;const r=Array.from(await this._collectDependencies(t));return sortPackages(await Promise.all(r.map((async e=>await this.fpi.toPackageObject(e)))))}catch(t){this.logger.error(`Error expanding package dependencies for ${String(e)}`);throw this.prethrow(t)}}async lookup(e={}){try{const t=await this.lookupMeta(e);const r=await Promise.all(t.map((async e=>{const t=await this._getFilePath(e);if(this.contentCache.has(t))return this.contentCache.get(t);const r=await loadJson(t);const i={__packageId:e.__packageId,__packageVersion:e.__packageVersion,__filename:e.filename,...r};this.contentCache.set(t,i);return i})));return r}catch(t){this.logger.error(`Error looking up resources with filter: ${JSON.stringify(e)}`);throw this.prethrow(t)}}async lookupMeta(e={}){try{const t=normalizePipedFilter(e);const r=this.contextPackages;let i=undefined;if(t.package){const e=await this.fpi.toPackageObject(t.package);i=await this._collectDependencies(e)}const a=new Map;for(const e of r){const r=`${e.id}#${e.version}`;if(i&&!i.has(r))continue;let s=this.indexCache.get(r);if(!s){await this.fpi.install(e);const t=await this.fpi.getPackageIndexFile(e);const i=t.files??[];s=i.map((t=>({...t,__packageId:e.id,__packageVersion:e.version})));this.indexCache.set(r,s);this._buildFastIndex(s)}const n=getAllFastIndexKeys(t);const o=n.flatMap((e=>this.fastIndex.get(e)??[]));const c=o.length>0?o:s;for(const e of c){const r=`${e.__packageId}#${e.__packageVersion}`;if(i&&!i.has(r))continue;if(!matchesFilter(e,t))continue;const s=`${e.filename}|${e.__packageId}|${e.__packageVersion}`;if(!a.has(s)){a.set(s,e)}}}return Array.from(a.values())}catch(t){this.logger.error(`Error looking up metadata with filter: ${JSON.stringify(e)}`);throw this.prethrow(t)}}async resolve(e={}){try{const t=await this.lookup(e);if(t.length===0)throw new Error(`No matching resource found with filter: ${JSON.stringify(e)}`);if(t.length>1){const r=await tryResolveDuplicates(t,e,this.fpi);if(r.length!==1)throw new Error(`Multiple matching resources found with filter: ${JSON.stringify(e)}`);return r[0]}return t[0]}catch(t){throw this.prethrow(`Error resolving resource with filter: ${JSON.stringify(e)}. Error: ${t instanceof Error?t.message:String(t)}`)}}async resolveMeta(e={}){try{const t=await this.lookupMeta(e);if(t.length===0)throw new Error(`No matching resource found with filter: ${JSON.stringify(e)}`);if(t.length>1){const r=await tryResolveDuplicates(t,e,this.fpi);if(r.length!==1)throw new Error(`Multiple matching resources found with filter: ${JSON.stringify(e)}`);return r[0]}return t[0]}catch(t){throw this.prethrow(`Error resolving metadata with filter: ${JSON.stringify(e)}. Error: ${t instanceof Error?t.message:String(t)}`)}}async getPackageManifest(e){try{const t=await this.fpi.getManifest(e);if(!t)throw new Error(`Failed to fetch manifest (package.json) for package: ${String(e)}`);return t}catch(e){throw this.prethrow(e)}}async _loadContext(e){const t=[];for(const r of e){const e=await this.fpi.toPackageObject(r);await this.fpi.install(e);t.push(e);const i=await this.fpi.getDependencies(e);for(const[e,r]of Object.entries(i||{})){const i={id:e,version:r};if(this.skipExamples&&i.id.includes("examples"))continue;await this.fpi.install(i);t.push(i)}}const r=new Map;for(const e of t)r.set(`${e.id}#${e.version}`,e);this.contextPackages=sortPackages(Array.from(r.values()))}async _collectDependencies(e){const t=new Set;const visit=async e=>{const r=`${e.id}#${e.version}`;if(t.has(r))return;t.add(r);const i=await this.fpi.getDependencies(e);for(const[e,t]of Object.entries(i||{})){if(this.skipExamples&&e.includes("examples"))continue;await visit({id:e,version:t})}};await visit(e);return t}async _getFilePath(e){const t=await this.fpi.getPackageDirPath({id:e.__packageId,version:e.__packageVersion});return o().join(t,"package",e.filename)}_buildFastIndex(e){for(const t of e){for(const e of getAllFastIndexKeys(t)){if(!this.fastIndex.has(e))this.fastIndex.set(e,[]);this.fastIndex.get(e).push(t)}}}}var h=a.Z;export{h as FhirPackageExplorer};