Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set version based on sushi-config.yaml in FSHOnly projects #1456

Merged
merged 2 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading