Repository: FHIR/sushi (ts)

Issue:
SUSHI drops resource extensions when generating IG JSON
To support "adjunct binary" loading with `Binary` resources, you must add an extension to the resource description in the IG JSON file.  You should be able to do this in sushi-config.yaml, but it seems that the extension is not coming through.

The attached zip (a modified version of an excellent example John Moerke provided), demonstrates the problem.  When you run it through SUSHI, the resulting IG JSON does _not_ have the resource extension in it.  As a result, when you run IG Publisher, the binary example is not processed correctly and has an error in the qa.html.

[testBinary.zip](https://github.com/FHIR/sushi/files/7822530/testBinary.zip)

I expected this to work, as resource extensions are an important part of the logical model examples workflow documented in the [SUSHI 2.2.0 release notes](https://github.com/FHIR/sushi/releases/tag/v2.2.0).

Zulip 1: https://chat.fhir.org/#narrow/stream/215610-shorthand/topic/Binary.20Adjunct/near/266507118
Zulip 2: https://chat.fhir.org/#narrow/stream/215610-shorthand/topic/.22Big.20data.22/near/266809120
Zulip 3: https://chat.fhir.org/#narrow/stream/179252-IG-creation/topic/binary.20resources/near/264207318


Pull request description:
Include configured extensions on resources
Fixes #1005 

This PR adds support for using the configured extensions when creating the `definition.resource` entries. This resolves the bug because the extensions weren't getting dropped, but instead were just never carried over. The reason this worked with the Logical Model examples is because they are never defined in FSH but are only provided as a JSON/XML resource and added to the sushi-config.yaml file. Now, if you do have FSH defined examples and provide any extensions in sushi-config.yaml, it will be carried over to the generated IG resource.

I this this is an appropriate way to solve this bug because it looks like it follows the pattern that is used for every other property on the `resource` entry, but if this doesn't line up with others' understanding of how we generate the IG resource or the `definition.resource` list, let me know.

Also, I'm running the full regression now ~and will update here if it looks good!~ Edit: It looks good!

Patch:
diff --git a/src/ig/IGExporter.ts b/src/ig/IGExporter.ts
index 6137b3b..876c876 100644
--- a/src/ig/IGExporter.ts
+++ b/src/ig/IGExporter.ts
@@ -748,6 +748,9 @@ export class IGExporter {
         } else {
           newResource.exampleBoolean = false;
         }
+        if (configResource?.extension?.length) {
+          newResource.extension = configResource.extension;
+        }
         this.ig.definition.resource.push(newResource);
       }
     });
@@ -798,6 +801,9 @@ export class IGExporter {
               newResource.exampleBoolean = false;
             }
           }
+          if (configResource?.extension?.length) {
+            newResource.extension = configResource.extension;
+          }
           this.ig.definition.resource.push(newResource);
         }
       });
@@ -940,6 +946,9 @@ export class IGExporter {
                   name ??
                   resourceJSON.id;
               }
+              if (configResource?.extension?.length) {
+                newResource.extension = configResource.extension;
+              }
 
               if (existingIndex >= 0) {
                 this.ig.definition.resource[existingIndex] = newResource;


Test patch:
diff --git a/test/ig/IGExporter.IG.test.ts b/test/ig/IGExporter.IG.test.ts
index 98f0de9..2ae03ce 100644
--- a/test/ig/IGExporter.IG.test.ts
+++ b/test/ig/IGExporter.IG.test.ts
@@ -110,6 +110,27 @@ describe('IGExporter', () => {
             version: '1.0.0'
           }
         ],
+        resources: [
+          {
+            reference: { reference: 'Patient/patient-example' },
+            name: 'Patient Example',
+            extension: [
+              {
+                url: 'http://hl7.org/fhir/StructureDefinition/implementationguide-resource-format',
+                valueCode: 'text/plain'
+              }
+            ]
+          },
+          {
+            reference: { reference: 'StructureDefinition/sample-patient' },
+            extension: [
+              {
+                url: 'http://hl7.org/fhir/StructureDefinition/implementationguide-resource-format',
+                valueCode: 'text/plain'
+              }
+            ]
+          }
+        ],
         status: 'active',
         fhirVersion: ['4.0.1'],
         language: 'en',
@@ -224,6 +245,13 @@ describe('IGExporter', () => {
               reference: {
                 reference: 'StructureDefinition/sample-patient'
               },
+              extension: [
+                // Extension is added from config
+                {
+                  url: 'http://hl7.org/fhir/StructureDefinition/implementationguide-resource-format',
+                  valueCode: 'text/plain'
+                }
+              ],
               name: 'SamplePatient',
               description:
                 'Demographics and other administrative information about an individual or animal receiving care or other health-related services.',
@@ -266,7 +294,14 @@ describe('IGExporter', () => {
               reference: {
                 reference: 'Patient/patient-example'
               },
-              name: 'patient-example',
+              name: 'Patient Example', // Name from config overrides _instanceMeta.name
+              extension: [
+                // Extension is added from config
+                {
+                  url: 'http://hl7.org/fhir/StructureDefinition/implementationguide-resource-format',
+                  valueCode: 'text/plain'
+                }
+              ],
               exampleBoolean: true // No defined Usage on FSH file sets this to true
             },
             {
@@ -1188,6 +1223,17 @@ describe('IGExporter', () => {
       loggerSpy.reset();
       tempOut = temp.mkdirSync('sushi-test');
       config = cloneDeep(minimalConfig);
+      config.resources = [
+        {
+          reference: { reference: 'Patient/BazPatient' },
+          extension: [
+            {
+              url: 'http://hl7.org/fhir/StructureDefinition/implementationguide-resource-format',
+              valueCode: 'text/plain'
+            }
+          ]
+        }
+      ];
       pkg = new Package(config);
       // Add a patient to the package that will be overwritten
       const fisher = new TestFisher(null, defs, pkg);
@@ -1262,6 +1308,12 @@ describe('IGExporter', () => {
           reference: 'Patient/BazPatient'
         },
         name: 'BazPatient',
+        extension: [
+          {
+            url: 'http://hl7.org/fhir/StructureDefinition/implementationguide-resource-format',
+            valueCode: 'text/plain'
+          }
+        ],
         exampleBoolean: false
       });
       expect(igContent.definition.resource).toContainEqual({