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

Fix output paths #991

Merged
merged 3 commits into from
Dec 20, 2021
Merged
Show file tree
Hide file tree
Changes from 2 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
21 changes: 21 additions & 0 deletions npm-shrinkwrap.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"junk": "^3.1.0",
"lodash": "^4.17.21",
"readline-sync": "^1.4.10",
"sanitize-filename": "^1.6.3",
"sax": "^1.2.4",
"tar": "^5.0.11",
"temp": "^0.9.1",
Expand Down
3 changes: 2 additions & 1 deletion src/fhirtypes/CodeSystem.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sanitize from 'sanitize-filename';
import { cloneDeep } from 'lodash';
import { Meta } from './specialTypes';
import { Extension } from '../fshtypes';
Expand Down Expand Up @@ -52,7 +53,7 @@ export class CodeSystem {
* @returns {string} the filename
*/
getFileName(): string {
return `CodeSystem-${this.id}.json`;
return sanitize(`CodeSystem-${this.id.replace(/\/\\/g, '-')}.json`, { replacement: '-' });
cmoesel marked this conversation as resolved.
Show resolved Hide resolved
cmoesel marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down
5 changes: 4 additions & 1 deletion src/fhirtypes/InstanceDefinition.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sanitize from 'sanitize-filename';
import { difference, remove, pull, cloneDeep, isObjectLike } from 'lodash';
import { Meta } from './specialTypes';
import { HasId } from './mixins';
Expand All @@ -22,7 +23,9 @@ export class InstanceDefinition {
* @returns {string} the filename
*/
getFileName(): string {
return `${this.resourceType}-${this.id ?? this._instanceMeta.name}.json`;
return sanitize(`${this.resourceType}-${this.id ?? this._instanceMeta.name}.json`, {
replacement: '-'
});
}

toJSON(): any {
Expand Down
3 changes: 2 additions & 1 deletion src/fhirtypes/StructureDefinition.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import upperFirst from 'lodash/upperFirst';
import cloneDeep from 'lodash/cloneDeep';
import escapeRegExp from 'lodash/escapeRegExp';
import sanitize from 'sanitize-filename';
import { ElementDefinition, ElementDefinitionType, LooseElementDefJSON } from './ElementDefinition';
import { Meta } from './specialTypes';
import { Identifier, CodeableConcept, Coding, Narrative, Resource, Extension } from './dataTypes';
Expand Down Expand Up @@ -124,7 +125,7 @@ export class StructureDefinition {
* @returns {string} the filename
*/
getFileName(): string {
return `StructureDefinition-${this.id}.json`;
return sanitize(`StructureDefinition-${this.id}.json`, { replacement: '-' });
}

get pathType(): string {
Expand Down
4 changes: 2 additions & 2 deletions src/fhirtypes/ValueSet.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import sanitize from 'sanitize-filename';
import { Meta } from './specialTypes';

import { Extension } from '../fshtypes';
import { Narrative, Resource, Identifier, CodeableConcept, Coding } from './dataTypes';
import { ContactDetail, UsageContext } from './metaDataTypes';
Expand Down Expand Up @@ -46,7 +46,7 @@ export class ValueSet {
* @returns {string} the filename
*/
getFileName(): string {
return `ValueSet-${this.id}.json`;
return sanitize(`ValueSet-${this.id}.json`, { replacement: '-' });
}

/**
Expand Down
7 changes: 6 additions & 1 deletion src/ig/IGExporter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import path from 'path';
import ini from 'ini';
import sanitize from 'sanitize-filename';
import { EOL } from 'os';
import { sortBy, words, pad, padEnd, repeat, cloneDeep } from 'lodash';
import { titleCase } from 'title-case';
Expand Down Expand Up @@ -1071,7 +1072,11 @@ export class IGExporter {
*/
addImplementationGuide(igPath: string): void {
const igJSONFolder = path.join('fsh-generated', 'resources');
const igJsonPath = path.join(igPath, igJSONFolder, `ImplementationGuide-${this.ig.id}.json`);
const igJsonPath = path.join(
igPath,
igJSONFolder,
sanitize(`ImplementationGuide-${this.ig.id}.json`, { replacement: '-' })
);
outputJSONSync(igJsonPath, this.ig, { spaces: 2 });
logger.info(`Generated ImplementationGuide-${this.ig.id}.json`);
}
Expand Down
33 changes: 33 additions & 0 deletions test/ig/IGExporter.IG.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2016,4 +2016,37 @@ describe('IGExporter', () => {
);
});
});

describe('#devious-id-ig', () => {
let tempOut: string;

beforeAll(() => {
loggerSpy.reset();
tempOut = temp.mkdirSync('sushi-test');
const fixtures = path.join(__dirname, 'fixtures', 'simple-ig');
const defs = new FHIRDefinitions();
loadFromPath(path.join(__dirname, '..', 'testhelpers', 'testdefs'), 'r4-definitions', defs);
const deviousConfig = cloneDeep(minimalConfig);
deviousConfig.id = '/../../../arenticlever';
const pkg = new Package(deviousConfig);
const exporter = new IGExporter(pkg, defs, fixtures);
exporter.export(tempOut);
});

afterAll(() => {
temp.cleanupSync();
});

it('should not allow devious characters in the IG file name ', () => {
const deviousPath = path.join(tempOut, 'arenticlever.json');
expect(fs.existsSync(deviousPath)).toBeFalse();
const angelicPath = path.join(
tempOut,
'fsh-generated',
'resources',
'ImplementationGuide--..-..-..-arenticlever.json'
);
expect(fs.existsSync(angelicPath)).toBeTruthy();
});
});
});
48 changes: 48 additions & 0 deletions test/utils/Processing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,54 @@ describe('Processing', () => {
expect(loggerSpy.getLastMessage('info')).toMatch(/Exported 14 FHIR resources/s);
});

it('should not allow devious characters in the resource file names', () => {
const tempDeviousIGPubRoot = temp.mkdirSync('output-ig-dir');
const deviousOutPackage = cloneDeep(outPackage);
deviousOutPackage.profiles.forEach(d => (d.id = `/../../devious/${d.id}`));
deviousOutPackage.extensions.forEach(d => (d.id = `/../../devious/${d.id}`));
deviousOutPackage.logicals.forEach(d => (d.id = `/../../devious/${d.id}`));
deviousOutPackage.resources.forEach(d => (d.id = `/../../devious/${d.id}`));
deviousOutPackage.valueSets.forEach(d => (d.id = `/../../devious/${d.id}`));
deviousOutPackage.codeSystems.forEach(d => (d.id = `/../../devious/${d.id}`));
deviousOutPackage.instances.forEach(d => (d.id = `/../../devious/${d.id}`));
writeFHIRResources(tempDeviousIGPubRoot, deviousOutPackage, defs, false);

// Make sure we didn't create the devious path
const deviousPath = path.join(tempDeviousIGPubRoot, 'fsh-generated', 'devious');
expect(fs.existsSync(deviousPath)).toBeFalse();

// Make sure we do have all the good file names
const angelicPath = path.join(tempDeviousIGPubRoot, 'fsh-generated', 'resources');
expect(fs.existsSync(angelicPath)).toBeTruthy();
const allAngelicFiles = fs.readdirSync(angelicPath);
expect(allAngelicFiles.length).toBe(16);
expect(allAngelicFiles).toContain(
'CapabilityStatement--..-..-devious-my-capabilities.json'
);
expect(allAngelicFiles).toContain('CodeSystem--..-..-devious-my-code-system.json');
expect(allAngelicFiles).toContain('ConceptMap--..-..-devious-my-concept-map.json');
expect(allAngelicFiles).toContain('Observation--..-..-devious-my-example.json');
expect(allAngelicFiles).toContain('Observation--..-..-devious-my-other-instance.json');
expect(allAngelicFiles).toContain('OperationDefinition--..-..-devious-my-operation.json');
expect(allAngelicFiles).toContain('Patient--..-..-devious-my-duplicate-instance.json');
expect(allAngelicFiles).toContain(
'StructureDefinition--..-..-devious-my-duplicate-profile.json'
);
expect(allAngelicFiles).toContain(
'StructureDefinition--..-..-devious-my-extension-instance.json'
);
expect(allAngelicFiles).toContain('StructureDefinition--..-..-devious-my-extension.json');
expect(allAngelicFiles).toContain('StructureDefinition--..-..-devious-my-logical.json');
expect(allAngelicFiles).toContain('StructureDefinition--..-..-devious-my-model.json');
expect(allAngelicFiles).toContain(
'StructureDefinition--..-..-devious-my-profile-instance.json'
);
expect(allAngelicFiles).toContain('StructureDefinition--..-..-devious-my-profile.json');
expect(allAngelicFiles).toContain('StructureDefinition--..-..-devious-my-resource.json');
expect(allAngelicFiles).toContain('ValueSet--..-..-devious-my-value-set.json');
expect(loggerSpy.getLastMessage('info')).toMatch(/Exported 16 FHIR resources/s);
});

it('should not write a resource if that resource already exists in the "input" folder', () => {
expect(
fs.existsSync(
Expand Down