Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

Commit

Permalink
feat: Compile IG StructureDefinitions (#219)
Browse files Browse the repository at this point in the history
  • Loading branch information
emilhdiaz authored Mar 8, 2021
1 parent ffb34ce commit aaaa707
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 28 deletions.
40 changes: 40 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Don't include original .ts files when doing `npm pack`
*.ts
!*.template.ts
!*.d.ts
coverage
.nyc_output
*.tgz

*.tsbuildinfo
tsconfig.json
.eslintrc.js
.eslintignore
.prettierrc.js
.github
.dockerignore
serverless.yaml
serverless_config.template.json
CODE_OF_CONDUCT.md
CONTRIBUTING.md
CHANGELOG.md
CODEOWNERS
CUSTOMIZE.md
DEVELOPMENT.md
INSTALL.md
LICENSE
NOTICE
README.md
THIRD-PARTY

auditLogMover/
bulkExport/
cloudformation/
compiledImplementationGuides/
implementationGuides/
docker/
integration-tests/
postman/
resources/
scripts/
src/
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"version": "2.4.0",
"description": "FHIR Works on AWS deployment",
"stackname": "fhir-works-on-aws-deployment",
"main": "src/index.ts",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"author": {
"name": "Amazon Web Services",
"email": "[email protected]",
Expand Down Expand Up @@ -68,10 +69,10 @@
"serverless-plugin-typescript": "^1.1.9",
"serverless-step-functions": "^2.27.1",
"sinon": "^9.0.2",
"tmp-promise": "^3.0.2",
"ts-jest": "^26.4.4",
"typescript": "^4.1.3",
"wait-for-expect": "^3.0.2",
"tmp-promise": "^3.0.2"
"wait-for-expect": "^3.0.2"
},
"resolutions": {
"dot-prop": "^5.1.1",
Expand Down
23 changes: 15 additions & 8 deletions scripts/compile-igs.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import { join, dirname } from 'path';
import yargs from 'yargs';
import { SearchImplementationGuides } from 'fhir-works-on-aws-search-es';
import { join } from 'path';
import { existsSync, mkdirSync } from 'fs';
import { SearchImplementationGuides } from 'fhir-works-on-aws-search-es';
import { StructureDefinitionImplementationGuides } from 'fhir-works-on-aws-routing/lib/implementationGuides';
import { IGCompiler } from '../src/implementationGuides/IGCompiler';
import { COMPILED_IGS_DIRECTORY } from "../src/implementationGuides/loadCompiledIGs";

const PROJECT_DIR = join(__dirname, '..');

function parseCmdOptions() {
return yargs(process.argv.slice(2))
.usage('Usage: $0 [--ignoreVersion, -i ] [--igPath, -p IG pack directory] [--outputFile, -o output ]')
.usage('Usage: $0 [--ignoreVersion, -i ] [--igPath, -p IG pack directory] [--outputDir, -o output ]')
.describe('ignoreVersion', "Don't care whether version of dependency lines up with version of installed IG")
.boolean('ignoreVersion')
.default('ignoreVersion', false)
.alias('i', 'ignoreVersion')
.describe('igPath', 'Path to folder with IG pack sub folders')
.default('igPath', join(PROJECT_DIR, 'implementationGuides/'))
.alias('p', 'igPath')
.describe('outputFile', 'Path to compiled output JSON file')
.alias('o', 'outputFile')
.default('outputFile', join(PROJECT_DIR, 'compiledImplementationGuides/fhir-works-on-aws-search-es.json')).argv;
.describe('outputDir', 'Path to compiled output JSON file')
.alias('o', 'outputDir')
.default('outputDir', join(PROJECT_DIR, COMPILED_IGS_DIRECTORY)).argv;
}

/**
Expand All @@ -34,14 +36,19 @@ async function compileIGs() {
console.log(`IGs folder '${cmdArgs.igPath}' does not exist. No IGs found, exiting...`);
return;
}
const compiledIgsDir = dirname(cmdArgs.outputFile);
const compiledIgsDir = cmdArgs.outputDir.toString()
if (!existsSync(compiledIgsDir)) {
console.log(`folder for compiled IGs '${compiledIgsDir}' does not exist, creating it`);
mkdirSync(compiledIgsDir, { recursive: true });
}

try {
await new IGCompiler(SearchImplementationGuides, options).compileIGs(cmdArgs.igPath, cmdArgs.outputFile);
await new IGCompiler(
SearchImplementationGuides,
new StructureDefinitionImplementationGuides,
options
)
.compileIGs(cmdArgs.igPath, cmdArgs.outputDir);
} catch (ex) {
console.error('Exception: ', ex.message, ex.stack);
}
Expand Down
2 changes: 1 addition & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ const baseResources = fhirVersion === '4.0.1' ? BASE_R4_RESOURCES : BASE_STU3_RE
const authService = IS_OFFLINE ? stubs.passThroughAuthz : new RBACHandler(RBACRules(baseResources), fhirVersion);
const dynamoDbDataService = new DynamoDbDataService(DynamoDb);
const dynamoDbBundleService = new DynamoDbBundleService(DynamoDb);

const esSearch = new ElasticSearchService(
[
{
Expand Down Expand Up @@ -79,6 +78,7 @@ export const fhirConfig: FhirConfig = {
profile: {
systemOperations: ['transaction'],
bundle: dynamoDbBundleService,
compiledImplementationGuides: loadImplementationGuides('fhir-works-on-aws-routing'),
systemHistory: stubs.history,
systemSearch: stubs.search,
bulkDataAccess: dynamoDbDataService,
Expand Down
43 changes: 34 additions & 9 deletions src/implementationGuides/IGCompiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,16 @@ export interface IGInfo {
export class IGCompiler {
private options: IGCompilerOptions;

private readonly implementationGuides: ImplementationGuides;
private readonly searchImplementationGuides: ImplementationGuides;
private readonly structureDefinitionImplementationGuides: ImplementationGuides;

constructor(implementationGuides: ImplementationGuides, options: IGCompilerOptions) {
constructor(searchImplementationGuides: ImplementationGuides, structureDefinitionImplementationGuides: ImplementationGuides, options: IGCompilerOptions) {
this.searchImplementationGuides = searchImplementationGuides;
this.structureDefinitionImplementationGuides = structureDefinitionImplementationGuides;
this.options = options;
this.implementationGuides = implementationGuides;
}

async collectResources(igDir: PathLike): Promise<any[]> {
async collectSearchParams(igDir: PathLike): Promise<any[]> {
const indexJson = path.join(igDir.toString(), '.index.json');
if (!existsSync(indexJson)) {
throw new Error(`'.index.json' not found in ${igDir}`);
Expand All @@ -83,6 +85,23 @@ export class IGCompiler {
return resources;
}

async collectStructureDefinitions(igDir: PathLike): Promise<any[]> {
const indexJson = path.join(igDir.toString(), '.index.json');
if (!existsSync(indexJson)) {
throw new Error(`'.index.json' not found in ${igDir}`);
}
const index: any = await loadJson(indexJson);
const resources = [];
for (const file of index.files) {
if (file.resourceType === 'StructureDefinition') {
const filePath = path.join(igDir.toString(), file.filename);
console.log(`Compiling ${filePath}`);
resources.push(await loadJson(filePath));
}
}
return resources;
}

/**
* Main public function
* @param igsDir
Expand All @@ -93,13 +112,19 @@ export class IGCompiler {
throw new Error(`'${igsDir}' doesn't exist`);
}
const igInfos = await this.collectIGInfos(igsDir);
this.validateDependencies(igInfos);
const resources: any[] = [];
// this.validateDependencies(igInfos);

const searchParams: any[] = [];
const structureDefinitions: any[] = [];
for (const igInfo of igInfos) {
resources.push(...(await this.collectResources(igInfo.path)));
searchParams.push(...(await this.collectSearchParams(igInfo.path)));
structureDefinitions.push(...(await this.collectStructureDefinitions(igInfo.path)));
}
const compiledResources = await this.implementationGuides.compile(resources);
await storeJson(outputPath, compiledResources);
const compiledSearchParams = await this.searchImplementationGuides.compile(searchParams);
const compiledStructureDefinitions = await this.structureDefinitionImplementationGuides.compile(structureDefinitions);

await storeJson(path.join(outputPath.toString(), 'fhir-works-on-aws-search-es.json'), compiledSearchParams);
await storeJson(path.join(outputPath.toString(), 'fhir-works-on-aws-routing.json'), compiledStructureDefinitions);
}

createIGKey(name: string, version: string) {
Expand Down
16 changes: 9 additions & 7 deletions src/implementationGuides/loadCompiledIGs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@
*/

import path from 'path';
import { existsSync, readFileSync } from 'fs';
import { existsSync, PathLike, readFileSync } from 'fs';

const COMPILED_IGS_DIRECTORY = 'compiledImplementationGuides';
export const COMPILED_IGS_DIRECTORY = 'compiledImplementationGuides';

// eslint-disable-next-line import/prefer-default-export
export const loadImplementationGuides = (moduleName: string): any[] | undefined => {
const implementationGuidesPath = path.join(__dirname, '..', '..', COMPILED_IGS_DIRECTORY);
const searchIgsPath = path.join(implementationGuidesPath, `${moduleName}.json`);
export const loadImplementationGuides = (moduleName: string, implementationGuidesPath?: PathLike): any[] | undefined => {
if ( implementationGuidesPath === undefined) {
implementationGuidesPath = path.join(__dirname, '..', '..', COMPILED_IGS_DIRECTORY);
}
const igsPath = path.join(implementationGuidesPath.toString(), `${moduleName}.json`);

if (existsSync(searchIgsPath)) {
return JSON.parse(readFileSync(searchIgsPath, { encoding: 'utf8' }));
if (existsSync(igsPath)) {
return JSON.parse(readFileSync(igsPath, { encoding: 'utf8' }));
}
return undefined;
};
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'.
"forceConsistentCasingInFileNames": true, // Disallow inconsistently-cased references to the same file.
"outDir": "dist",
"declaration": true,
"sourceMap": true,
"resolveJsonModule": true,
"baseUrl": ".",
Expand Down

0 comments on commit aaaa707

Please sign in to comment.