Repository: FHIR/sushi
Pull request #1247 (2023-03-27 20:27:20)

Change hl7.fhir.uv.extensions autoload to use 'latest' version (v2.x)
With the release of FHIR R5, the `hl7.fhir.uv.extensions` package got its first official release (1.0.0). As per [this conversation](https://chat.fhir.org/#narrow/stream/179239-tooling/topic/New.20Implicit.20Package/near/327872896), SUSHI and IG Publisher should automatically load the _latest published_ version of `hl7.fhir.uv.extensions`. Prior to this PR, we autoloaded the `current` version instead.

Note that I needed to enhance the logic for detecting `latest` so that it will fall back to `packages2.fhir.org` if there is no manifest for the package on `packages.fhir.org` (which is the case for `hl7.fhir.uv.extensions`).

To test this manually, create an R5 IG. When you run the `v2.x` branch, you'll see it pull down the `current` version of `hl7.fhir.uv.extensions`.  When you run this PR branch, you should see it pull down version `1.0.0` instead.

Implements [CIMPL-1083](https://standardhealthrecord.atlassian.net/browse/CIMPL-1083).




Patch:
diff --git a/src/utils/Processing.ts b/src/utils/Processing.ts
index b7817a2..4f2811c 100644
--- a/src/utils/Processing.ts
+++ b/src/utils/Processing.ts
@@ -19,6 +19,7 @@ import { Package } from '../export';
 import { Configuration } from '../fshtypes';
 import { axiosGet } from './axiosUtils';
 import { ImplementationGuideDependsOn } from '../fhirtypes';
+import { AxiosResponse } from 'axios';
 
 const EXT_PKG_TO_FHIR_PKG_MAP: { [key: string]: string } = {
   'hl7.fhir.extensions.r2': 'hl7.fhir.r2.core#1.0.2',
@@ -54,8 +55,11 @@ export const AUTOMATIC_DEPENDENCIES: AutomaticDependency[] = [
     version: 'latest'
   },
   {
+    // Right now, auto-load the extensions package for R5 only. In the future, we'll do this for R4 as well, but as
+    // of 3/27/2023, the rules for resolution in R4 have not yet been determined.
+    // See: https://chat.fhir.org/#narrow/stream/179239-tooling/topic/New.20Implicit.20Package/near/344938535
     packageId: 'hl7.fhir.uv.extensions',
-    version: 'current',
+    version: 'latest',
     fhirVersion: /^5\.0\.0(-draft-final)?$/
   }
 ];
@@ -256,9 +260,20 @@ export async function loadAutomaticDependencies(
         if (dep.version === 'latest') {
           // clone it before we modify it so we don't overwrite the global (mostly helpful for testing)
           dep = cloneDeep(dep);
-          const res = await axiosGet(`https://packages.fhir.org/${dep.packageId}`, {
-            responseType: 'json'
-          });
+          let res: AxiosResponse;
+          try {
+            res = await axiosGet(`https://packages.fhir.org/${dep.packageId}`, {
+              responseType: 'json'
+            });
+          } catch (e) {
+            // Fallback to trying packages2.fhir.org
+            res = await axiosGet(`https://packages2.fhir.org/packages/${dep.packageId}`, {
+              responseType: 'json'
+            }).catch(() => {
+              // If the fallback failed too, just throw the original error
+              throw e;
+            });
+          }
           if (res?.data?.['dist-tags']?.latest?.length) {
             dep.version = res.data['dist-tags'].latest;
           } else {


Test patch:
diff --git a/test/utils/Processing.test.ts b/test/utils/Processing.test.ts
index 8b3fdc2..6f723a8 100644
--- a/test/utils/Processing.test.ts
+++ b/test/utils/Processing.test.ts
@@ -51,6 +51,7 @@ import { EOL } from 'os';
 const NUM_R4_AUTO_DEPENDENCIES = 2;
 const NUM_R5_AUTO_DEPENDENCIES = 3;
 
+// Represents a typical response from packages.fhir.org
 const TERM_PKG_RESPONSE = {
   _id: 'hl7.terminology.r4',
   name: 'hl7.terminology.r4',
@@ -70,6 +71,26 @@ const TERM_PKG_RESPONSE = {
   }
 };
 
+// Represents a typical response from packages2.fhir.org (note: not on packages.fhir.org)
+const EXT_PKG_RESPONSE = {
+  _id: 'hl7.fhir.uv.extensions',
+  name: 'hl7.fhir.uv.extensions',
+  'dist-tags': { latest: '4.5.6-test' },
+  versions: {
+    '4.5.6-test': {
+      name: 'hl7.fhir.uv.extensions',
+      date: '2023-03-26T08:46:31-00:00',
+      version: '1.0.0',
+      fhirVersion: '??',
+      kind: '??',
+      count: '18',
+      canonical: 'http://hl7.org/fhir/extensions',
+      description: 'None',
+      url: 'https://packages2.fhir.org/packages/hl7.fhir.uv.extensions/4.5.6-test'
+    }
+  }
+};
+
 describe('Processing', () => {
   temp.track();
   let termNockScope: nock.Interceptor;
@@ -77,6 +98,14 @@ describe('Processing', () => {
   beforeEach(() => {
     termNockScope = nock('https://packages.fhir.org').persist().get('/hl7.terminology.r4');
     termNockScope.reply(200, TERM_PKG_RESPONSE);
+    nock('https://packages.fhir.org')
+      .persist()
+      .get('/hl7.fhir.uv.extensions')
+      .reply(404, 'Status Code: 404; Not Found');
+    nock('https://packages2.fhir.org')
+      .persist()
+      .get('/packages/hl7.fhir.uv.extensions')
+      .reply(200, EXT_PKG_RESPONSE);
   });
 
   afterEach(() => {
@@ -525,7 +554,7 @@ describe('Processing', () => {
         expect(defs.packages).toContain('hl7.fhir.r5.core#5.0.0');
         expect(defs.packages).toContain('hl7.fhir.uv.tools#current');
         expect(defs.packages).toContain('hl7.terminology.r4#1.2.3-test');
-        expect(defs.packages).toContain('hl7.fhir.uv.extensions#current');
+        expect(defs.packages).toContain('hl7.fhir.uv.extensions#4.5.6-test');
         expect(loggerSpy.getAllLogs('warn')).toHaveLength(0);
       });
     });
@@ -737,7 +766,7 @@ describe('Processing', () => {
         expect(defs.packages).toHaveLength(3);
         expect(defs.packages).toContain('hl7.fhir.uv.tools#current');
         expect(defs.packages).toContain('hl7.terminology.r4#1.2.3-test');
-        expect(defs.packages).toContain('hl7.fhir.uv.extensions#current');
+        expect(defs.packages).toContain('hl7.fhir.uv.extensions#4.5.6-test');
         expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
       });
     });
@@ -756,7 +785,7 @@ describe('Processing', () => {
         expect(defs.packages).toHaveLength(3);
         expect(defs.packages).toContain('hl7.fhir.uv.tools#current');
         expect(defs.packages).toContain('hl7.terminology.r4#1.2.3-test');
-        expect(defs.packages).toContain('hl7.fhir.uv.extensions#current');
+        expect(defs.packages).toContain('hl7.fhir.uv.extensions#4.5.6-test');
         expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
       });
     });