diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..db564b05 --- /dev/null +++ b/.npmignore @@ -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/ diff --git a/package.json b/package.json index 115d9510..f68d0e84 100644 --- a/package.json +++ b/package.json @@ -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": "fhir-works-on-aws-dev@amazon.com", @@ -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", diff --git a/scripts/compile-igs.ts b/scripts/compile-igs.ts index ab2ae127..526c13cb 100644 --- a/scripts/compile-igs.ts +++ b/scripts/compile-igs.ts @@ -1,14 +1,16 @@ -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) @@ -16,9 +18,9 @@ function parseCmdOptions() { .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; } /** @@ -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); } diff --git a/src/config.ts b/src/config.ts index 7d48176d..b2af507a 100644 --- a/src/config.ts +++ b/src/config.ts @@ -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( [ { @@ -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, diff --git a/src/implementationGuides/IGCompiler.ts b/src/implementationGuides/IGCompiler.ts index 2757eb2e..8773a850 100644 --- a/src/implementationGuides/IGCompiler.ts +++ b/src/implementationGuides/IGCompiler.ts @@ -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 { + async collectSearchParams(igDir: PathLike): Promise { const indexJson = path.join(igDir.toString(), '.index.json'); if (!existsSync(indexJson)) { throw new Error(`'.index.json' not found in ${igDir}`); @@ -83,6 +85,23 @@ export class IGCompiler { return resources; } + async collectStructureDefinitions(igDir: PathLike): Promise { + 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 @@ -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) { diff --git a/src/implementationGuides/loadCompiledIGs.ts b/src/implementationGuides/loadCompiledIGs.ts index ec78adad..e7c8d607 100644 --- a/src/implementationGuides/loadCompiledIGs.ts +++ b/src/implementationGuides/loadCompiledIGs.ts @@ -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; }; diff --git a/tsconfig.json b/tsconfig.json index db683ff2..37fd766e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -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": ".",