Skip to content

Commit

Permalink
Fix issues w/ metadata (derivation, baseDefinition, context) and bump…
Browse files Browse the repository at this point in the history
… version (#29)

* Set derivation to constraint

* Bump version to 0.2.1 and update handlebars dependency

* Set derivation to 'constraint' for Profiles/Extensions only

* Set baseDefinition to the parent url

* Temporary Fix: Default value for Extension context

Every Extension must specify a context.  Ideally, FSH should do this via a keyword or caret syntax.  In the short term, however, we will hard-code it to a default value if it's not specified by the parent already.
  • Loading branch information
jafeltra authored and Dylan Mahalingam committed Nov 19, 2019
1 parent bc3ae85 commit d4970b9
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 10 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fsh-sushi",
"version": "0.2.0",
"version": "0.2.1",
"description": "Sushi Unshortens Short Hand Inputs (FSH Compiler)",
"scripts": {
"build": "rm -rf dist && tsc && cp -r src/fhirdefs/fhir-4.0.1 dist/fhirdefs/fhir-4.0.1",
Expand Down
22 changes: 21 additions & 1 deletion src/export/StructureDefinitionExporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,29 @@ export class StructureDefinitionExporter {
): void {
structDef.name = fshDefinition.name;
structDef.id = fshDefinition.id;
structDef.url = `${tank.config.canonical}/StructureDefinition/${structDef.id}`;
if (fshDefinition.title) structDef.title = fshDefinition.title;
if (fshDefinition.description) structDef.description = fshDefinition.description;
// Assuming the starting StructureDefinition was a clone of the parent,
// set the baseDefinition to the parent url before re-assiging the url
structDef.baseDefinition = structDef.url;
// Now re-assign the URL based on canonical and id
structDef.url = `${tank.config.canonical}/StructureDefinition/${structDef.id}`;
// Set the derivation as appropriate
if (fshDefinition instanceof Profile) {
structDef.derivation = 'constraint';
} else if (fshDefinition instanceof Extension) {
structDef.derivation = 'constraint';
if (structDef.context == null) {
// NOTE: For now, we always set context to everything, but this will be user-specified
// in the future
structDef.context = [
{
type: 'element',
expression: 'Element'
}
];
}
}
}

/**
Expand Down
4 changes: 3 additions & 1 deletion src/fhirtypes/StructureDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class StructureDefinition {
contextInvariant: string[];
type: string;
baseDefinition: string;
derivation: string;
derivation: 'specialization' | 'constraint';

/**
* The StructureDefinition's elements. The returned array should not be pushed to directly. Instead, use
Expand Down Expand Up @@ -247,6 +247,7 @@ export class StructureDefinition {
j[prop] = cloneDeep(this[prop]);
}
}

// Now handle snapshot and differential
j.snapshot = { element: this.elements.map(e => e.toJSON()) };
j.differential = {
Expand Down Expand Up @@ -444,6 +445,7 @@ type PathPart = {
*/
interface LooseStructDefJSON {
resourceType: string;
derivation?: string;
snapshot?: { element: any[] };
differential?: { element: any[] };
// [key: string]: any;
Expand Down
41 changes: 41 additions & 0 deletions test/export/StructureDefinitionExporter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ describe('StructureDefinitionExporter', () => {
expect(exported.description).toBe('foo bar foobar');
expect(exported.url).toBe('http://example.com/StructureDefinition/foo');
expect(exported.type).toBe('Observation');
expect(exported.baseDefinition).toBe('http://hl7.org/fhir/StructureDefinition/Observation');
expect(exported.derivation).toBe('constraint');
});

it('should not overwrite metadata that is not given for a profile', () => {
Expand All @@ -53,6 +55,8 @@ describe('StructureDefinitionExporter', () => {
expect(exported.description).toBe('This is the base resource type for everything.');
expect(exported.url).toBe('http://example.com/StructureDefinition/Foo');
expect(exported.type).toBe('Resource');
expect(exported.baseDefinition).toBe('http://hl7.org/fhir/StructureDefinition/Resource');
expect(exported.derivation).toBe('constraint');
});

it('should throw ParentNotDefinedError when parent resource is not found', () => {
Expand All @@ -77,7 +81,17 @@ describe('StructureDefinitionExporter', () => {
expect(exported.title).toBe('Foo Profile');
expect(exported.description).toBe('foo bar foobar');
expect(exported.url).toBe('http://example.com/StructureDefinition/foo');
// NOTE: For now, we always set context to everything, but this will be user-specified in
// the future
expect(exported.context).toEqual([
{
type: 'element',
expression: 'Element'
}
]);
expect(exported.type).toBe('Extension');
expect(exported.baseDefinition).toBe('http://hl7.org/fhir/StructureDefinition/Extension');
expect(exported.derivation).toBe('constraint');
});

it('should not overwrite metadata that is not given for an extension', () => {
Expand All @@ -91,7 +105,34 @@ describe('StructureDefinitionExporter', () => {
'Base StructureDefinition for Extension Type: Optional Extension Element - found in all resources.'
);
expect(exported.url).toBe('http://example.com/StructureDefinition/Foo');
// NOTE: For now, we always set context to everything, but this will be user-specified in
// the future
expect(exported.context).toEqual([
{
type: 'element',
expression: 'Element'
}
]);
expect(exported.type).toBe('Extension');
expect(exported.baseDefinition).toBe('http://hl7.org/fhir/StructureDefinition/Extension');
expect(exported.derivation).toBe('constraint');
});

it('should not hardcode in the default context if parent already had a context', () => {
// NOTE: This is a temporary test to ensure that we don't overwrite a valid context with our
// "default" context. In the (near) future, however, we should do away with our default
// context and make context user-specified, in which case it should override the parent's
// context.
const extension = new Extension('Foo');
extension.parent = 'http://hl7.org/fhir/StructureDefinition/patient-animal';
doc.extensions.set(extension.name, extension);
const exported = exporter.exportStructDef(extension, input);
expect(exported.context).toEqual([
{
type: 'element',
expression: 'Patient'
}
]);
});

it('should throw ParentNotDefinedError when parent extension is not found', () => {
Expand Down

0 comments on commit d4970b9

Please sign in to comment.