Skip to content

Commit

Permalink
Set version based on configuration in FSHOnly (#1456)
Browse files Browse the repository at this point in the history
  • Loading branch information
jafeltra authored Apr 18, 2024
1 parent 99bf99b commit 28c325f
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 4 deletions.
6 changes: 5 additions & 1 deletion src/export/CodeSystemExporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ export class CodeSystemExporter {
}
if (fshDefinition.title) codeSystem.title = fshDefinition.title;
if (fshDefinition.description) codeSystem.description = fshDefinition.description;
delete codeSystem.version; // deleting to allow the IG Publisher default to take hold
if (this.tank.config.FSHOnly) {
codeSystem.version = this.tank.config.version;
} else {
delete codeSystem.version; // deleting to allow the IG Publisher default to take hold
}
codeSystem.status = this.tank.config.status;
codeSystem.url = `${this.tank.config.canonical}/CodeSystem/${codeSystem.id}`;
}
Expand Down
6 changes: 5 additions & 1 deletion src/export/StructureDefinitionExporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,11 @@ export class StructureDefinitionExporter implements Fishable {
delete structDef.title;
}
structDef.status = this.tank.config.status;
delete structDef.version; // deleting to allow the IG Publisher default to take hold
if (this.tank.config.FSHOnly) {
structDef.version = this.tank.config.version;
} else {
delete structDef.version; // deleting to allow the IG Publisher default to take hold
}
delete structDef.experimental;
delete structDef.date;
delete structDef.publisher;
Expand Down
6 changes: 5 additions & 1 deletion src/export/ValueSetExporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@ export class ValueSetExporter {
if (fshDefinition.description) {
valueSet.description = fshDefinition.description;
}
delete valueSet.version; // deleting to allow the IG Publisher default to take hold
if (this.tank.config.FSHOnly) {
valueSet.version = this.tank.config.version;
} else {
delete valueSet.version; // deleting to allow the IG Publisher default to take hold
}
valueSet.status = this.tank.config.status;
valueSet.url = `${this.tank.config.canonical}/ValueSet/${valueSet.id}`;
}
Expand Down
1 change: 1 addition & 0 deletions src/import/importConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const MINIMAL_IG_ONLY_PROPERTIES = ['id', 'name', 'status', 'copyrightYear', 're
const ALLOWED_FSH_ONLY_PROPERTIES = [
...MINIMAL_CONFIG_PROPERTIES,
'version',
'status',
'dependencies',
'instanceOptions',
'applyExtensionMetadataToRoot',
Expand Down
28 changes: 28 additions & 0 deletions test/export/CodeSystemExporter.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { loadFromPath } from 'fhir-package-loader';
import path from 'path';
import { cloneDeep } from 'lodash';
import { CodeSystemExporter, Package } from '../../src/export';
import { FSHDocument, FSHTank } from '../../src/import';
import { FshCodeSystem, FshCode, RuleSet, Instance } from '../../src/fshtypes';
Expand Down Expand Up @@ -89,6 +90,33 @@ describe('CodeSystemExporter', () => {
});
});

it('should export a code system with status and version in FSHOnly mode', () => {
// Create a FSHOnly config with a status and version
const fshOnlyConfig = cloneDeep(minimalConfig);
fshOnlyConfig.FSHOnly = true;
fshOnlyConfig.version = '0.1.0';
fshOnlyConfig.status = 'active';
const input = new FSHTank([doc], fshOnlyConfig);
pkg = new Package(input.config);
const fisher = new TestFisher(input, defs, pkg);
exporter = new CodeSystemExporter(input, pkg, fisher);

const codeSystem = new FshCodeSystem('MyCodeSystem');
codeSystem.id = 'CodeSystem1';
doc.codeSystems.set(codeSystem.name, codeSystem);
const exported = exporter.export().codeSystems;
expect(exported.length).toBe(1);
expect(exported[0]).toEqual({
resourceType: 'CodeSystem',
name: 'MyCodeSystem',
id: 'CodeSystem1',
status: 'active',
version: '0.1.0',
content: 'complete',
url: 'http://hl7.org/fhir/us/minimal/CodeSystem/CodeSystem1'
});
});

it('should export each code system once, even if export is called more than once', () => {
const codeSystem = new FshCodeSystem('MyCodeSystem');
doc.codeSystems.set(codeSystem.name, codeSystem);
Expand Down
100 changes: 100 additions & 0 deletions test/export/StructureDefinitionExporter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
StructureDefinitionMapping
} from '../../src/fhirtypes';
import path from 'path';
import { cloneDeep } from 'lodash';
import { withDebugLogging } from '../testhelpers/withDebugLogging';
import { minimalConfig } from '../utils/minimalConfig';
import { ValidationError } from '../../src/errors';
Expand Down Expand Up @@ -800,6 +801,33 @@ describe('StructureDefinitionExporter R4', () => {
expect(exported.url).toBe('http://hl7.org/fhir/us/minimal/StructureDefinition/foo');
expect(exported.type).toBe('Observation');
expect(exported.baseDefinition).toBe('http://hl7.org/fhir/StructureDefinition/Observation');
expect(exported.version).toBeUndefined();
expect(exported.status).toBe('draft');
});

it('should set status and version metadata for a profile in FSHOnly mode', () => {
// Create a FSHOnly config with a status and version
const fshOnlyConfig = cloneDeep(minimalConfig);
fshOnlyConfig.FSHOnly = true;
fshOnlyConfig.version = '0.1.0';
fshOnlyConfig.status = 'active';
const input = new FSHTank([doc], fshOnlyConfig);
pkg = new Package(input.config);
const fisher = new TestFisher(input, defs, pkg);
exporter = new StructureDefinitionExporter(input, pkg, fisher);

const profile = new Profile('Foo');
profile.id = 'foo';
profile.parent = 'Observation';
doc.profiles.set(profile.name, profile);
exporter.exportStructDef(profile);
const exported = pkg.profiles[0];
expect(exported.name).toBe('Foo');
expect(exported.id).toBe('foo');
expect(exported.type).toBe('Observation');
expect(exported.baseDefinition).toBe('http://hl7.org/fhir/StructureDefinition/Observation');
expect(exported.version).toBe('0.1.0');
expect(exported.status).toBe('active');
});

it('should properly set/clear all metadata properties for a profile', () => {
Expand All @@ -822,6 +850,7 @@ describe('StructureDefinitionExporter R4', () => {
expect(exported.name).toBe('Foo'); // provided by user
expect(exported.title).toBeUndefined();
expect(exported.status).toBe('draft'); // always draft
expect(exported.version).toBeUndefined();
expect(exported.experimental).toBeUndefined();
expect(exported.date).toBeUndefined();
expect(exported.publisher).toBeUndefined();
Expand Down Expand Up @@ -1191,6 +1220,8 @@ describe('StructureDefinitionExporter R4', () => {
expect(exported.description).toBe('foo bar foobar');
expect(exported.elements[0].definition).toBe('foo bar foobar');
expect(exported.url).toBe('http://hl7.org/fhir/us/minimal/StructureDefinition/foo');
expect(exported.status).toBe('draft');
expect(exported.version).toBeUndefined();
expect(exported.type).toBe('Extension');
expect(exported.baseDefinition).toBe('http://hl7.org/fhir/StructureDefinition/Extension');
expect(exported.context).toEqual([
Expand All @@ -1214,6 +1245,28 @@ describe('StructureDefinitionExporter R4', () => {
);
});

it('should set status and version metadata for an extension in FSHOnly mode', () => {
// Create a FSHOnly config with a status and version
const fshOnlyConfig = cloneDeep(minimalConfig);
fshOnlyConfig.FSHOnly = true;
fshOnlyConfig.version = '0.1.0';
fshOnlyConfig.status = 'active';
const input = new FSHTank([doc], fshOnlyConfig);
pkg = new Package(input.config);
const fisher = new TestFisher(input, defs, pkg);
exporter = new StructureDefinitionExporter(input, pkg, fisher);

const extension = new Extension('Foo');
extension.id = 'foo';
doc.extensions.set(extension.name, extension);
exporter.exportStructDef(extension);
const exported = pkg.extensions[0];
expect(exported.name).toBe('Foo');
expect(exported.id).toBe('foo');
expect(exported.version).toBe('0.1.0');
expect(exported.status).toBe('active');
});

it('should not set metadata on the root element when applyExtensionMetadataToRoot is false', () => {
const config: Configuration = { ...minimalConfig, applyExtensionMetadataToRoot: false };
const tank = new FSHTank([doc], config);
Expand Down Expand Up @@ -1512,11 +1565,35 @@ describe('StructureDefinitionExporter R4', () => {
expect(exported.id).toBe('foo');
expect(exported.title).toBe('Logical Foo Model');
expect(exported.description).toBe('foo bar foobar');
expect(exported.status).toBe('draft');
expect(exported.version).toBeUndefined();
expect(exported.url).toBe('http://hl7.org/fhir/us/minimal/StructureDefinition/foo');
expect(exported.type).toBe('http://hl7.org/fhir/us/minimal/StructureDefinition/foo');
expect(exported.baseDefinition).toBe('http://hl7.org/fhir/StructureDefinition/Base');
});

it('should set status and version metadata for a logical model in FSHOnly mode', () => {
// Create a FSHOnly config with a status and version
const fshOnlyConfig = cloneDeep(minimalConfig);
fshOnlyConfig.FSHOnly = true;
fshOnlyConfig.version = '0.1.0';
fshOnlyConfig.status = 'active';
const input = new FSHTank([doc], fshOnlyConfig);
pkg = new Package(input.config);
const fisher = new TestFisher(input, defs, pkg);
exporter = new StructureDefinitionExporter(input, pkg, fisher);

const logical = new Logical('Foo');
logical.id = 'foo';
doc.logicals.set(logical.name, logical);
exporter.exportStructDef(logical);
const exported = pkg.logicals[0];
expect(exported.name).toBe('Foo');
expect(exported.id).toBe('foo');
expect(exported.version).toBe('0.1.0');
expect(exported.status).toBe('active');
});

it('should properly set/clear all metadata properties for a logical model', () => {
const logical = new Logical('Foo');
logical.parent = 'AlternateIdentification';
Expand Down Expand Up @@ -1851,13 +1928,36 @@ describe('StructureDefinitionExporter R4', () => {
expect(exported.title).toBe('Custom Foo Resource');
expect(exported.description).toBe('foo bar foobar');
expect(exported.url).toBe('http://hl7.org/fhir/us/minimal/StructureDefinition/foo');
expect(exported.status).toBe('draft');
expect(exported.version).toBeUndefined();
expect(exported.type).toBe('foo');
expect(exported.baseDefinition).toBe(
'http://hl7.org/fhir/StructureDefinition/DomainResource'
);
});

it('should set status and version metadata for a resource in FSHOnly mode', () => {
// Create a FSHOnly config with a status and version
const fshOnlyConfig = cloneDeep(minimalConfig);
fshOnlyConfig.FSHOnly = true;
fshOnlyConfig.version = '0.1.0';
fshOnlyConfig.status = 'active';
const input = new FSHTank([doc], fshOnlyConfig);
pkg = new Package(input.config);
const fisher = new TestFisher(input, defs, pkg);
exporter = new StructureDefinitionExporter(input, pkg, fisher);

const resource = new Resource('Foo');
resource.id = 'foo';
doc.resources.set(resource.name, resource);
exporter.exportStructDef(resource);
const exported = pkg.resources[0];
expect(exported.name).toBe('Foo');
expect(exported.id).toBe('foo');
expect(exported.version).toBe('0.1.0');
expect(exported.status).toBe('active');
});

it('should properly set/clear all metadata properties for a resource', () => {
const resource = new Resource('Foo');
resource.parent = 'Resource';
Expand Down
26 changes: 26 additions & 0 deletions test/export/ValueSetExporter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { loggerSpy } from '../testhelpers/loggerSpy';
import { TestFisher } from '../testhelpers';
import { FHIRDefinitions } from '../../src/fhirdefs';
import path from 'path';
import { cloneDeep } from 'lodash';
import {
CaretValueRule,
InsertRule,
Expand Down Expand Up @@ -109,6 +110,31 @@ describe('ValueSetExporter', () => {
});
});

it('should export a value set with status and version in FSHOnly mode', () => {
// Create a FSHOnly config with a status and version
const fshOnlyConfig = cloneDeep(minimalConfig);
fshOnlyConfig.FSHOnly = true;
fshOnlyConfig.version = '0.1.0';
fshOnlyConfig.status = 'active';
const input = new FSHTank([doc], fshOnlyConfig);
pkg = new Package(input.config);
const fisher = new TestFisher(input, defs, pkg);
exporter = new ValueSetExporter(input, pkg, fisher);

const valueSet = new FshValueSet('BreakfastVS');
doc.valueSets.set(valueSet.name, valueSet);
const exported = exporter.export().valueSets;
expect(exported.length).toBe(1);
expect(exported[0]).toEqual({
resourceType: 'ValueSet',
name: 'BreakfastVS',
id: 'BreakfastVS',
status: 'active',
version: '0.1.0',
url: 'http://hl7.org/fhir/us/minimal/ValueSet/BreakfastVS'
});
});

it('should warn when title and/or description is an empty string', () => {
const valueSet = new FshValueSet('BreakfastVS');
valueSet.title = '';
Expand Down
2 changes: 1 addition & 1 deletion test/import/importConfiguration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2915,7 +2915,7 @@ describe('importConfiguration', () => {
minYAML.FSHOnly = true;
const config = importConfiguration(minYAML, 'test-config.yaml');
expect(loggerSpy.getLastMessage('warn')).toMatch(
/The following properties are unused and only relevant for IG creation: id, name, status, copyrightYear, releaseLabel, template, menu, contained\..*File: test-config.yaml/s
/The following properties are unused and only relevant for IG creation: id, name, copyrightYear, releaseLabel, template, menu, contained\..*File: test-config.yaml/s
);
expect(config.FSHOnly).toBe(true);
});
Expand Down

0 comments on commit 28c325f

Please sign in to comment.