├── .czrc ├── .gitallowed ├── .gitattributes ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── miscellaneous.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── scripts │ ├── commitizen.sh │ ├── git-secrets-scan.sh │ └── viperlight-scan.sh ├── .gitignore ├── .npmpackagejsonlintignore ├── .npmpackagejsonlintrc.json ├── .prettierignore ├── .prettierrc.js ├── .viperlightignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── DEVELOPMENT.md ├── FHIR Works on AWS - Migration Tool User Guide.pdf ├── FHIR Works on AWS Implementation Guide - 24-MAR-2023 - v6.0.0.pdf ├── INSTALL.md ├── LICENSE.txt ├── NOTICE.txt ├── README.md ├── brazil.ion ├── buildspec.yml ├── commitlint.config.js ├── common ├── autoinstallers │ ├── commitizen │ │ ├── package.json │ │ └── pnpm-lock.yaml │ ├── commitlint │ │ ├── package.json │ │ └── pnpm-lock.yaml │ └── rush-prettier │ │ ├── package.json │ │ └── pnpm-lock.yaml ├── changes │ └── @aws │ │ ├── fhir-works-on-aws-authz-rbac │ │ ├── notice-fixes_2023-04-10-18-45.json │ │ └── sevu-tasks-update-changelogs_2023-04-10-16-06.json │ │ ├── fhir-works-on-aws-authz-smart │ │ ├── kcadette-docs-changelogs-mfa_2023-06-07-15-15.json │ │ ├── kcadette-docs-changelogs-mfa_2023-06-07-15-24.json │ │ ├── notice-fixes_2023-04-10-18-45.json │ │ ├── sevu-tasks-update-changelogs_2023-04-10-16-06.json │ │ └── sukeev-feat-migrationTool_2023-05-31-18-38.json │ │ ├── fhir-works-on-aws-interface │ │ ├── notice-fixes_2023-04-10-18-45.json │ │ └── sevu-tasks-update-changelogs_2023-04-10-16-06.json │ │ ├── fhir-works-on-aws-persistence-ddb │ │ ├── notice-fixes_2023-04-10-18-45.json │ │ └── sevu-tasks-update-changelogs_2023-04-10-16-06.json │ │ ├── fhir-works-on-aws-routing │ │ ├── notice-fixes_2023-04-10-18-45.json │ │ └── sevu-tasks-update-changelogs_2023-04-10-16-06.json │ │ └── fhir-works-on-aws-search-es │ │ ├── kcadette-docs-changelogs-mfa_2023-06-07-15-24.json │ │ ├── notice-fixes_2023-04-10-18-45.json │ │ └── sevu-tasks-update-changelogs_2023-04-10-16-06.json ├── config │ └── rush │ │ ├── .npmrc │ │ ├── .npmrc-publish │ │ ├── .pnpmfile.cjs │ │ ├── artifactory.json │ │ ├── browser-approved-packages.json │ │ ├── build-cache.json │ │ ├── command-line.json │ │ ├── common-versions.json │ │ ├── experiments.json │ │ ├── nonbrowser-approved-packages.json │ │ ├── pnpm-config.json │ │ ├── pnpm-lock.yaml │ │ ├── repo-state.json │ │ ├── rush-plugins.json │ │ └── version-policies.json ├── git-hooks │ ├── commit-msg │ ├── pre-commit │ └── prepare-commit-msg └── scripts │ ├── install-hooks.js │ ├── install-run-rush.js │ ├── install-run-rushx.js │ └── install-run.js ├── core └── eslint-custom │ ├── .eslintignore │ ├── .eslintrc.js │ ├── LICENSE │ ├── NOTICE │ ├── README.md │ ├── config │ ├── heft.json │ ├── jest.config.json │ └── rig.json │ ├── package.json │ ├── src │ ├── custom-eslint.ts │ ├── index.ts │ └── rules │ │ └── import-convention.ts │ └── tsconfig.json ├── deployment ├── build-open-source-dist.sh ├── build-s3-dist.sh ├── cdk-solution-helper │ ├── README.md │ ├── index.js │ ├── package-lock.json │ └── package.json ├── run-unit-tests.sh └── solution_config ├── fwoa-core ├── authz-rbac │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .npmignore │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── CODE_OF_CONDUCT.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── NOTICE │ ├── README.md │ ├── THIRD_PARTY_LICENSES │ ├── config │ │ ├── heft.json │ │ ├── jest.config.json │ │ └── rig.json │ ├── package.json │ ├── src │ │ ├── RBACConfig.ts │ │ ├── RBACHandler.test.ts │ │ ├── RBACHandler.ts │ │ └── index.ts │ └── tsconfig.json ├── authz-smart │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .npmignore │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── CODE_OF_CONDUCT.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── NOTICE │ ├── README.md │ ├── THIRD_PARTY_LICENSES │ ├── config │ │ ├── heft.json │ │ ├── jest.config.json │ │ └── rig.json │ ├── package.json │ ├── scripts │ │ └── generateResourceReferenceMatrixFile.ts │ ├── src │ │ ├── comboTest │ │ │ ├── README.md │ │ │ ├── __snapshots__ │ │ │ │ ├── authorizeAndFilterReadResponse-combo.test.ts.snap │ │ │ │ ├── getAllowedResourceTypesForOperation-combo.test.ts.snap │ │ │ │ ├── getSearchFilterBasedOnIdentity-combo.test.ts.snap │ │ │ │ ├── isBundleRequestAuthorized-combo.test.ts.snap │ │ │ │ ├── isWriteRequestAuthorized-combo.test.ts.snap │ │ │ │ ├── verifyAccessToken-BulkDataAuth-combo.test.ts.snap │ │ │ │ └── verifyAccessToken-combo.test.ts.snap │ │ │ ├── authorizeAndFilterReadResponse-combo.test.ts │ │ │ ├── document │ │ │ │ ├── combo-test-process.png │ │ │ │ └── param-generation-example.png │ │ │ ├── getAllowedResourceTypesForOperation-combo.test.ts │ │ │ ├── getSearchFilterBasedOnIdentity-combo.test.ts │ │ │ ├── isBundleRequestAuthorized-combo.test.ts │ │ │ ├── isWriteRequestAuthorized-combo.test.ts │ │ │ ├── params │ │ │ │ ├── GetSearchFilterBasedOnIdentity-params.csv │ │ │ │ ├── VerifyAccessToken-BulkDataAuth-params.csv │ │ │ │ ├── VerifyAccessToken-NoBulkDataAuth-params.csv │ │ │ │ ├── authorizeAndFilterReadResponse-params.csv │ │ │ │ ├── getAllowedResourceTypesForOperation-params.csv │ │ │ │ ├── isBundleRequestAuthorized-params.csv │ │ │ │ └── isWriteRequestAuthorized-params.csv │ │ │ ├── paramsDefinition │ │ │ │ ├── GetAllowedResourceTypesForOperationRequest-definition.txt │ │ │ │ ├── GetSearchFilterBasedOnIdentity-definition.txt │ │ │ │ ├── VerifyAccessToken-BulkDataAuth-definition.txt │ │ │ │ ├── VerifyAccessToken-NoBulkDataAuth-definition.txt │ │ │ │ ├── authorizeAndFilterReadResponse-definition.txt │ │ │ │ ├── isBundleRequestAuthorized-definition.txt │ │ │ │ └── isWriteRequestAuthorized-definition.txt │ │ │ ├── testCaseUtil.test.ts │ │ │ ├── testStubs.ts │ │ │ ├── verifyAccessToken-BulkDataAuth-combo.test.ts │ │ │ └── verifyAccessToken-combo.test.ts │ │ ├── index.ts │ │ ├── loggerBuilder.ts │ │ ├── regExpressions.test.ts │ │ ├── schema │ │ │ ├── fhirResourceReferencesMatrix.v3.0.1.json │ │ │ └── fhirResourceReferencesMatrix.v4.0.1.json │ │ ├── smartAuthorizationHelper.test.ts │ │ ├── smartAuthorizationHelper.ts │ │ ├── smartConfig.ts │ │ ├── smartHandler.test.ts │ │ ├── smartHandler.ts │ │ ├── smartScopeHelper.test.ts │ │ └── smartScopeHelper.ts │ └── tsconfig.json ├── interface │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .npmignore │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── CODE_OF_CONDUCT.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── NOTICE │ ├── README.md │ ├── THIRD_PARTY_LICENSES │ ├── config │ │ ├── heft.json │ │ ├── jest.config.json │ │ └── rig.json │ ├── openapi.yaml │ ├── package.json │ ├── src │ │ ├── __snapshots__ │ │ │ └── loggerUtilities.test.ts.snap │ │ ├── authorization.ts │ │ ├── bulkDataAccess.ts │ │ ├── bundle.ts │ │ ├── capabilities.ts │ │ ├── constants.ts │ │ ├── encryptedLoggerBuilder.ts │ │ ├── errors │ │ │ ├── BadRequestError.ts │ │ │ ├── InvalidResourceError.ts │ │ │ ├── InvalidSearchParameterError.ts │ │ │ ├── MethodNotAllowedError.ts │ │ │ ├── ResourceConflictError.ts │ │ │ ├── ResourceNotFoundError.ts │ │ │ ├── ResourceVersionNotFoundError.ts │ │ │ ├── TooManyConcurrentExportRequestsError.ts │ │ │ └── UnauthorizedError.ts │ │ ├── fhirConfig.ts │ │ ├── genericResponse.ts │ │ ├── history.ts │ │ ├── implementationGuides.ts │ │ ├── index.ts │ │ ├── inputExampleEncryptSelectedField.json │ │ ├── loggerBuilder.ts │ │ ├── loggerUtilities.test.ts │ │ ├── loggerUtilities.ts │ │ ├── persistence.ts │ │ ├── resourceMeta.ts │ │ ├── search.ts │ │ ├── smartAuthorization.ts │ │ ├── stubs.ts │ │ ├── utilities.test.ts │ │ ├── utilities.ts │ │ └── validator.ts │ └── tsconfig.json ├── persistence-ddb │ ├── .eslintignore │ ├── .eslintrc.js │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── CODE_OF_CONDUCT.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── NOTICE │ ├── README.md │ ├── THIRD_PARTY_LICENSES │ ├── config │ │ ├── heft.json │ │ ├── jest.config.json │ │ └── rig.json │ ├── package.json │ ├── src │ │ ├── AWS.ts │ │ ├── bulkExport │ │ │ ├── __mocks__ │ │ │ │ └── bulkExport.ts │ │ │ ├── bulkExport.test.ts │ │ │ ├── bulkExport.ts │ │ │ ├── bulkExportResultsUrlGenerator.ts │ │ │ ├── bulkExportS3PresignedUrlGenerator.ts │ │ │ ├── getJobStatus.test.ts │ │ │ ├── getJobStatus.ts │ │ │ ├── startExportJob.test.ts │ │ │ ├── startExportJob.ts │ │ │ ├── stopExportJob.test.ts │ │ │ ├── stopExportJob.ts │ │ │ ├── types.ts │ │ │ ├── updateStatus.test.ts │ │ │ └── updateStatus.ts │ │ ├── constants.ts │ │ ├── dataServices │ │ │ ├── __mock__dynamoDbDataService.ts │ │ │ ├── __mocks__ │ │ │ │ └── dynamoDbBundleService.ts │ │ │ ├── documentStatus.ts │ │ │ ├── dynamoDb.ts │ │ │ ├── dynamoDbBundleService.test.ts │ │ │ ├── dynamoDbBundleService.ts │ │ │ ├── dynamoDbBundleServiceHelper.test.ts │ │ │ ├── dynamoDbBundleServiceHelper.ts │ │ │ ├── dynamoDbDataService.test.ts │ │ │ ├── dynamoDbDataService.ts │ │ │ ├── dynamoDbHelper.test.ts │ │ │ ├── dynamoDbHelper.ts │ │ │ ├── dynamoDbParamBuilder.test.ts │ │ │ ├── dynamoDbParamBuilder.ts │ │ │ ├── dynamoDbUtil.test.ts │ │ │ └── dynamoDbUtil.ts │ │ ├── ddbToEs │ │ │ ├── ESBulkCommand.ts │ │ │ ├── ddbToEsHelper.test.ts │ │ │ ├── ddbToEsHelper.ts │ │ │ ├── ddbToEsSync.test.ts │ │ │ ├── ddbToEsSync.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── loggerBuilder.ts │ │ ├── objectStorageService │ │ │ ├── ObjectNotFoundError.ts │ │ │ ├── __mocks__ │ │ │ │ └── s3ObjectStorageService.ts │ │ │ ├── objectStorageInterface.ts │ │ │ ├── s3.ts │ │ │ ├── s3DataService.test.ts │ │ │ ├── s3DataService.ts │ │ │ └── s3ObjectStorageService.ts │ │ ├── offlineEnvVariables.ts │ │ ├── regExpressions.test.ts │ │ ├── regExpressions.ts │ │ ├── sampleData │ │ │ ├── validV3Account.json │ │ │ ├── validV3JpegBinary.json │ │ │ ├── validV4Account.json │ │ │ ├── validV4JpegBinary.json │ │ │ ├── validV4Patient.json │ │ │ └── validV4PdfBinary.json │ │ └── testUtilities │ │ │ ├── ConditionalCheckFailedException.ts │ │ │ ├── GenerateRollbackRequestsFactory.ts │ │ │ ├── GenerateStagingRequestsFactory.ts │ │ │ └── regExpressions.ts │ └── tsconfig.json ├── routing │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .npmignore │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── CODE_OF_CONDUCT.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── NOTICE │ ├── README.md │ ├── THIRD_PARTY_LICENSES │ ├── config │ │ ├── heft.json │ │ ├── jest.config.json │ │ └── rig.json │ ├── package.json │ ├── src │ │ ├── AWS.ts │ │ ├── app.test.ts │ │ ├── app.ts │ │ ├── configHandler.ts │ │ ├── constants.ts │ │ ├── implementationGuides │ │ │ ├── index.test.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── loggerBuilder.ts │ │ ├── offlineEnvVariables.ts │ │ ├── operationDefinitions │ │ │ ├── OperationDefinitionRegistry.test.ts │ │ │ ├── OperationDefinitionRegistry.ts │ │ │ ├── USCoreDocRef │ │ │ │ ├── convertDocRefParamsToSearchParams.ts │ │ │ │ ├── docRefParamsToSearchParams.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── parseParams.test.ts │ │ │ │ └── parseParams.ts │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── regExpressions.test.ts │ │ ├── regExpressions.ts │ │ ├── registry │ │ │ ├── ResourceCapabilityInterface.ts │ │ │ ├── index.test.ts │ │ │ └── index.ts │ │ ├── router │ │ │ ├── __mocks_ │ │ │ │ ├── dynamoDbBundleService.ts │ │ │ │ ├── dynamoDbDataService.ts │ │ │ │ └── elasticSearchService.ts │ │ │ ├── bundle │ │ │ │ ├── bundleGenerator.ts │ │ │ │ ├── bundleHandler.test.ts │ │ │ │ ├── bundleHandler.ts │ │ │ │ ├── bundleHandlerInterface.ts │ │ │ │ ├── bundleParser.test.ts │ │ │ │ └── bundleParser.ts │ │ │ ├── handlers │ │ │ │ ├── crudHandlerInterface.ts │ │ │ │ ├── exportHandler.ts │ │ │ │ ├── resourceHandler.test.ts │ │ │ │ ├── resourceHandler.ts │ │ │ │ ├── rootHandler.ts │ │ │ │ ├── utils.ts │ │ │ │ ├── wellKnownUriHandler.test.ts │ │ │ │ └── wellKnownUriHandler.ts │ │ │ ├── metadata │ │ │ │ ├── cap.rest.resource.template.ts │ │ │ │ ├── cap.rest.security.template.ts │ │ │ │ ├── cap.rest.template.ts │ │ │ │ ├── cap.template.ts │ │ │ │ ├── metadataHandler.test.ts │ │ │ │ └── metadataHandler.ts │ │ │ ├── middlewares │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── setLogger.test.ts.snap │ │ │ │ ├── setContentType.test.ts │ │ │ │ ├── setContentType.ts │ │ │ │ ├── setLogger.test.ts │ │ │ │ ├── setLogger.ts │ │ │ │ ├── setServerUrl.test.ts │ │ │ │ ├── setServerUrl.ts │ │ │ │ ├── setTenantId.test.ts │ │ │ │ └── setTenantId.ts │ │ │ ├── operationsGenerator.ts │ │ │ ├── routes │ │ │ │ ├── errorHandling.ts │ │ │ │ ├── exportRoute.ts │ │ │ │ ├── exportRouteHelper.test.ts │ │ │ │ ├── exportRouteHelper.ts │ │ │ │ ├── genericResourceRoute.ts │ │ │ │ ├── metadataRoute.ts │ │ │ │ ├── rootRoute.ts │ │ │ │ ├── routeHelper.ts │ │ │ │ └── wellKnownUriRoute.ts │ │ │ └── validation │ │ │ │ ├── hapiFhirLambdaValidator.test.ts │ │ │ │ ├── hapiFhirLambdaValidator.ts │ │ │ │ ├── jsonSchemaValidator.test.ts │ │ │ │ ├── jsonSchemaValidator.ts │ │ │ │ ├── schemas │ │ │ │ ├── fhir.schema.v3.json │ │ │ │ └── fhir.schema.v4.json │ │ │ │ ├── subscriptionSchema.json │ │ │ │ ├── subscriptionValidator.test.ts │ │ │ │ ├── subscriptionValidator.ts │ │ │ │ ├── validationUtilities.test.ts │ │ │ │ └── validationUtilities.ts │ │ └── sampleData │ │ │ ├── invalidV4Patient.json │ │ │ ├── r4FhirConfigGeneric.ts │ │ │ ├── r4FhirConfigNoGeneric.ts │ │ │ ├── r4FhirConfigWithExclusions.ts │ │ │ ├── stu3FhirConfigWithExclusions.ts │ │ │ ├── validV3Account.json │ │ │ ├── validV3JpegBinary.json │ │ │ ├── validV4Account.json │ │ │ ├── validV4JpegBinary.json │ │ │ ├── validV4Patient.json │ │ │ └── validV4PdfBinary.json │ └── tsconfig.json └── search-es │ ├── .eslintignore │ ├── .eslintrc.js │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── CODE_OF_CONDUCT.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── NOTICE │ ├── README.md │ ├── THIRD_PARTY_LICENSES │ ├── config │ ├── heft.json │ ├── jest.config.json │ └── rig.json │ ├── jest.env.js │ ├── package.json │ ├── scripts │ ├── elasticSearchMappingsGenerator │ │ ├── choiceDataTypes.ts │ │ ├── constants.ts │ │ ├── index.ts │ │ ├── profilesRegistry.ts │ │ └── types.ts │ └── searchParamsCompiler │ │ └── run.ts │ ├── src │ ├── FHIRSearchParametersRegistry │ │ ├── __snapshots__ │ │ │ └── index.test.ts.snap │ │ ├── index.test.ts │ │ └── index.ts │ ├── FhirQueryParser │ │ ├── index.test.ts │ │ ├── index.ts │ │ ├── searchInclusion.test.ts │ │ ├── searchInclusion.ts │ │ ├── searchOR.test.ts │ │ ├── searchOR.ts │ │ ├── typeParsers │ │ │ ├── dateParser.test.ts │ │ │ ├── dateParser.ts │ │ │ ├── numberParser.test.ts │ │ │ ├── numberParser.ts │ │ │ ├── quantityParser.test.ts │ │ │ ├── quantityParser.ts │ │ │ ├── referenceParser.test.ts │ │ │ ├── referenceParser.ts │ │ │ ├── tokenParser.test.ts │ │ │ └── tokenParser.ts │ │ ├── util.test.ts │ │ └── util.ts │ ├── InMemoryMatcher │ │ ├── index.test.ts │ │ ├── index.ts │ │ └── matchers │ │ │ ├── common │ │ │ ├── __snapshots__ │ │ │ │ └── numericComparison.test.ts.snap │ │ │ ├── numericComparison.test.ts │ │ │ └── numericComparison.ts │ │ │ ├── dateMatch.ts │ │ │ ├── numberMatch.test.ts │ │ │ ├── numberMatch.ts │ │ │ ├── quantityMatch.test.ts │ │ │ ├── quantityMatch.ts │ │ │ ├── referenceMatcher.test.ts │ │ │ ├── referenceMatcher.ts │ │ │ ├── stringMatch.test.ts │ │ │ ├── stringMatch.ts │ │ │ ├── tokenMatch.test.ts │ │ │ ├── tokenMatch.ts │ │ │ ├── uriMatch.test.ts │ │ │ └── uriMatch.ts │ ├── QueryBuilder │ │ ├── chain.test.ts │ │ ├── chain.ts │ │ ├── index.ts │ │ ├── sort.test.ts │ │ ├── sort.ts │ │ └── typeQueries │ │ │ ├── common │ │ │ ├── number.test.ts │ │ │ ├── number.ts │ │ │ └── prefixRange.ts │ │ │ ├── dateQuery.test.ts │ │ │ ├── dateQuery.ts │ │ │ ├── numberQuery.test.ts │ │ │ ├── numberQuery.ts │ │ │ ├── quantityQuery.test.ts │ │ │ ├── quantityQuery.ts │ │ │ ├── referenceQuery.test.ts │ │ │ ├── referenceQuery.ts │ │ │ ├── stringQuery.test.ts │ │ │ ├── stringQuery.ts │ │ │ ├── tokenQuery.test.ts │ │ │ ├── tokenQuery.ts │ │ │ ├── uriQuery.test.ts │ │ │ └── uriQuery.ts │ ├── StreamSubscriptionMatcher │ │ ├── AsyncRefreshCache.test.ts │ │ ├── AsyncRefreshCache.ts │ │ ├── StreamSubscriptionMatcher.ts │ │ ├── index.ts │ │ ├── subscriptions.test.ts │ │ └── subscriptions.ts │ ├── __mocks__ │ │ └── elasticSearch.ts │ ├── __snapshots__ │ │ └── elasticSearchService.test.ts.snap │ ├── constants.ts │ ├── elasticSearch.ts │ ├── elasticSearchService.test.ts │ ├── elasticSearchService.ts │ ├── getAllValuesForFHIRPath.test.ts │ ├── getAllValuesForFHIRPath.ts │ ├── implementationGuides │ │ ├── __snapshots__ │ │ │ └── index.test.ts.snap │ │ ├── index.test.ts │ │ ├── index.ts │ │ ├── reducedFHIRPath.ne │ │ ├── reducedFHIRPath.ts │ │ ├── reducedXPath.ne │ │ └── reducedXPath.ts │ ├── index.ts │ ├── loggerBuilder.ts │ ├── schema │ │ ├── compiledSearchParameters.3.0.1.json │ │ ├── compiledSearchParameters.4.0.1.json │ │ ├── searchMappingsBase.3.0.1.json │ │ └── searchMappingsBase.4.0.1.json │ ├── searchInclusions.test.ts │ ├── searchInclusions.ts │ ├── searchMappings │ │ ├── __snapshots__ │ │ │ └── index.test.ts.snap │ │ ├── customMappings.ts │ │ ├── fhirTypeToESMapping.ts │ │ ├── index.test.ts │ │ └── index.ts │ ├── searchMappingsManager │ │ ├── index.test.ts │ │ └── index.ts │ ├── searchParametersMapping.ts │ └── tsUtils.ts │ └── tsconfig.json ├── fwoa-tools ├── .eslintignore ├── .eslintrc.js ├── config │ ├── heft.json │ ├── jest.config.json │ └── rig.json ├── package.json ├── src │ ├── binaryConverter.test.ts │ ├── binaryConverter.ts │ ├── createPatientPractitionerEncounterBundle.json │ ├── export-script.py │ ├── exportHelper.test.ts │ ├── exportHelper.ts │ ├── index.ts │ ├── integration-tests │ │ ├── migrationIntegTests.test.ts │ │ └── migrationUtilsInteInteg.test.ts │ ├── migrationExport.test.ts │ ├── migrationExport.ts │ ├── migrationImport.test.ts │ ├── migrationImport.ts │ ├── migrationUtils.test.ts │ ├── migrationUtils.ts │ ├── migrationVerify.test.ts │ └── migrationVerify.ts └── tsconfig.json ├── fwoa-utilities ├── .eslintignore ├── .eslintrc.js ├── javaHapiValidatorLambda │ ├── THIRD-PARTY │ ├── USING_IMPLEMENTATION_GUIDES.md │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── software │ │ │ │ └── amazon │ │ │ │ └── fwoa │ │ │ │ ├── Handler.java │ │ │ │ ├── IGUtils.java │ │ │ │ ├── Validator.java │ │ │ │ ├── ValidatorResponse.java │ │ │ │ └── models │ │ │ │ ├── IgFile.java │ │ │ │ └── IgIndex.java │ │ └── resources │ │ │ ├── implementationGuides │ │ │ └── .gitkeep │ │ │ └── log4j2.xml │ │ └── test │ │ ├── java │ │ └── software │ │ │ └── amazon │ │ │ └── fwoa │ │ │ └── ValidatorTest.java │ │ └── resources │ │ ├── testImplementationGuides-r4 │ │ └── us-core │ │ │ ├── .index.json │ │ │ ├── CapabilityStatement-us-core-client.json │ │ │ ├── CapabilityStatement-us-core-server.json │ │ │ ├── CodeSystem-careplan-category.json │ │ │ ├── CodeSystem-cdcrec.json │ │ │ ├── CodeSystem-condition-category.json │ │ │ ├── CodeSystem-us-core-documentreference-category.json │ │ │ ├── CodeSystem-us-core-provenance-participant-type.json │ │ │ ├── ConceptMap-ndc-cvx.json │ │ │ ├── ImplementationGuide-hl7.fhir.us.core.json │ │ │ ├── OperationDefinition-docref.json │ │ │ ├── SearchParameter-us-core-allergyintolerance-clinical-status.json │ │ │ ├── SearchParameter-us-core-allergyintolerance-patient.json │ │ │ ├── SearchParameter-us-core-careplan-category.json │ │ │ ├── SearchParameter-us-core-careplan-date.json │ │ │ ├── SearchParameter-us-core-careplan-patient.json │ │ │ ├── SearchParameter-us-core-careplan-status.json │ │ │ ├── SearchParameter-us-core-careteam-patient.json │ │ │ ├── SearchParameter-us-core-careteam-status.json │ │ │ ├── SearchParameter-us-core-condition-category.json │ │ │ ├── SearchParameter-us-core-condition-clinical-status.json │ │ │ ├── SearchParameter-us-core-condition-code.json │ │ │ ├── SearchParameter-us-core-condition-onset-date.json │ │ │ ├── SearchParameter-us-core-condition-patient.json │ │ │ ├── SearchParameter-us-core-device-patient.json │ │ │ ├── SearchParameter-us-core-device-type.json │ │ │ ├── SearchParameter-us-core-diagnosticreport-category.json │ │ │ ├── SearchParameter-us-core-diagnosticreport-code.json │ │ │ ├── SearchParameter-us-core-diagnosticreport-date.json │ │ │ ├── SearchParameter-us-core-diagnosticreport-patient.json │ │ │ ├── SearchParameter-us-core-diagnosticreport-status.json │ │ │ ├── SearchParameter-us-core-documentreference-category.json │ │ │ ├── SearchParameter-us-core-documentreference-date.json │ │ │ ├── SearchParameter-us-core-documentreference-id.json │ │ │ ├── SearchParameter-us-core-documentreference-patient.json │ │ │ ├── SearchParameter-us-core-documentreference-period.json │ │ │ ├── SearchParameter-us-core-documentreference-status.json │ │ │ ├── SearchParameter-us-core-documentreference-type.json │ │ │ ├── SearchParameter-us-core-encounter-class.json │ │ │ ├── SearchParameter-us-core-encounter-date.json │ │ │ ├── SearchParameter-us-core-encounter-id.json │ │ │ ├── SearchParameter-us-core-encounter-identifier.json │ │ │ ├── SearchParameter-us-core-encounter-patient.json │ │ │ ├── SearchParameter-us-core-encounter-status.json │ │ │ ├── SearchParameter-us-core-encounter-type.json │ │ │ ├── SearchParameter-us-core-ethnicity.json │ │ │ ├── SearchParameter-us-core-goal-lifecycle-status.json │ │ │ ├── SearchParameter-us-core-goal-patient.json │ │ │ ├── SearchParameter-us-core-goal-target-date.json │ │ │ ├── SearchParameter-us-core-immunization-date.json │ │ │ ├── SearchParameter-us-core-immunization-patient.json │ │ │ ├── SearchParameter-us-core-immunization-status.json │ │ │ ├── SearchParameter-us-core-location-address-city.json │ │ │ ├── SearchParameter-us-core-location-address-postalcode.json │ │ │ ├── SearchParameter-us-core-location-address-state.json │ │ │ ├── SearchParameter-us-core-location-address.json │ │ │ ├── SearchParameter-us-core-location-name.json │ │ │ ├── SearchParameter-us-core-medicationrequest-authoredon.json │ │ │ ├── SearchParameter-us-core-medicationrequest-encounter.json │ │ │ ├── SearchParameter-us-core-medicationrequest-intent.json │ │ │ ├── SearchParameter-us-core-medicationrequest-patient.json │ │ │ ├── SearchParameter-us-core-medicationrequest-status.json │ │ │ ├── SearchParameter-us-core-observation-category.json │ │ │ ├── SearchParameter-us-core-observation-code.json │ │ │ ├── SearchParameter-us-core-observation-date.json │ │ │ ├── SearchParameter-us-core-observation-patient.json │ │ │ ├── SearchParameter-us-core-observation-status.json │ │ │ ├── SearchParameter-us-core-organization-address.json │ │ │ ├── SearchParameter-us-core-organization-name.json │ │ │ ├── SearchParameter-us-core-patient-birthdate.json │ │ │ ├── SearchParameter-us-core-patient-family.json │ │ │ ├── SearchParameter-us-core-patient-gender.json │ │ │ ├── SearchParameter-us-core-patient-given.json │ │ │ ├── SearchParameter-us-core-patient-id.json │ │ │ ├── SearchParameter-us-core-patient-identifier.json │ │ │ ├── SearchParameter-us-core-patient-name.json │ │ │ ├── SearchParameter-us-core-practitioner-identifier.json │ │ │ ├── SearchParameter-us-core-practitioner-name.json │ │ │ ├── SearchParameter-us-core-practitionerrole-practitioner.json │ │ │ ├── SearchParameter-us-core-practitionerrole-specialty.json │ │ │ ├── SearchParameter-us-core-procedure-code.json │ │ │ ├── SearchParameter-us-core-procedure-date.json │ │ │ ├── SearchParameter-us-core-procedure-patient.json │ │ │ ├── SearchParameter-us-core-procedure-status.json │ │ │ ├── SearchParameter-us-core-race.json │ │ │ ├── StructureDefinition-head-occipital-frontal-circumference-percentile.json │ │ │ ├── StructureDefinition-pediatric-bmi-for-age.json │ │ │ ├── StructureDefinition-pediatric-weight-for-height.json │ │ │ ├── StructureDefinition-us-core-allergyintolerance.json │ │ │ ├── StructureDefinition-us-core-birthsex.json │ │ │ ├── StructureDefinition-us-core-careplan.json │ │ │ ├── StructureDefinition-us-core-careteam.json │ │ │ ├── StructureDefinition-us-core-condition.json │ │ │ ├── StructureDefinition-us-core-diagnosticreport-lab.json │ │ │ ├── StructureDefinition-us-core-diagnosticreport-note.json │ │ │ ├── StructureDefinition-us-core-direct.json │ │ │ ├── StructureDefinition-us-core-documentreference.json │ │ │ ├── StructureDefinition-us-core-encounter.json │ │ │ ├── StructureDefinition-us-core-ethnicity.json │ │ │ ├── StructureDefinition-us-core-goal.json │ │ │ ├── StructureDefinition-us-core-immunization.json │ │ │ ├── StructureDefinition-us-core-implantable-device.json │ │ │ ├── StructureDefinition-us-core-location.json │ │ │ ├── StructureDefinition-us-core-medication.json │ │ │ ├── StructureDefinition-us-core-medicationrequest.json │ │ │ ├── StructureDefinition-us-core-observation-lab.json │ │ │ ├── StructureDefinition-us-core-organization.json │ │ │ ├── StructureDefinition-us-core-patient.json │ │ │ ├── StructureDefinition-us-core-practitioner.json │ │ │ ├── StructureDefinition-us-core-practitionerrole.json │ │ │ ├── StructureDefinition-us-core-procedure.json │ │ │ ├── StructureDefinition-us-core-provenance.json │ │ │ ├── StructureDefinition-us-core-pulse-oximetry.json │ │ │ ├── StructureDefinition-us-core-race.json │ │ │ ├── StructureDefinition-us-core-smokingstatus.json │ │ │ ├── ValueSet-birthsex.json │ │ │ ├── ValueSet-detailed-ethnicity.json │ │ │ ├── ValueSet-detailed-race.json │ │ │ ├── ValueSet-omb-ethnicity-category.json │ │ │ ├── ValueSet-omb-race-category.json │ │ │ ├── ValueSet-simple-language.json │ │ │ ├── ValueSet-us-core-allergy-substance.json │ │ │ ├── ValueSet-us-core-careteam-provider-roles.json │ │ │ ├── ValueSet-us-core-clinical-note-type.json │ │ │ ├── ValueSet-us-core-condition-category.json │ │ │ ├── ValueSet-us-core-condition-code.json │ │ │ ├── ValueSet-us-core-diagnosticreport-category.json │ │ │ ├── ValueSet-us-core-diagnosticreport-lab-codes.json │ │ │ ├── ValueSet-us-core-diagnosticreport-report-and-note-codes.json │ │ │ ├── ValueSet-us-core-documentreference-category.json │ │ │ ├── ValueSet-us-core-documentreference-type.json │ │ │ ├── ValueSet-us-core-encounter-type.json │ │ │ ├── ValueSet-us-core-medication-codes.json │ │ │ ├── ValueSet-us-core-narrative-status.json │ │ │ ├── ValueSet-us-core-ndc-vaccine-codes.json │ │ │ ├── ValueSet-us-core-observation-smoking-status-status.json │ │ │ ├── ValueSet-us-core-observation-smokingstatus-max.json │ │ │ ├── ValueSet-us-core-observation-smokingstatus.json │ │ │ ├── ValueSet-us-core-observation-value-codes.json │ │ │ ├── ValueSet-us-core-procedure-code.json │ │ │ ├── ValueSet-us-core-procedure-icd10pcs.json │ │ │ ├── ValueSet-us-core-provenance-participant-type.json │ │ │ ├── ValueSet-us-core-provider-role.json │ │ │ ├── ValueSet-us-core-provider-specialty.json │ │ │ ├── ValueSet-us-core-smoking-status-observation-codes.json │ │ │ ├── ValueSet-us-core-usps-state.json │ │ │ ├── ValueSet-us-core-vaccines-cvx.json │ │ │ └── ig-r4.json │ │ └── testImplementationGuides-stu3 │ │ └── us-core │ │ ├── .index.json │ │ ├── AllergyIntolerance-example.json │ │ ├── Bundle-66c8856b-ba11-4876-8aa8-467aad8c11a2.json │ │ ├── Bundle-uscore-mo3.json │ │ ├── Bundle-uscore-ms3.json │ │ ├── CapabilityStatement-us-core-client.json │ │ ├── CapabilityStatement-us-core-server.json │ │ ├── CarePlan-colonoscopy.json │ │ ├── CareTeam-example.json │ │ ├── CodeSystem-careplan-category.json │ │ ├── CodeSystem-cdcrec.json │ │ ├── CodeSystem-condition-category.json │ │ ├── ConceptMap-ndc-cvx.json │ │ ├── Condition-example.json │ │ ├── Condition-hc1.json │ │ ├── Device-udi-1.json │ │ ├── DiagnosticReport-cbc.json │ │ ├── DiagnosticReport-metabolic-panel.json │ │ ├── DiagnosticReport-urinalysis.json │ │ ├── DocumentReference-episode-summary.json │ │ ├── Encounter-1036.json │ │ ├── Encounter-example-1.json │ │ ├── Goal-goal-1.json │ │ ├── Immunization-imm-1.json │ │ ├── ImplementationGuide-us-core-ig.json │ │ ├── Location-hl7east.json │ │ ├── Medication-uscore-med1.json │ │ ├── Medication-uscore-med2.json │ │ ├── MedicationRequest-uscore-mo1.json │ │ ├── MedicationRequest-uscore-mo2.json │ │ ├── MedicationStatement-uscore-ms1.json │ │ ├── MedicationStatement-uscore-ms2.json │ │ ├── Observation-blood-glucose.json │ │ ├── Observation-blood-pressure.json │ │ ├── Observation-bmi.json │ │ ├── Observation-bp-data-absent.json │ │ ├── Observation-bun.json │ │ ├── Observation-erythrocytes.json │ │ ├── Observation-head-circumference.json │ │ ├── Observation-heart-rate.json │ │ ├── Observation-height.json │ │ ├── Observation-hemoglobin.json │ │ ├── Observation-length.json │ │ ├── Observation-mchc.json │ │ ├── Observation-neutrophils.json │ │ ├── Observation-oxygen-saturation.json │ │ ├── Observation-respiratory-rate.json │ │ ├── Observation-serum-calcium.json │ │ ├── Observation-serum-chloride.json │ │ ├── Observation-serum-co2.json │ │ ├── Observation-serum-creatinine.json │ │ ├── Observation-serum-potassium.json │ │ ├── Observation-serum-sodium.json │ │ ├── Observation-serum-total-bilirubin.json │ │ ├── Observation-some-day-smoker.json │ │ ├── Observation-temperature.json │ │ ├── Observation-urine-bacteria.json │ │ ├── Observation-urine-bilirubin.json │ │ ├── Observation-urine-cells.json │ │ ├── Observation-urine-clarity.json │ │ ├── Observation-urine-color.json │ │ ├── Observation-urine-epi-cells.json │ │ ├── Observation-urine-glucose.json │ │ ├── Observation-urine-hemoglobin.json │ │ ├── Observation-urine-ketone.json │ │ ├── Observation-urine-leukocyte-esterase.json │ │ ├── Observation-urine-nitrite.json │ │ ├── Observation-urine-ph.json │ │ ├── Observation-urine-protein.json │ │ ├── Observation-urine-rbcs.json │ │ ├── Observation-urine-sediment.json │ │ ├── Observation-urine-wbcs.json │ │ ├── Observation-urobilinogen.json │ │ ├── Observation-usg.json │ │ ├── Observation-vitals-panel.json │ │ ├── Observation-weight.json │ │ ├── OperationDefinition-docref.json │ │ ├── Organization-acme-lab.json │ │ ├── Organization-example-organization-2.json │ │ ├── Organization-saint-luke-w-endpoint.json │ │ ├── Patient-example.json │ │ ├── Practitioner-practitioner-1.json │ │ ├── Practitioner-practitioner-2.json │ │ ├── Procedure-rehab.json │ │ ├── SearchParameter-us-core-ethnicity.json │ │ ├── SearchParameter-us-core-race.json │ │ ├── StructureDefinition-us-core-allergyintolerance.json │ │ ├── StructureDefinition-us-core-birthsex.json │ │ ├── StructureDefinition-us-core-careplan.json │ │ ├── StructureDefinition-us-core-careteam.json │ │ ├── StructureDefinition-us-core-condition.json │ │ ├── StructureDefinition-us-core-device.json │ │ ├── StructureDefinition-us-core-diagnosticreport.json │ │ ├── StructureDefinition-us-core-direct.json │ │ ├── StructureDefinition-us-core-documentreference.json │ │ ├── StructureDefinition-us-core-encounter.json │ │ ├── StructureDefinition-us-core-ethnicity.json │ │ ├── StructureDefinition-us-core-goal.json │ │ ├── StructureDefinition-us-core-immunization.json │ │ ├── StructureDefinition-us-core-location.json │ │ ├── StructureDefinition-us-core-medication.json │ │ ├── StructureDefinition-us-core-medicationrequest.json │ │ ├── StructureDefinition-us-core-medicationstatement.json │ │ ├── StructureDefinition-us-core-observationresults.json │ │ ├── StructureDefinition-us-core-organization.json │ │ ├── StructureDefinition-us-core-patient.json │ │ ├── StructureDefinition-us-core-practitioner.json │ │ ├── StructureDefinition-us-core-practitionerrole.json │ │ ├── StructureDefinition-us-core-procedure.json │ │ ├── StructureDefinition-us-core-profile-link.json │ │ ├── StructureDefinition-us-core-race.json │ │ ├── StructureDefinition-us-core-smokingstatus.json │ │ ├── ValueSet-detailed-ethnicity.json │ │ ├── ValueSet-detailed-race.json │ │ ├── ValueSet-omb-ethnicity-category.json │ │ ├── ValueSet-omb-race-category.json │ │ ├── ValueSet-simple-language.json │ │ ├── ValueSet-us-core-birthsex.json │ │ ├── ValueSet-us-core-careteam-provider-roles.json │ │ ├── ValueSet-us-core-condition-category.json │ │ ├── ValueSet-us-core-cvx.json │ │ ├── ValueSet-us-core-encounter-type.json │ │ ├── ValueSet-us-core-medication-codes.json │ │ ├── ValueSet-us-core-narrative-status.json │ │ ├── ValueSet-us-core-ndc-vaccine-codes.json │ │ ├── ValueSet-us-core-observation-ccdasmokingstatus.json │ │ ├── ValueSet-us-core-observation-value-codes.json │ │ ├── ValueSet-us-core-problem.json │ │ ├── ValueSet-us-core-procedure-code.json │ │ ├── ValueSet-us-core-procedure-icd10pcs.json │ │ ├── ValueSet-us-core-provider-role.json │ │ ├── ValueSet-us-core-provider-specialty.json │ │ ├── ValueSet-us-core-substance-ndfrt.json │ │ ├── ValueSet-us-core-substance-rxnorm.json │ │ ├── ValueSet-us-core-substance-sct.json │ │ ├── ValueSet-us-core-substance.json │ │ └── ig-r4.json ├── package.json ├── src │ ├── fhirWorksAppRegistry.ts │ ├── index.ts │ └── testData.ts └── tsconfig.json ├── imgs ├── awscliterminal.jpg ├── awscloudshell.jpg ├── chooseloggroups.jpg ├── createbucket.jpg ├── monitorexporttasks.jpg ├── searchlogsbytimerange.jpg ├── selectloggroup.jpg ├── successfullycreatedexporttask.jpg └── verifyexportins3bucket.jpg ├── rush.json ├── solutions ├── deployment │ ├── .dockerignore │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .npmignore │ ├── CHANGELOG.md │ ├── CODE_OF_CONDUCT.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── NOTICE │ ├── README.md │ ├── THIRD_PARTY_LICENSES │ ├── bin │ │ ├── cdk-infra.test.ts │ │ └── cdk-infra.ts │ ├── bulkExport │ │ ├── extractPatientCompartmentSearchParams.js │ │ ├── glueScripts │ │ │ └── export-script.py │ │ ├── index.ts │ │ ├── schema │ │ │ ├── compartmentdefinition-patient.3.0.2.json │ │ │ ├── compartmentdefinition-patient.4.0.1.json │ │ │ ├── patientCompartmentSearchParams.3.0.2.json │ │ │ ├── patientCompartmentSearchParams.4.0.1.json │ │ │ └── transitiveReferenceParams.json │ │ ├── state-machine-definition.yaml │ │ └── uploadGlueScriptsToS3.ts │ ├── cdk-nag-deny-list.yaml │ ├── cdk.json │ ├── compiledImplementationGuides │ │ └── gitkeep │ ├── config │ │ ├── heft.json │ │ ├── jest.config.json │ │ ├── rig.json │ │ └── typescript.json │ ├── lib │ │ ├── alarms.ts │ │ ├── backup.ts │ │ ├── bulkExport.ts │ │ ├── bulkExportStateMachine.ts │ │ ├── cdk-infra-stack.ts │ │ ├── cognito.ts │ │ ├── elasticsearch.ts │ │ ├── javaHapiValidator.ts │ │ ├── kms.ts │ │ └── subscriptions.ts │ ├── package.json │ ├── postman │ │ ├── Fhir.postman_collection.json │ │ ├── Fhir_Dev_Env.json │ │ ├── Fhir_Local_Env.json │ │ └── Fhir_Prod_Env.json │ ├── resources │ │ ├── architecture.png │ │ ├── billableperiod.png │ │ ├── kibanaurl.png │ │ ├── opensearchservice.png │ │ └── postman_body_request_settings.png │ ├── scripts │ │ ├── build_lambda.js │ │ ├── compile-igs.ts │ │ ├── create-postman-collection.ts │ │ ├── elasticsearch-operations.js │ │ ├── iam_policy.json │ │ ├── init-auth.py │ │ ├── provision-user.py │ │ ├── replay-ddbToES.js │ │ └── sort-key-migration.js │ ├── src │ │ ├── RBACRules.ts │ │ ├── config.ts │ │ ├── ddbToEsLambda │ │ │ └── index.ts │ │ ├── implementationGuides │ │ │ ├── IGCompiler.test.ts │ │ │ ├── IGCompiler.ts │ │ │ └── loadCompiledIGs.ts │ │ ├── index.ts │ │ ├── integration-tests │ │ │ ├── STU3_1_1UsCoreCapStatement.json │ │ │ ├── SubscriptionsHelper.ts │ │ │ ├── batchBundle.test.ts │ │ │ ├── binary.test.ts │ │ │ ├── bulkExport.test.ts │ │ │ ├── bulkExportTestHelper.ts │ │ │ ├── createGroupMembersBundle.json │ │ │ ├── createPatientPractitionerEncounterBundle.json │ │ │ ├── implementationGuides.test.ts │ │ │ ├── infrastructure │ │ │ │ ├── allowList-integTests.ts │ │ │ │ └── subscriptions-endpoint │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── README.md │ │ │ │ │ ├── src │ │ │ │ │ ├── app.js │ │ │ │ │ └── package.json │ │ │ │ │ └── template.yaml │ │ │ ├── multitenancy.test.ts │ │ │ ├── rbac-permission.test.ts │ │ │ ├── search.test.ts │ │ │ ├── subscriptions.test.ts │ │ │ ├── types.ts │ │ │ └── utils.ts │ │ ├── subscriptions │ │ │ ├── allowList.ts │ │ │ ├── matcherLambda │ │ │ │ └── index.ts │ │ │ ├── reaperLambda │ │ │ │ ├── index.ts │ │ │ │ ├── subscriptionReaper.test.ts │ │ │ │ └── subscriptionReaper.ts │ │ │ └── restHookLambda │ │ │ │ ├── allowListUtil.ts │ │ │ │ ├── index.ts │ │ │ │ ├── restHook.test.ts │ │ │ │ ├── restHook.ts │ │ │ │ └── restHookMultiTenant.test.ts │ │ └── updateSearchMappings │ │ │ └── index.ts │ └── tsconfig.json ├── documentation │ ├── CUSTOMIZE.md │ ├── FWoA-subscriptions.svg │ ├── MOVING-CLOUDWATCH-LOGS-TO-S3.md │ ├── SECURE_LOGGING.md │ ├── USING_BULK_DATA_EXPORT.md │ ├── USING_MULTI_TENANCY.md │ ├── USING_SUBSCRIPTIONS.md │ └── bulkExport.png └── smart-deployment │ ├── .dockerignore │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .npmrc │ ├── CHANGELOG.md │ ├── CODE_OF_CONDUCT.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── NOTICE │ ├── README.md │ ├── SMART_ON_FHIR_FAQ.MD │ ├── THIRD_PARTY_LICENSES │ ├── bin │ └── cdk-infra.ts │ ├── bulkExport │ ├── extractPatientCompartmentSearchParams.js │ ├── glueScripts │ │ └── export-script.py │ ├── index.ts │ ├── schema │ │ ├── compartmentdefinition-patient.3.0.2.json │ │ ├── compartmentdefinition-patient.4.0.1.json │ │ ├── patientCompartmentSearchParams.3.0.2.json │ │ ├── patientCompartmentSearchParams.4.0.1.json │ │ └── transitiveReferenceParams.json │ ├── state-machine-definition.yaml │ └── uploadGlueScriptsToS3.ts │ ├── cdk-nag-deny-list.yaml │ ├── cdk.json │ ├── compiledImplementationGuides │ └── gitkeep │ ├── config │ ├── heft.json │ ├── jest.config.json │ ├── rig.json │ └── typescript.json │ ├── package.json │ ├── postman │ ├── FHIR_SMART.postman_collection.json │ └── FHIR_SMART.postman_environment.json │ ├── resources │ ├── architecture-smart.png │ ├── oauth2-fwoa-flow.png │ └── postman_body_request_settings.png │ ├── scripts │ ├── build_lambda.js │ ├── compile-igs.ts │ ├── elasticsearch-operations.js │ ├── iam_policy.json │ └── sort-key-migration.js │ ├── src │ ├── authZConfig.ts │ ├── config.ts │ ├── ddbToEsLambda │ │ └── index.ts │ ├── implementationGuides │ │ ├── IGCompiler.test.ts │ │ ├── IGCompiler.ts │ │ └── loadCompiledIGs.ts │ ├── index.ts │ ├── integration-tests │ │ ├── STU3_1_1UsCoreCapStatement.json │ │ ├── SubscriptionsHelper.ts │ │ ├── batchBundle.test.ts │ │ ├── bulkExport.test.ts │ │ ├── bulkExportTestHelper.ts │ │ ├── createGroupMembersBundle.json │ │ ├── createPatientPractitionerEncounterBundle.json │ │ ├── implementationGuides.test.ts │ │ ├── infrastructure │ │ │ ├── allowList-integTests.ts │ │ │ └── subscriptions-endpoint │ │ │ │ ├── .gitignore │ │ │ │ ├── README.md │ │ │ │ ├── src │ │ │ │ ├── app.js │ │ │ │ └── package.json │ │ │ │ └── template.yaml │ │ ├── multitenancy.test.ts │ │ ├── search.test.ts │ │ ├── smartAuth.test.ts │ │ ├── subscriptions.test.ts │ │ ├── types.ts │ │ └── utils.ts │ ├── lib │ │ ├── alarms.ts │ │ ├── backup.ts │ │ ├── bulkExport.ts │ │ ├── bulkExportStateMachine.ts │ │ ├── cdk-infra-stack.ts │ │ ├── cdk-infra.test.ts │ │ ├── elasticsearch.ts │ │ ├── javaHapiValidator.ts │ │ ├── kms.ts │ │ └── subscriptions.ts │ ├── subscriptions │ │ ├── allowList.ts │ │ ├── matcherLambda │ │ │ └── index.ts │ │ ├── reaperLambda │ │ │ ├── index.ts │ │ │ ├── subscriptionReaper.test.ts │ │ │ └── subscriptionReaper.ts │ │ └── restHookLambda │ │ │ ├── allowListUtil.ts │ │ │ ├── index.ts │ │ │ ├── restHook.test.ts │ │ │ ├── restHook.ts │ │ │ └── restHookMultiTenant.test.ts │ └── updateSearchMappings │ │ └── index.ts │ └── tsconfig.json └── sonar-project.properties /.czrc: -------------------------------------------------------------------------------- 1 | { 2 | "path": "cz-conventional-changelog" 3 | } -------------------------------------------------------------------------------- /.gitallowed: -------------------------------------------------------------------------------- 1 | .github/workflows/* 2 | .gitallowed 3 | 4 | # This file matches because of "βrazil nut" (It's silly that git secrets also scans this file, so we cannot write βrazil with a regular "B") 5 | fwoa-utilities/javaHapiValidatorLambda/src/test/resources/** 6 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Don't allow people to merge changes to these generated files, because the result 2 | # may be invalid. You need to run "rush update" again. 3 | pnpm-lock.yaml merge=text 4 | shrinkwrap.yaml merge=binary 5 | npm-shrinkwrap.json merge=binary 6 | 7 | # Rush's JSON config files use JavaScript-style code comments. The rule below prevents pedantic 8 | # syntax highlighters such as GitHub's from highlighting these comments as errors. Your text editor 9 | # may also require a special configuration to allow comments in JSON. 10 | # 11 | # For more information, see this issue: https://github.com/microsoft/rushstack/issues/1088 12 | # 13 | *.json linguist-language=JSON-with-Comments 14 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @aws-solutions/wwps-psh-dev 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a bug report to help us improve 4 | title: '[Bug] insert summary' 5 | labels: bug 6 | assignees: '' 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Versions (please complete the following information):** 27 | 28 | - Release Version installed or commit hash [e.g. v1.0.3, 1edf4] 29 | 30 | 31 | 32 | **Additional context** 33 | Add any other context about the problem here. 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '[Feature Request] insert summary' 5 | labels: enhancement 6 | assignees: '' 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/miscellaneous.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Miscellaneous 3 | about: Ask a question or share something interesting 4 | title: '[Misc] insert summary' 5 | labels: customer-inquiry 6 | assignees: '' 7 | --- 8 | 9 | **What's on your mind?** 10 | Try to be descriptive about your questions/comments/suggestions. The magic is in the details. 11 | 12 | **Versions (please complete the following information):** 13 | 14 | - Release Version installed [e.g. v1.0.3] 15 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Issue #, if available: 2 | 3 | Description of changes: 4 | 5 | Checklist: 6 | 7 | 8 | 9 | - [ ] Have you successfully deployed to an AWS account with your changes? 10 | - [ ] Have you written new tests for your core changes, as applicable? 11 | - [ ] Did you add new integration tests? 12 | - [ ] Did you run integration tests with your changes? 13 | 14 | By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. 15 | -------------------------------------------------------------------------------- /.github/workflows/scripts/commitizen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | exec < /dev/tty && pwd && common/autoinstallers/commitizen/node_modules/.bin/cz --hook || true -------------------------------------------------------------------------------- /.npmpackagejsonlintignore: -------------------------------------------------------------------------------- 1 | **/implementationGuides/* 2 | **/subscriptions-endpoint/src/package.json 3 | **/cdk.out/* -------------------------------------------------------------------------------- /.npmpackagejsonlintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "npm-package-json-lint-config-default", 3 | "rules": { 4 | "require-repository": "error", 5 | "require-author": "error", 6 | "require-description": "error", 7 | "require-homepage": "error", 8 | "require-license": "error", 9 | "valid-values-license": ["error", ["Apache-2.0"]] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: true, 3 | htmlWhitespaceSensitivity: 'css', 4 | insertPragma: false, 5 | jsxSingleQuote: false, 6 | printWidth: 110, 7 | proseWrap: 'preserve', 8 | quoteProps: 'as-needed', 9 | requirePragma: false, 10 | semi: true, 11 | singleQuote: true, 12 | tabWidth: 2, 13 | trailingComma: 'none', 14 | useTabs: false 15 | }; 16 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | 3 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 4 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 5 | opensource-codeofconduct@amazon.com with any additional questions or comments. 6 | -------------------------------------------------------------------------------- /FHIR Works on AWS - Migration Tool User Guide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/FHIR Works on AWS - Migration Tool User Guide.pdf -------------------------------------------------------------------------------- /FHIR Works on AWS Implementation Guide - 24-MAR-2023 - v6.0.0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/FHIR Works on AWS Implementation Guide - 24-MAR-2023 - v6.0.0.pdf -------------------------------------------------------------------------------- /brazil.ion: -------------------------------------------------------------------------------- 1 | 'brazil_package_spec@1.0' 2 | 3 | common::{ 4 | name: "FHIR-Works-on-AWS", 5 | major_version: "1.0", 6 | 7 | dependencies: { 8 | default_closure: run, 9 | 10 | closures: { 11 | run: public::{ 12 | include: [self], 13 | }, 14 | }, 15 | }, 16 | 17 | build: { 18 | command: null, 19 | 20 | env: { 21 | PATH: [ 22 | (env PATH), 23 | ], 24 | }, 25 | 26 | outputs: { 27 | public_dir: null, 28 | private_dir: null, 29 | }, 30 | 31 | cleaned: [], 32 | }, 33 | } 34 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['./common/autoinstallers/commitlint/node_modules/@commitlint/config-conventional/index.js'] 3 | }; 4 | -------------------------------------------------------------------------------- /common/autoinstallers/commitizen/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "commitizen", 3 | "description": "commitizen auto installer", 4 | "version": "1.0.0", 5 | "private": true, 6 | "dependencies": { 7 | "commitizen": "^4.2.6" 8 | }, 9 | "pnpm": { 10 | "overrides": { 11 | "word-wrap": ">=1.2.4" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /common/autoinstallers/commitlint/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "commitlint", 3 | "description": "commitlint auto installer", 4 | "version": "1.0.0", 5 | "private": true, 6 | "dependencies": { 7 | "@commitlint/cli": "^17.4.2", 8 | "@commitlint/config-conventional": "^17.4.2" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /common/autoinstallers/rush-prettier/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rush-prettier", 3 | "description": "rush-prettier auto installer", 4 | "version": "1.0.0", 5 | "private": true, 6 | "dependencies": { 7 | "prettier": "^2.5.1", 8 | "pretty-quick": "^3.1.3" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-authz-rbac/notice-fixes_2023-04-10-18-45.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-authz-rbac", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-authz-rbac" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-authz-rbac/sevu-tasks-update-changelogs_2023-04-10-16-06.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-authz-rbac", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-authz-rbac" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-authz-smart/kcadette-docs-changelogs-mfa_2023-06-07-15-15.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-authz-smart", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-authz-smart" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-authz-smart/kcadette-docs-changelogs-mfa_2023-06-07-15-24.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-authz-smart", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-authz-smart" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-authz-smart/notice-fixes_2023-04-10-18-45.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-authz-smart", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-authz-smart" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-authz-smart/sevu-tasks-update-changelogs_2023-04-10-16-06.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-authz-smart", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-authz-smart" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-authz-smart/sukeev-feat-migrationTool_2023-05-31-18-38.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-authz-smart", 5 | "comment": "update axios version", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-authz-smart" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-interface/notice-fixes_2023-04-10-18-45.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-interface", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-interface" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-interface/sevu-tasks-update-changelogs_2023-04-10-16-06.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-interface", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-interface" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-persistence-ddb/notice-fixes_2023-04-10-18-45.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-persistence-ddb", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-persistence-ddb" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-persistence-ddb/sevu-tasks-update-changelogs_2023-04-10-16-06.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-persistence-ddb", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-persistence-ddb" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-routing/notice-fixes_2023-04-10-18-45.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-routing", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-routing" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-routing/sevu-tasks-update-changelogs_2023-04-10-16-06.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-routing", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-routing" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-search-es/kcadette-docs-changelogs-mfa_2023-06-07-15-24.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-search-es", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-search-es" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-search-es/notice-fixes_2023-04-10-18-45.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-search-es", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-search-es" 10 | } 11 | -------------------------------------------------------------------------------- /common/changes/@aws/fhir-works-on-aws-search-es/sevu-tasks-update-changelogs_2023-04-10-16-06.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@aws/fhir-works-on-aws-search-es", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@aws/fhir-works-on-aws-search-es" 10 | } 11 | -------------------------------------------------------------------------------- /common/config/rush/.npmrc: -------------------------------------------------------------------------------- 1 | # Rush uses this file to configure the NPM package registry during installation. It is applicable 2 | # to PNPM, NPM, and Yarn package managers. It is used by operations such as "rush install", 3 | # "rush update", and the "install-run.js" scripts. 4 | # 5 | # NOTE: The "rush publish" command uses .npmrc-publish instead. 6 | # 7 | # Before invoking the package manager, Rush will copy this file to the folder where installation 8 | # is performed. The copied file will omit any config lines that reference environment variables 9 | # that are undefined in that session; this avoids problems that would otherwise result due to 10 | # a missing variable being replaced by an empty string. 11 | # 12 | # * * * SECURITY WARNING * * * 13 | # 14 | # It is NOT recommended to store authentication tokens in a text file on a lab machine, because 15 | # other unrelated processes may be able to read the file. Also, the file may persist indefinitely, 16 | # for example if the machine loses power. A safer practice is to pass the token via an 17 | # environment variable, which can be referenced from .npmrc using ${} expansion. For example: 18 | # 19 | # //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN} 20 | # 21 | registry=https://registry.npmjs.org/ 22 | always-auth=false 23 | -------------------------------------------------------------------------------- /common/config/rush/.npmrc-publish: -------------------------------------------------------------------------------- 1 | # This config file is very similar to common/config/rush/.npmrc, except that .npmrc-publish 2 | # is used by the "rush publish" command, as publishing often involves different credentials 3 | # and registries than other operations. 4 | # 5 | # Before invoking the package manager, Rush will copy this file to "common/temp/publish-home/.npmrc" 6 | # and then temporarily map that folder as the "home directory" for the current user account. 7 | # This enables the same settings to apply for each project folder that gets published. The copied file 8 | # will omit any config lines that reference environment variables that are undefined in that session; 9 | # this avoids problems that would otherwise result due to a missing variable being replaced by 10 | # an empty string. 11 | # 12 | # * * * SECURITY WARNING * * * 13 | # 14 | # It is NOT recommended to store authentication tokens in a text file on a lab machine, because 15 | # other unrelated processes may be able to read the file. Also, the file may persist indefinitely, 16 | # for example if the machine loses power. A safer practice is to pass the token via an 17 | # environment variable, which can be referenced from .npmrc using ${} expansion. For example: 18 | # 19 | # //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN} 20 | # 21 | //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN} -------------------------------------------------------------------------------- /common/config/rush/.pnpmfile.cjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * When using the PNPM package manager, you can use pnpmfile.js to workaround 5 | * dependencies that have mistakes in their package.json file. (This feature is 6 | * functionally similar to Yarn's "resolutions".) 7 | * 8 | * For details, see the PNPM documentation: 9 | * https://pnpm.js.org/docs/en/hooks.html 10 | * 11 | * IMPORTANT: SINCE THIS FILE CONTAINS EXECUTABLE CODE, MODIFYING IT IS LIKELY TO INVALIDATE 12 | * ANY CACHED DEPENDENCY ANALYSIS. After any modification to pnpmfile.js, it's recommended to run 13 | * "rush update --full" so that PNPM will recalculate all version selections. 14 | */ 15 | module.exports = { 16 | hooks: { 17 | readPackage 18 | } 19 | }; 20 | 21 | /** 22 | * This hook is invoked during installation before a package's dependencies 23 | * are selected. 24 | * The `packageJson` parameter is the deserialized package.json 25 | * contents for the package that is about to be installed. 26 | * The `context` parameter provides a log() function. 27 | * The return value is the updated object. 28 | */ 29 | function readPackage(packageJson, context) { 30 | // // The karma types have a missing dependency on typings from the log4js package. 31 | // if (packageJson.name === '@types/karma') { 32 | // context.log('Fixed up dependencies for @types/karma'); 33 | // packageJson.dependencies['log4js'] = '0.6.38'; 34 | // } 35 | 36 | return packageJson; 37 | } 38 | -------------------------------------------------------------------------------- /common/config/rush/nonbrowser-approved-packages.json: -------------------------------------------------------------------------------- 1 | // DO NOT ADD COMMENTS IN THIS FILE. They will be lost when the Rush tool resaves it. 2 | { 3 | "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/approved-packages.schema.json", 4 | "packages": [] 5 | } 6 | -------------------------------------------------------------------------------- /common/config/rush/repo-state.json: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. 2 | { 3 | "pnpmShrinkwrapHash": "27f66bfccb6e383d9dad1bf50d4ec3e96a7d2f03", 4 | "preferredVersionsHash": "bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f" 5 | } 6 | -------------------------------------------------------------------------------- /common/config/rush/rush-plugins.json: -------------------------------------------------------------------------------- 1 | /** 2 | * This configuration file manages Rush's plugin feature. 3 | */ 4 | { 5 | "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugins.schema.json", 6 | "plugins": [ 7 | /** 8 | * Each item defines a plugin configuration used by Rush. 9 | */ 10 | // { 11 | // /** 12 | // * The name of the rush plugin package. 13 | // */ 14 | // "packageName": "@scope/my-rush-plugin", 15 | // /** 16 | // * The name of the plugin provided by rush plugin package 17 | // */ 18 | // "pluginName": "my-plugin-name", 19 | // /** 20 | // * Autoinstaller name used to install the plugin. 21 | // */ 22 | // "autoinstallerName": "plugins" 23 | // } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /common/git-hooks/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # This is an example Git hook for use with Rush. To enable this hook, rename this file 4 | # to "commit-msg" and then run "rush install", which will copy it from common/git-hooks 5 | # to the .git/hooks folder. 6 | # 7 | # TO LEARN MORE ABOUT GIT HOOKS 8 | # 9 | # The Git documentation is here: https://git-scm.com/docs/githooks 10 | # Some helpful resources: https://githooks.com 11 | # 12 | # ABOUT THIS EXAMPLE 13 | # 14 | # The commit-msg hook is called by "git commit" with one argument, the name of the file 15 | # that has the commit message. The hook should exit with non-zero status after issuing 16 | # an appropriate message if it wants to stop the commit. The hook is allowed to edit 17 | # the commit message file. 18 | 19 | # enforce conventional commits 20 | # INPUT_FILE=$1 21 | # START_LINE=`head -n1 $INPUT_FILE` 22 | # PATTERN="^(BREAKING CHANGE)|(feat)|(fix)|(build)|(chore)|(ci)|(docs)|(style)|(refactor)|(perf)|(test)(\(\w+\))?!?: .+" 23 | # if ! [[ "$START_LINE" =~ $PATTERN ]]; then 24 | # echo "Bad commit message, see example conventional commits: https://www.conventionalcommits.org/en/v1.0.0/" 25 | # exit 1 26 | # fi 27 | INPUT_FILE=$1 28 | node common/scripts/install-run-rush.js commitlint --edit "$INPUT_FILE" 29 | -------------------------------------------------------------------------------- /common/git-hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Called by "git commit" with no arguments. The hook should 3 | # exit with non-zero status after issuing an appropriate message if 4 | # it wants to stop the commit. 5 | 6 | # Invoke the "rush prettier" custom command to reformat files whenever they 7 | # are committed. The command is defined in common/config/rush/command-line.json 8 | # and uses the "rush-prettier" autoinstaller. 9 | 10 | node common/scripts/install-run-rush.js git-secrets-scan || exit $? 11 | # node common/scripts/install-run-rush.js viperlight-scan || exit $? 12 | node common/scripts/install-run-rush.js prettier || exit $? 13 | # node common/scripts/install-run-rush.js common-coverage-make-badge || exit $? 14 | node common/scripts/install-run-rush.js sort-package-json && git add **/package.json || exit $? -------------------------------------------------------------------------------- /common/git-hooks/prepare-commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | node common/scripts/install-run-rush.js commitizen || echo $? -------------------------------------------------------------------------------- /common/scripts/install-run-rushx.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 3 | // See the @microsoft/rush package's LICENSE file for license information. 4 | Object.defineProperty(exports, "__esModule", { value: true }); 5 | // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. 6 | // 7 | // This script is intended for usage in an automated build environment where the Rush command may not have 8 | // been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush 9 | // specified in the rush.json configuration file (if not already installed), and then pass a command-line to the 10 | // rushx command. 11 | // 12 | // An example usage would be: 13 | // 14 | // node common/scripts/install-run-rushx.js custom-command 15 | // 16 | // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ 17 | require("./install-run-rush"); 18 | //# sourceMappingURL=install-run-rushx.js.map -------------------------------------------------------------------------------- /core/eslint-custom/.eslintignore: -------------------------------------------------------------------------------- 1 | .eslintrc.js 2 | node_modules 3 | lib -------------------------------------------------------------------------------- /core/eslint-custom/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This is a workaround for https://github.com/eslint/eslint/issues/3458 2 | require('@rushstack/eslint-config/patch/modern-module-resolution'); 3 | 4 | module.exports = { 5 | plugins: ['security', 'import'], 6 | extends: [ 7 | '@rushstack/eslint-config/profile/node', 8 | '@rushstack/eslint-config/mixins/tsdoc', 9 | 'plugin:security/recommended', 10 | 'plugin:import/recommended' 11 | ], 12 | rules: { 13 | 'import/no-unresolved': ['off'], 14 | 'import/named': ['off'], 15 | 'import/order': [ 16 | 'error', 17 | { 18 | alphabetize: { 19 | order: 'asc', 20 | caseInsensitive: true 21 | }, 22 | groups: ['builtin', 'external', 'parent', 'sibling'] 23 | } 24 | ], 25 | 'import/newline-after-import': ['error'] 26 | }, 27 | parserOptions: { tsconfigRootDir: __dirname } 28 | }; 29 | -------------------------------------------------------------------------------- /core/eslint-custom/README.md: -------------------------------------------------------------------------------- 1 | # FWoA Core ESLint Config Custom 2 | 3 | ⚠️ $\textcolor{red}{\text{Experimental}}$ ⚠️ : Not for use in any critical, production, or otherwise important deployments 4 | 5 | ## Description 6 | 7 | Custom ESLint rules 8 | 9 | ## Usage 10 | 11 | 1. Update your package.json: 12 | 13 | ``` 14 | "devDependencies": { 15 | . 16 | . 17 | "@aws/eslint-config-fwoa-core-eslint-custom": "workspace:*" 18 | } 19 | ``` 20 | 21 | 2. Update your eslintrc.js: 22 | 23 | ``` 24 | // This is a workaround for https://github.com/eslint/eslint/issues/3458 25 | require('@rushstack/eslint-config/patch/modern-module-resolution'); 26 | 27 | module.exports = { 28 | extends: [ 29 | '@aws/workbench-core-eslint-custom' 30 | ], 31 | parserOptions: { tsconfigRootDir: __dirname } 32 | }; 33 | ``` 34 | -------------------------------------------------------------------------------- /core/eslint-custom/config/jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rushstack/heft-node-rig/profiles/default/config/jest.config.json", 3 | "collectCoverage": true 4 | } 5 | -------------------------------------------------------------------------------- /core/eslint-custom/config/rig.json: -------------------------------------------------------------------------------- 1 | // The "rig.json" file directs tools to look for their config files in an external package. 2 | // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package 3 | { 4 | "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", 5 | 6 | /** 7 | * (Required) The name of the rig package to inherit from. 8 | * It should be an NPM package name with the "-rig" suffix. 9 | */ 10 | "rigPackageName": "@rushstack/heft-node-rig" 11 | 12 | /** 13 | * (Optional) Selects a config profile from the rig package. The name must consist of 14 | * lowercase alphanumeric words separated by hyphens, for example "sample-profile". 15 | * If omitted, then the "default" profile will be used." 16 | */ 17 | // "rigProfile": "your-profile-name" 18 | } 19 | -------------------------------------------------------------------------------- /core/eslint-custom/src/custom-eslint.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | /* eslint-disable @typescript-eslint/no-explicit-any */ 7 | import { importConvention } from './rules/import-convention'; 8 | 9 | const rules: any = Object.assign({}, importConvention.rules); 10 | 11 | export const customESLint: any = { 12 | plugins: ['security', 'import'], 13 | extends: [ 14 | '@rushstack/eslint-config/profile/node', 15 | '@rushstack/eslint-config/mixins/tsdoc', 16 | 'plugin:security/recommended', 17 | 'plugin:import/recommended', 18 | 'plugin:import/typescript' 19 | ], 20 | rules: { ...rules, '@typescript-eslint/naming-convention': 'off' }, 21 | settings: { 22 | 'import/parsers': { 23 | '@typescript-eslint/parser': ['.ts', '.tsx'] 24 | }, 25 | 'import/resolver': { 26 | typescript: { 27 | alwaysTryTypes: true 28 | } 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /core/eslint-custom/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { customESLint } from './custom-eslint'; 7 | 8 | export = customESLint; 9 | -------------------------------------------------------------------------------- /core/eslint-custom/src/rules/import-convention.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 7 | export const importConvention: any = { 8 | rules: { 9 | 'import/no-unresolved': ['off'], 10 | 'import/named': ['off'], 11 | 'import/order': [ 12 | 'error', 13 | { 14 | alphabetize: { 15 | order: 'asc', 16 | caseInsensitive: true 17 | }, 18 | groups: ['builtin', 'external', 'parent', 'sibling'] 19 | } 20 | ], 21 | 'import/newline-after-import': ['error'] 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /core/eslint-custom/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/tsconfig", 3 | "extends": "./node_modules/@rushstack/heft-node-rig/profiles/default/tsconfig-base.json", 4 | "compilerOptions": { 5 | "types": ["heft-jest", "node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /deployment/cdk-solution-helper/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cdk-solution-helper", 3 | "version": "0.1.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "cdk-solution-helper", 9 | "version": "0.1.0", 10 | "license": "Apache-2.0", 11 | "dependencies": { 12 | "fs": "0.0.1-security" 13 | }, 14 | "devDependencies": { 15 | "fs": "0.0.1-security" 16 | } 17 | }, 18 | "node_modules/fs": { 19 | "version": "0.0.1-security", 20 | "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", 21 | "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==", 22 | "dev": true 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /deployment/cdk-solution-helper/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cdk-solution-helper", 3 | "description": "cdk-solution-helper", 4 | "version": "0.1.0", 5 | "devDependencies": { 6 | "fs": "0.0.1-security" 7 | }, 8 | "dependencies": { 9 | "fs": "0.0.1-security" 10 | }, 11 | "license": "Apache-2.0" 12 | } 13 | -------------------------------------------------------------------------------- /deployment/run-unit-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This assumes all of the OS-level configuration has been completed and git repo has already been cloned 4 | # 5 | # This script should be run from the repo's deployment directory 6 | # cd deployment 7 | # ./run-unit-tests.sh 8 | # 9 | 10 | # Get reference for all important folders 11 | template_dir="$PWD" 12 | source_dir="$template_dir/../fwoa-core/interface" 13 | 14 | echo "------------------------------------------------------------------------------" 15 | echo "Install packages" 16 | echo "------------------------------------------------------------------------------" 17 | npm install -g @microsoft/rush 18 | npm install -g pnpm 19 | npm install -g aws-cdk@2.46.0 20 | git submodule update --init --recursive --remote 21 | echo "------------------------------------------------------------------------------" 22 | echo "Install Run Unit Tests" 23 | echo "------------------------------------------------------------------------------" 24 | cd $source_dir 25 | rush purge 26 | rush update 27 | rush build-test 28 | echo "Test Complete" -------------------------------------------------------------------------------- /deployment/solution_config: -------------------------------------------------------------------------------- 1 | SOLUTION_ID='SO0128' 2 | SOLUTION_NAME='fhir-works-on-aws' 3 | SOLUTION_TRADEMARKEDNAME='fhir-works-on-aws' 4 | -------------------------------------------------------------------------------- /fwoa-core/authz-rbac/.eslintignore: -------------------------------------------------------------------------------- 1 | .eslintrc.js 2 | node_modules 3 | lib 4 | temp -------------------------------------------------------------------------------- /fwoa-core/authz-rbac/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This is a workaround for https://github.com/eslint/eslint/issues/3458 2 | require('@rushstack/eslint-config/patch/modern-module-resolution'); 3 | 4 | module.exports = { 5 | extends: ['@aws/eslint-config-fwoa-eslint-custom'], 6 | parserOptions: { tsconfigRootDir: __dirname }, 7 | overrides: [ 8 | { 9 | files: ['*.ts'], 10 | rules: { 11 | '@typescript-eslint/no-explicit-any': 'off', 12 | '@typescript-eslint/explicit-member-accessibility': 'off', 13 | 'security/detect-object-injection': 'off', 14 | '@typescript-eslint/explicit-function-return-type': 'off', 15 | 'import/namespace': 'off' 16 | } 17 | } 18 | ] 19 | }; 20 | -------------------------------------------------------------------------------- /fwoa-core/authz-rbac/.npmignore: -------------------------------------------------------------------------------- 1 | # Don't include original .ts files when doing `npm pack` 2 | *.ts 3 | !*.template.ts 4 | !*.d.ts 5 | coverage 6 | .nyc_output 7 | *.tgz 8 | 9 | src 10 | dist 11 | *.tsbuildinfo 12 | tsconfig.json 13 | .eslintrc.js 14 | .eslintignore 15 | .prettierrc.js 16 | .github 17 | CODE_OF_CONDUCT.md 18 | CONTRIBUTING.md 19 | -------------------------------------------------------------------------------- /fwoa-core/authz-rbac/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | 3 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 4 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 5 | opensource-codeofconduct@amazon.com with any additional questions or comments. 6 | -------------------------------------------------------------------------------- /fwoa-core/authz-rbac/config/jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rushstack/heft-node-rig/profiles/default/config/jest.config.json", 3 | "collectCoverage": true, 4 | "coverageThreshold": { 5 | "global": { 6 | "branches": 70, 7 | "functions": 70, 8 | "lines": 70, 9 | "statements": 70 10 | } 11 | }, 12 | "coveragePathIgnorePatterns": ["/src/index.ts"], 13 | "coverageReporters": ["json-summary", "json", "lcov", "text"] 14 | } 15 | -------------------------------------------------------------------------------- /fwoa-core/authz-rbac/config/rig.json: -------------------------------------------------------------------------------- 1 | // The "rig.json" file directs tools to look for their config files in an external package. 2 | // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package 3 | { 4 | "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", 5 | 6 | /** 7 | * (Required) The name of the rig package to inherit from. 8 | * It should be an NPM package name with the "-rig" suffix. 9 | */ 10 | "rigPackageName": "@rushstack/heft-node-rig" 11 | 12 | /** 13 | * (Optional) Selects a config profile from the rig package. The name must consist of 14 | * lowercase alphanumeric words separated by hyphens, for example "sample-profile". 15 | * If omitted, then the "default" profile will be used." 16 | */ 17 | // "rigProfile": "your-profile-name" 18 | } 19 | -------------------------------------------------------------------------------- /fwoa-core/authz-rbac/src/RBACConfig.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { TypeOperation, SystemOperation } from '@aws/fhir-works-on-aws-interface'; 7 | 8 | export interface Rule { 9 | operations: (TypeOperation | SystemOperation)[]; 10 | resources: string[]; // This will be able to support any type of resource 11 | } 12 | 13 | export interface GroupRule { 14 | [groupName: string]: Rule; 15 | } 16 | 17 | export interface RBACConfig { 18 | version: number; 19 | groupRules: GroupRule; 20 | } 21 | -------------------------------------------------------------------------------- /fwoa-core/authz-rbac/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | export * from './RBACConfig'; 6 | export * from './RBACHandler'; 7 | -------------------------------------------------------------------------------- /fwoa-core/authz-rbac/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/tsconfig", 3 | "extends": "./node_modules/@rushstack/heft-node-rig/profiles/default/tsconfig-base.json", 4 | "compilerOptions": { 5 | "types": ["heft-jest", "node"], 6 | "target": "es2019", // Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. 7 | "lib": ["es2019"], 8 | "module": "commonjs", // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 9 | "strict": true, // // Enable all strict type-checking options. 10 | "esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 11 | "forceConsistentCasingInFileNames": true, // Disallow inconsistently-cased references to the same file. 12 | "outDir": "lib", 13 | "declaration": true, 14 | "sourceMap": true, 15 | "resolveJsonModule": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "*": ["node_modules/*"] 19 | } 20 | }, 21 | "include": ["src/**/*"] 22 | } 23 | -------------------------------------------------------------------------------- /fwoa-core/authz-smart/.eslintignore: -------------------------------------------------------------------------------- 1 | .eslintrc.js 2 | node_modules 3 | lib 4 | temp -------------------------------------------------------------------------------- /fwoa-core/authz-smart/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This is a workaround for https://github.com/eslint/eslint/issues/3458 2 | require('@rushstack/eslint-config/patch/modern-module-resolution'); 3 | 4 | module.exports = { 5 | extends: ['@aws/eslint-config-fwoa-eslint-custom'], 6 | parserOptions: { tsconfigRootDir: __dirname }, 7 | ignorePatterns: ['src/smartAuthorizationHelper.test.ts', 'scripts/generateResourceReferenceMatrixFile.ts'], 8 | overrides: [ 9 | { 10 | files: ['*.ts'], 11 | rules: { 12 | '@typescript-eslint/no-explicit-any': 'off', 13 | '@typescript-eslint/explicit-member-accessibility': 'off', 14 | 'security/detect-object-injection': 'off', 15 | '@typescript-eslint/ban-types': 'off', 16 | '@typescript-eslint/explicit-function-return-type': 'off', 17 | '@rushstack/typedef-var': 'off', 18 | '@typescript-eslint/typedef': 'off', 19 | 'tsdoc/syntax': 'off', 20 | '@typescript-eslint/consistent-type-assertions': 'off', 21 | 'security/detect-non-literal-regexp': 'off', 22 | 'security/detect-unsafe-regex': 'off', 23 | '@rushstack/no-new-null': 'off', 24 | '@rushstack/security/no-unsafe-regexp': 'off', 25 | 'import/no-named-as-default-member': 'off', 26 | '@typescript-eslint/no-unused-vars': 'off' 27 | } 28 | }, 29 | { 30 | files: ['src/smartHandler.test.ts'], 31 | rules: { 32 | 'max-lines': 'off' 33 | } 34 | } 35 | ] 36 | }; 37 | -------------------------------------------------------------------------------- /fwoa-core/authz-smart/.npmignore: -------------------------------------------------------------------------------- 1 | # Don't include original .ts files when doing `npm pack` 2 | *.ts 3 | !*.template.ts 4 | !*.d.ts 5 | coverage 6 | .nyc_output 7 | *.tgz 8 | scripts/ 9 | 10 | src 11 | dist 12 | *.tsbuildinfo 13 | tsconfig.json 14 | .eslintrc.js 15 | .eslintignore 16 | .prettierrc.js 17 | .github 18 | CODE_OF_CONDUCT.md 19 | CONTRIBUTING.md 20 | -------------------------------------------------------------------------------- /fwoa-core/authz-smart/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | 3 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact opensource-codeofconduct@amazon.com with any additional questions or comments. 4 | -------------------------------------------------------------------------------- /fwoa-core/authz-smart/config/jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rushstack/heft-node-rig/profiles/default/config/jest.config.json", 3 | "collectCoverage": true, 4 | "coverageThreshold": { 5 | "global": { 6 | "branches": 70, 7 | "functions": 50, 8 | "lines": 70, 9 | "statements": 70 10 | } 11 | }, 12 | "coveragePathIgnorePatterns": ["/src/comboTest/"], 13 | "testPathIgnorePatterns": [ 14 | "/src/comboTest/__snapshots__/", 15 | "/node_modules/", 16 | "/src/comboTest/testCaseUtil.test.ts" 17 | ], 18 | "coverageReporters": ["json-summary", "json", "lcov", "text"], 19 | "moduleNameMapper": { 20 | "^jose/(.*)$": "/node_modules/jose/dist/node/cjs/$1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /fwoa-core/authz-smart/config/rig.json: -------------------------------------------------------------------------------- 1 | // The "rig.json" file directs tools to look for their config files in an external package. 2 | // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package 3 | { 4 | "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", 5 | 6 | /** 7 | * (Required) The name of the rig package to inherit from. 8 | * It should be an NPM package name with the "-rig" suffix. 9 | */ 10 | "rigPackageName": "@rushstack/heft-node-rig" 11 | 12 | /** 13 | * (Optional) Selects a config profile from the rig package. The name must consist of 14 | * lowercase alphanumeric words separated by hyphens, for example "sample-profile". 15 | * If omitted, then the "default" profile will be used." 16 | */ 17 | // "rigProfile": "your-profile-name" 18 | } 19 | -------------------------------------------------------------------------------- /fwoa-core/authz-smart/src/comboTest/document/combo-test-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/fwoa-core/authz-smart/src/comboTest/document/combo-test-process.png -------------------------------------------------------------------------------- /fwoa-core/authz-smart/src/comboTest/document/param-generation-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/fwoa-core/authz-smart/src/comboTest/document/param-generation-example.png -------------------------------------------------------------------------------- /fwoa-core/authz-smart/src/comboTest/paramsDefinition/VerifyAccessToken-BulkDataAuth-definition.txt: -------------------------------------------------------------------------------- 1 | [System] 2 | Name: VerifyAccessToken-BulkDataAuth 3 | 4 | [Parameter] 5 | patientContext(enum): patientIdentity,N/A 6 | fhirUser(enum): practitionerFhirUser,patientFhirUser,N/A 7 | operation(enum): read,delete 8 | BulkDataAuth.operation(enum): initiate-export,get-status-export,cancel-export 9 | BulkDataAuth.exportType(enum): system,group,patient 10 | fhirServiceBaseUrl(enum): matchUrl,nonMatchUrl 11 | isUserScopeAllowedForSystemExport(enum): true,false 12 | patient/Patient.read(enum): patient/Patient.read,N/A 13 | patient/*.read(enum): patient/*.read,N/A 14 | user/Patient.read(enum): user/Patient.read,N/A 15 | user/*.read(enum): user/*.read,N/A 16 | system/Patient.read(enum): system/Patient.read,N/A 17 | system/*.read(enum): system/*.read,N/A 18 | 19 | [Constraint] -------------------------------------------------------------------------------- /fwoa-core/authz-smart/src/comboTest/paramsDefinition/authorizeAndFilterReadResponse-definition.txt: -------------------------------------------------------------------------------- 1 | [System] 2 | Name: authorizeAndFilterReadResponse 3 | 4 | [Parameter] 5 | patientContext(enum): patientIdentity, N/A 6 | fhirUser(enum): practitionerFhirUser,patientFhirUser,N/A 7 | operation(enum): search-type, search-system, history-type, history-system, read 8 | fhirServiceBaseUrl(enum): matchUrl,nonMatchUrl 9 | patient/Patient.read(enum): patient/Patient.read,N/A 10 | patient/MedicationRequest.read(enum): patient/MedicationRequest.read,N/A 11 | patient/Condition.read(enum): patient/Condition.read,N/A 12 | user/Patient.read(enum): user/Patient.read,N/A 13 | user/MedicationRequest.read(enum): user/MedicationRequest.read,N/A 14 | user/Condition.read(enum): user/Condition.read,N/A 15 | system/Patient.read(enum): system/Patient.read,N/A 16 | system/MedicationRequest.read(enum): system/MedicationRequest.read,N/A 17 | system/Condition.read(enum): system/Condition.read,N/A 18 | matchMedicationRequest: matchMedicationRequest, N/A 19 | unmatchCondition: unmatchCondition, N/A 20 | matchPatient: matchPatient, N/A 21 | unmatchPatient: unmatchPatient, N/A 22 | 23 | [Constraint] -------------------------------------------------------------------------------- /fwoa-core/authz-smart/src/comboTest/paramsDefinition/isBundleRequestAuthorized-definition.txt: -------------------------------------------------------------------------------- 1 | [System] 2 | Name: isBundleRequestAuthorized 3 | 4 | [Parameter] 5 | patientContext(enum): patientIdentity, N/A 6 | fhirUser(enum): practitionerFhirUser,patientFhirUser,N/A 7 | fhirServiceBaseUrl(enum): matchUrl,nonMatchUrl 8 | patient/Patient.read(enum): patient/Patient.read,N/A 9 | patient/Patient.write(enum): patient/Patient.write,N/A 10 | patient/Observation.read(enum): patient/Observation.read,N/A 11 | patient/Observation.write(enum): patient/Observation.write,N/A 12 | patient/Condition.read(enum): patient/Condition.read,N/A 13 | patient/Condition.write(enum): patient/Condition.write,N/A 14 | user/Patient.read(enum): user/Patient.read,N/A 15 | user/Patient.write(enum): user/Patient.write,N/A 16 | user/Observation.read(enum): user/Observation.read,N/A 17 | user/Observation.write(enum): user/Observation.write,N/A 18 | user/Condition.read(enum): user/Condition.read,N/A 19 | user/Condition.write(enum): user/Condition.write,N/A 20 | system/Patient.read(enum): system/Patient.read,N/A 21 | system/Patient.write(enum): system/Patient.write,N/A 22 | system/Observation.read(enum): system/Observation.read,N/A 23 | system/Observation.write(enum): system/Observation.write,N/A 24 | system/Condition.read(enum): system/Condition.read,N/A 25 | system/Condition.write(enum): system/Condition.write,N/A 26 | 27 | [Constraint] -------------------------------------------------------------------------------- /fwoa-core/authz-smart/src/comboTest/paramsDefinition/isWriteRequestAuthorized-definition.txt: -------------------------------------------------------------------------------- 1 | [System] 2 | Name: isWriteRequestAuthorized 3 | 4 | [Parameter] 5 | patientContext(enum): patientIdentity, N/A 6 | fhirUser(enum): practitionerFhirUser,patientFhirUser,N/A 7 | operation(enum): create, update, patch, delete 8 | fhirServiceBaseUrl(enum): matchUrl,nonMatchUrl 9 | resourceBody: matchObservation, unmatchCondition, matchPatient, unmatchPatient, patientReferencePractitioner 10 | patient/Patient.write(enum): patient/Patient.write,N/A 11 | patient/Observation.write(enum): patient/Observation.write,N/A 12 | patient/Observation.read(enum): patient/Observation.read,N/A 13 | patient/Condition.write(enum): patient/Condition.write,N/A 14 | user/Patient.write(enum): user/Patient.write,N/A 15 | user/Patient.read(enum): user/Patient.read,N/A 16 | user/Observation.write(enum): user/Observation.write,N/A 17 | user/Condition.write(enum): user/Condition.write,N/A 18 | system/Patient.write(enum): system/Patient.write,N/A 19 | system/Observation.write(enum): system/Observation.write,N/A 20 | system/Condition.write(enum): system/Condition.write,N/A 21 | 22 | [Constraint] -------------------------------------------------------------------------------- /fwoa-core/authz-smart/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | export * from './smartConfig'; 6 | export * from './smartHandler'; 7 | -------------------------------------------------------------------------------- /fwoa-core/authz-smart/src/loggerBuilder.ts: -------------------------------------------------------------------------------- 1 | import { makeLogger } from '@aws/fhir-works-on-aws-interface'; 2 | 3 | const componentLogger = makeLogger({ 4 | component: 'auth-smart' 5 | }); 6 | 7 | export default function getComponentLogger(): any { 8 | return componentLogger; 9 | } 10 | -------------------------------------------------------------------------------- /fwoa-core/authz-smart/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/tsconfig", 3 | "extends": "./node_modules/@rushstack/heft-node-rig/profiles/default/tsconfig-base.json", 4 | "compilerOptions": { 5 | "types": ["heft-jest", "node"], 6 | "target": "es2019", // Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. 7 | "module": "commonjs", // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 8 | "strict": true, // // Enable all strict type-checking options. 9 | "esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 10 | "forceConsistentCasingInFileNames": true, // Disallow inconsistently-cased references to the same file. 11 | "outDir": "lib", 12 | "declaration": true, 13 | "sourceMap": true, 14 | "resolveJsonModule": true, 15 | "baseUrl": ".", 16 | "lib": ["ES2019", "DOM"] 17 | }, 18 | "include": ["src/**/*"] 19 | } 20 | -------------------------------------------------------------------------------- /fwoa-core/interface/.eslintignore: -------------------------------------------------------------------------------- 1 | .eslintrc.js 2 | node_modules 3 | lib 4 | temp -------------------------------------------------------------------------------- /fwoa-core/interface/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This is a workaround for https://github.com/eslint/eslint/issues/3458 2 | require('@rushstack/eslint-config/patch/modern-module-resolution'); 3 | 4 | module.exports = { 5 | extends: ['@aws/eslint-config-fwoa-eslint-custom'], 6 | parserOptions: { tsconfigRootDir: __dirname } 7 | }; 8 | -------------------------------------------------------------------------------- /fwoa-core/interface/.npmignore: -------------------------------------------------------------------------------- 1 | # Don't include original .ts files when doing `npm pack` 2 | *.ts 3 | !*.template.ts 4 | !*.d.ts 5 | coverage 6 | .nyc_output 7 | *.tgz 8 | 9 | src 10 | dist 11 | *.tsbuildinfo 12 | tsconfig.json 13 | .eslintrc.js 14 | .eslintignore 15 | .prettierrc.js 16 | .github 17 | CODE_OF_CONDUCT.md 18 | CONTRIBUTING.md 19 | CODEOWNERS 20 | openapi.yaml 21 | -------------------------------------------------------------------------------- /fwoa-core/interface/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | 3 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 4 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 5 | opensource-codeofconduct@amazon.com with any additional questions or comments. 6 | -------------------------------------------------------------------------------- /fwoa-core/interface/config/jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rushstack/heft-node-rig/profiles/default/config/jest.config.json", 3 | "collectCoverage": true, 4 | "coverageThreshold": { 5 | "global": { 6 | "branches": 70, 7 | "functions": 50, 8 | "lines": 70, 9 | "statements": 70 10 | } 11 | }, 12 | "coveragePathIgnorePatterns": [ 13 | "/src/errors", 14 | "/src/index.ts", 15 | "/src/constants.ts", 16 | "/src/resourceMeta.ts", 17 | "/src/stubs.ts", 18 | "/src/loggerBuilder.ts", 19 | "/src/encryptedLoggerBuilder.ts" 20 | ], 21 | "coverageReporters": ["json-summary", "json", "lcov", "text"] 22 | } 23 | -------------------------------------------------------------------------------- /fwoa-core/interface/config/rig.json: -------------------------------------------------------------------------------- 1 | // The "rig.json" file directs tools to look for their config files in an external package. 2 | // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package 3 | { 4 | "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", 5 | 6 | /** 7 | * (Required) The name of the rig package to inherit from. 8 | * It should be an NPM package name with the "-rig" suffix. 9 | */ 10 | "rigPackageName": "@rushstack/heft-node-rig" 11 | 12 | /** 13 | * (Optional) Selects a config profile from the rig package. The name must consist of 14 | * lowercase alphanumeric words separated by hyphens, for example "sample-profile". 15 | * If omitted, then the "default" profile will be used." 16 | */ 17 | // "rigProfile": "your-profile-name" 18 | } 19 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/capabilities.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { FhirVersion } from './constants'; 7 | import { GenericResponse } from './genericResponse'; 8 | 9 | // https://www.hl7.org/fhir/http.html#capabilities 10 | export type CapabilityMode = 'full' | 'normative' | 'terminology'; 11 | 12 | export interface CapabilitiesRequest { 13 | fhirVersion: FhirVersion; 14 | mode: CapabilityMode; 15 | } 16 | 17 | export interface Capabilities { 18 | /** 19 | * Return the capabilities statement. This specifies what the server supports 20 | * https://www.hl7.org/fhir/capabilitystatement-definitions.html#CapabilityStatement.format 21 | */ 22 | capabilities(request: CapabilitiesRequest): Promise; 23 | } 24 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/encryptedLoggerBuilder.ts: -------------------------------------------------------------------------------- 1 | // import _ from 'lodash'; 2 | import { createLogger, Logger } from 'winston'; 3 | import Transport from 'winston-transport'; 4 | import { encryptSelectedField, runLoggerLevel } from './loggerUtilities'; 5 | 6 | class SimpleEncryptConsole extends Transport { 7 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 8 | public async log(info: any, callback: () => void): Promise { 9 | try { 10 | setImmediate(() => this.emit('logged', info)); 11 | // encrypt 12 | const encryptedMessage = await encryptSelectedField(info); 13 | 14 | const msg = [info.meta, JSON.stringify(encryptedMessage, null, ' ')]; 15 | if (info[Symbol.for('splat')]) { 16 | msg.push(...info[Symbol.for('splat')]); 17 | } 18 | runLoggerLevel(info, msg); 19 | if (callback) { 20 | callback(); 21 | } 22 | } catch (error) { 23 | console.error(error); 24 | } 25 | } 26 | } 27 | 28 | export function makeEncryptLogger( 29 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 30 | metadata?: any, 31 | logLevel?: string 32 | ): Logger { 33 | return createLogger({ 34 | level: logLevel ?? process.env.LOG_LEVEL, 35 | transports: [new SimpleEncryptConsole()], 36 | defaultMeta: { meta: metadata } 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/errors/BadRequestError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | // eslint-disable-next-line import/prefer-default-export 7 | /* eslint-disable @typescript-eslint/explicit-member-accessibility */ 8 | export class BadRequestError extends Error { 9 | readonly isBadRequestError: boolean; 10 | 11 | // eslint-disable-next-line @typescript-eslint/typedef 12 | constructor(message = 'Bad Request') { 13 | // Node Error class requires passing a string message to the parent class 14 | super(message); 15 | Object.setPrototypeOf(this, BadRequestError.prototype); 16 | this.name = this.constructor.name; 17 | this.isBadRequestError = true; 18 | } 19 | } 20 | export function isBadRequestError(error: unknown): error is BadRequestError { 21 | return Boolean(error) && (error as BadRequestError).isBadRequestError === true; 22 | } 23 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/errors/InvalidResourceError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | /* eslint-disable @typescript-eslint/explicit-member-accessibility */ 6 | // eslint-disable-next-line import/prefer-default-export 7 | export class InvalidResourceError extends Error { 8 | readonly isInvalidResourceError: boolean; 9 | 10 | // eslint-disable-next-line @typescript-eslint/typedef 11 | constructor(message = 'Invalid Resource') { 12 | // Node Error class requires passing a string message to the parent class 13 | super(message); 14 | Object.setPrototypeOf(this, InvalidResourceError.prototype); 15 | this.isInvalidResourceError = true; 16 | this.name = this.constructor.name; 17 | } 18 | } 19 | export function isInvalidResourceError(error: unknown): error is InvalidResourceError { 20 | return Boolean(error) && (error as InvalidResourceError).isInvalidResourceError === true; 21 | } 22 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/errors/InvalidSearchParameterError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | /* eslint-disable @typescript-eslint/explicit-member-accessibility */ 6 | // eslint-disable-next-line import/prefer-default-export 7 | export class InvalidSearchParameterError extends Error { 8 | readonly isInvalidSearchParameterError: boolean; 9 | 10 | constructor(message: string) { 11 | // Node Error class requires passing a string message to the parent class 12 | super(message); 13 | Object.setPrototypeOf(this, InvalidSearchParameterError.prototype); 14 | this.isInvalidSearchParameterError = true; 15 | this.name = this.constructor.name; 16 | } 17 | } 18 | export function isInvalidSearchParameterError(error: unknown): error is InvalidSearchParameterError { 19 | return Boolean(error) && (error as InvalidSearchParameterError).isInvalidSearchParameterError === true; 20 | } 21 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/errors/MethodNotAllowedError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | /* eslint-disable @typescript-eslint/explicit-member-accessibility */ 6 | // eslint-disable-next-line import/prefer-default-export 7 | export class MethodNotAllowedError extends Error { 8 | readonly isMethodNotAllowed: boolean; 9 | 10 | // eslint-disable-next-line @typescript-eslint/typedef 11 | constructor(message = 'Method Not Allowed') { 12 | // Node Error class requires passing a string message to the parent class 13 | super(message); 14 | Object.setPrototypeOf(this, MethodNotAllowedError.prototype); 15 | this.name = this.constructor.name; 16 | this.isMethodNotAllowed = true; 17 | } 18 | } 19 | export function isMethodNotAllowed(error: unknown): error is MethodNotAllowedError { 20 | return Boolean(error) && (error as MethodNotAllowedError).isMethodNotAllowed === true; 21 | } 22 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/errors/ResourceConflictError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | /* eslint-disable @typescript-eslint/explicit-member-accessibility */ 7 | // eslint-disable-next-line import/prefer-default-export 8 | export class ResourceConflictError extends Error { 9 | readonly isResourceConflictError: boolean; 10 | 11 | readonly resourceType: string; 12 | 13 | readonly id: string; 14 | 15 | constructor(resourceType: string, id: string, message?: string) { 16 | const msg = message || `Resource ${resourceType}/${id} is conflicting`; 17 | // Node Error class requires passing a string message to the parent class. 18 | super(msg); 19 | Object.setPrototypeOf(this, ResourceConflictError.prototype); 20 | this.resourceType = resourceType; 21 | this.id = id; 22 | this.name = this.constructor.name; 23 | this.isResourceConflictError = true; 24 | } 25 | } 26 | export function isResourceConflictError(error: unknown): error is ResourceConflictError { 27 | return Boolean(error) && (error as ResourceConflictError).isResourceConflictError === true; 28 | } 29 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/errors/ResourceNotFoundError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | /* eslint-disable @typescript-eslint/explicit-member-accessibility */ 6 | // eslint-disable-next-line import/prefer-default-export 7 | export class ResourceNotFoundError extends Error { 8 | readonly isResourceNotFoundError: boolean; 9 | 10 | readonly resourceType: string; 11 | 12 | readonly id: string; 13 | 14 | constructor(resourceType: string, id: string, message?: string) { 15 | const msg = message || 'Resource is not known'; 16 | // Node Error class requires passing a string message to the parent class 17 | super(msg); 18 | Object.setPrototypeOf(this, ResourceNotFoundError.prototype); 19 | this.resourceType = resourceType; 20 | this.id = id; 21 | this.name = this.constructor.name; 22 | this.isResourceNotFoundError = true; 23 | } 24 | } 25 | export function isResourceNotFoundError(error: unknown): error is ResourceNotFoundError { 26 | return Boolean(error) && (error as ResourceNotFoundError).isResourceNotFoundError === true; 27 | } 28 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/errors/ResourceVersionNotFoundError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | /* eslint-disable @typescript-eslint/explicit-member-accessibility */ 6 | // eslint-disable-next-line import/prefer-default-export 7 | export class ResourceVersionNotFoundError extends Error { 8 | readonly isResourceVersionNotFoundError: boolean; 9 | 10 | readonly resourceType: string; 11 | 12 | readonly id: string; 13 | 14 | readonly version: string; 15 | 16 | constructor(resourceType: string, id: string, version: string, message?: string) { 17 | const msg = message || 'Version is not valid for resource'; 18 | // Node Error class requires passing a string message to the parent class 19 | super(msg); 20 | Object.setPrototypeOf(this, ResourceVersionNotFoundError.prototype); 21 | this.resourceType = resourceType; 22 | this.id = id; 23 | this.version = version; 24 | this.name = this.constructor.name; 25 | this.isResourceVersionNotFoundError = true; 26 | } 27 | } 28 | export function isResourceVersionNotFoundError(error: unknown): error is ResourceVersionNotFoundError { 29 | return Boolean(error) && (error as ResourceVersionNotFoundError).isResourceVersionNotFoundError === true; 30 | } 31 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/errors/TooManyConcurrentExportRequestsError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | /* eslint-disable @typescript-eslint/explicit-member-accessibility */ 6 | export class TooManyConcurrentExportRequestsError extends Error { 7 | readonly isTooManyConcurrentExportRequestsError: boolean; 8 | 9 | // eslint-disable-next-line @typescript-eslint/typedef 10 | constructor(message = 'Too Many Concurrent Export Requests') { 11 | // Node Error class requires passing a string message to the parent class 12 | super(message); 13 | Object.setPrototypeOf(this, TooManyConcurrentExportRequestsError.prototype); 14 | this.isTooManyConcurrentExportRequestsError = true; 15 | this.name = this.constructor.name; 16 | } 17 | } 18 | export function isTooManyConcurrentExportRequestsError( 19 | error: unknown 20 | ): error is TooManyConcurrentExportRequestsError { 21 | return ( 22 | Boolean(error) && 23 | (error as TooManyConcurrentExportRequestsError).isTooManyConcurrentExportRequestsError === true 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/errors/UnauthorizedError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | /* eslint-disable @typescript-eslint/explicit-member-accessibility */ 6 | // eslint-disable-next-line import/prefer-default-export 7 | export class UnauthorizedError extends Error { 8 | readonly isUnauthorizedError: boolean; 9 | 10 | // eslint-disable-next-line @typescript-eslint/typedef 11 | constructor(message = 'Forbidden') { 12 | // Node Error class requires passing a string message to the parent class 13 | super(message); 14 | Object.setPrototypeOf(this, UnauthorizedError.prototype); 15 | this.name = this.constructor.name; 16 | this.isUnauthorizedError = true; 17 | } 18 | } 19 | export function isUnauthorizedError(error: unknown): error is UnauthorizedError { 20 | return Boolean(error) && (error as UnauthorizedError).isUnauthorizedError === true; 21 | } 22 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/genericResponse.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | export interface GenericResponse { 7 | readonly message: string; 8 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 9 | readonly resource?: any; 10 | } 11 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/implementationGuides.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | export interface ImplementationGuides { 7 | /** 8 | * Compiles the contents of an Implementation Guide into an internal representation used to implement the features specified by it. 9 | * 10 | * The FHIR resource types commonly used on Implementation Guides are: StructureDefinition, SearchParameter, CodeSystem, ValueSet, ImplementationGuide, ConceptMap, OperationDefinition, CapabilityStatement. 11 | * 12 | * Different implementations of this interface may choose to process only a subset of the above resources. 13 | * 14 | * @param input - an array of FHIR resource objects to be compiled. 15 | * @returns compiled output - The output is not meant to be used by any other entity other than the module that implements this interface. 16 | */ 17 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 18 | compile(input: any[]): Promise; 19 | } 20 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | export * from './authorization'; 7 | export * from './bulkDataAccess'; 8 | export * from './bundle'; 9 | export * from './capabilities'; 10 | export * from './constants'; 11 | export * from './fhirConfig'; 12 | export * from './genericResponse'; 13 | export * from './history'; 14 | export * from './implementationGuides'; 15 | export * from './persistence'; 16 | export * from './resourceMeta'; 17 | export * from './search'; 18 | export * from './utilities'; 19 | export * from './errors/InvalidResourceError'; 20 | export * from './errors/ResourceNotFoundError'; 21 | export * from './errors/ResourceVersionNotFoundError'; 22 | export * from './errors/UnauthorizedError'; 23 | export * from './errors/TooManyConcurrentExportRequestsError'; 24 | export * from './errors/InvalidSearchParameterError'; 25 | export * from './errors/ResourceConflictError'; 26 | export * from './errors/MethodNotAllowedError'; 27 | export * from './errors/BadRequestError'; 28 | export * from './validator'; 29 | export { makeLogger } from './loggerBuilder'; 30 | export { makeEncryptLogger } from './encryptedLoggerBuilder'; 31 | export { stubs } from './stubs'; 32 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/loggerBuilder.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { createLogger, Logger } from 'winston'; 7 | import Transport from 'winston-transport'; 8 | import { runLoggerLevel } from './loggerUtilities'; 9 | 10 | class SimpleConsole extends Transport { 11 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 12 | public log(info: any, callback: () => void): void { 13 | setImmediate(() => this.emit('logged', info)); 14 | const msg = [info.meta, info.message]; 15 | if (info[Symbol.for('splat')]) { 16 | msg.push(...info[Symbol.for('splat')]); 17 | } 18 | runLoggerLevel(info, msg); 19 | if (callback) { 20 | callback(); 21 | } 22 | } 23 | } 24 | 25 | // eslint-disable-next-line @typescript-eslint/no-explicit-any,import/prefer-default-export 26 | export function makeLogger(metadata?: any, logLevel?: string): Logger { 27 | return createLogger({ 28 | level: logLevel ?? process.env.LOG_LEVEL, 29 | transports: [new SimpleConsole()], 30 | defaultMeta: { meta: metadata } 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/resourceMeta.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | // https://www.hl7.org/fhir/datatypes.html#Coding 7 | export interface Coding { 8 | system?: string; 9 | version?: string; 10 | code?: string; 11 | display?: string; 12 | userSelected?: boolean; 13 | } 14 | 15 | // https://www.hl7.org/fhir/resource.html#Meta 16 | export interface Meta { 17 | versionId: string; 18 | lastUpdated: string; 19 | source?: string; 20 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 21 | profile?: any | any[]; 22 | security?: Coding | Coding[]; 23 | tag?: Coding | Coding[]; 24 | } 25 | 26 | export function generateMeta(vid: string, lastUpdatedDate: Date = new Date()): Meta { 27 | return { 28 | versionId: vid, 29 | lastUpdated: lastUpdatedDate.toISOString() 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/smartAuthorization.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | export interface SmartAuthorization { 6 | /** 7 | * Retrieve SMART scopes that are supported by the Auth server 8 | * http://hl7.org/fhir/smart-app-launch/scopes-and-launch-context/index.html#quick-start 9 | * @returns a list of scopes supported by the Auth server 10 | */ 11 | getSupportedSMARTScopes(): Promise; 12 | } 13 | -------------------------------------------------------------------------------- /fwoa-core/interface/src/validator.ts: -------------------------------------------------------------------------------- 1 | import { TypeOperation } from './constants'; 2 | 3 | export interface Validator { 4 | /** 5 | * returns a resolved Promise if the resource is valid. Otherwise throws an error 6 | * @throws InvalidResourceError 7 | */ 8 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 9 | validate( 10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 11 | resource: any, 12 | { tenantId, typeOperation }: { tenantId?: string; typeOperation?: TypeOperation } 13 | ): Promise; 14 | } 15 | -------------------------------------------------------------------------------- /fwoa-core/interface/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/tsconfig", 3 | "extends": "./node_modules/@rushstack/heft-node-rig/profiles/default/tsconfig-base.json", 4 | "compilerOptions": { 5 | "types": ["heft-jest", "node"], 6 | "target": "es2019", // Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. 7 | "module": "commonjs", // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 8 | "strict": true, // // Enable all strict type-checking options. 9 | "esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 10 | "forceConsistentCasingInFileNames": true, // Disallow inconsistently-cased references to the same file. 11 | "outDir": "lib", 12 | "declaration": true, 13 | "sourceMap": true, 14 | "resolveJsonModule": true, 15 | "baseUrl": "." 16 | }, 17 | "include": ["src/**/*"] 18 | } 19 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/.eslintignore: -------------------------------------------------------------------------------- 1 | .eslintrc.js 2 | node_modules 3 | lib 4 | temp -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This is a workaround for https://github.com/eslint/eslint/issues/3458 2 | require('@rushstack/eslint-config/patch/modern-module-resolution'); 3 | 4 | module.exports = { 5 | extends: ['@aws/eslint-config-fwoa-eslint-custom'], 6 | parserOptions: { tsconfigRootDir: __dirname }, 7 | overrides: [ 8 | { 9 | files: ['*.ts'], 10 | rules: { 11 | '@typescript-eslint/no-explicit-any': 'off', 12 | '@typescript-eslint/explicit-member-accessibility': 'off', 13 | 'security/detect-object-injection': 'off', 14 | '@typescript-eslint/ban-types': 'off', 15 | '@typescript-eslint/explicit-function-return-type': 'off', 16 | '@rushstack/typedef-var': 'off', 17 | '@typescript-eslint/typedef': 'off', 18 | 'tsdoc/syntax': 'off', 19 | '@typescript-eslint/consistent-type-assertions': 'off', 20 | 'security/detect-non-literal-regexp': 'off', 21 | 'security/detect-unsafe-regex': 'off', 22 | '@rushstack/no-new-null': 'off', 23 | '@rushstack/security/no-unsafe-regexp': 'off', 24 | 'import/no-named-as-default-member': 'off', 25 | '@typescript-eslint/no-unused-vars': 'off' 26 | } 27 | } 28 | ] 29 | }; 30 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | 3 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 4 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 5 | opensource-codeofconduct@amazon.com with any additional questions or comments. 6 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/config/jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rushstack/heft-node-rig/profiles/default/config/jest.config.json", 3 | "collectCoverage": true, 4 | "coverageThreshold": { 5 | "global": { 6 | "branches": 70, 7 | "functions": 70, 8 | "lines": 70, 9 | "statements": 70 10 | } 11 | }, 12 | "coveragePathIgnorePatterns": [ 13 | "/src/index.ts", 14 | "/src/dataServices/__mock__dynamoDbDataService.ts " 15 | ], 16 | "coverageReporters": ["json-summary", "json", "lcov", "text"] 17 | } 18 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/config/rig.json: -------------------------------------------------------------------------------- 1 | // The "rig.json" file directs tools to look for their config files in an external package. 2 | // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package 3 | { 4 | "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", 5 | 6 | /** 7 | * (Required) The name of the rig package to inherit from. 8 | * It should be an NPM package name with the "-rig" suffix. 9 | */ 10 | "rigPackageName": "@rushstack/heft-node-rig" 11 | 12 | /** 13 | * (Optional) Selects a config profile from the rig package. The name must consist of 14 | * lowercase alphanumeric words separated by hyphens, for example "sample-profile". 15 | * If omitted, then the "default" profile will be used." 16 | */ 17 | // "rigProfile": "your-profile-name" 18 | } 19 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/AWS.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import './offlineEnvVariables'; 7 | import AWS from 'aws-sdk'; 8 | import AWSXRay from 'aws-xray-sdk'; 9 | 10 | const AWSWithXray = AWSXRay.captureAWS(AWS); 11 | 12 | const { IS_OFFLINE } = process.env; 13 | 14 | if (IS_OFFLINE === 'true') { 15 | AWSWithXray.config.update({ 16 | region: process.env.AWS_REGION || 'us-west-2', 17 | accessKeyId: process.env.ACCESS_KEY, 18 | secretAccessKey: process.env.SECRET_KEY 19 | }); 20 | } else { 21 | AWSWithXray.config.update({ 22 | customUserAgent: process.env.CUSTOM_USER_AGENT 23 | }); 24 | } 25 | 26 | export default AWSWithXray; 27 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/bulkExport/__mocks__/bulkExport.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | import { BulkExportJob } from '../types'; 6 | 7 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 8 | export const getBulkExportResults = async (jobId: string): Promise<{ type: string; url: string }[]> => { 9 | return []; 10 | }; 11 | 12 | // eslint-disable-next-line @typescript-eslint/no-empty-function,@typescript-eslint/no-unused-vars 13 | export const startJobExecution = async (bulkExportJob: BulkExportJob): Promise => {}; 14 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/bulkExport/bulkExportResultsUrlGenerator.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | export interface BulkExportResultsUrlGenerator { 8 | getUrls(options: { 9 | exportBucket: string; 10 | s3Keys: string[]; 11 | }): Promise<{ requiresAccessToken: boolean; urls: string[] }>; 12 | } 13 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/bulkExport/stopExportJob.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { Handler } from 'aws-lambda'; 7 | import AWS from '../AWS'; 8 | import getComponentLogger from '../loggerBuilder'; 9 | import { BulkExportStateMachineGlobalParameters } from './types'; 10 | 11 | const logger = getComponentLogger(); 12 | 13 | export const stopExportJobHandler: Handler< 14 | BulkExportStateMachineGlobalParameters, 15 | BulkExportStateMachineGlobalParameters 16 | > = async (event) => { 17 | const { GLUE_JOB_NAME } = process.env; 18 | if (GLUE_JOB_NAME === undefined) { 19 | throw new Error('GLUE_JOB_NAME environment variable is not defined'); 20 | } 21 | const glueJobRunId = event.executionParameters?.glueJobRunId; 22 | if (glueJobRunId === undefined) { 23 | throw new Error('executionParameters.glueJobRunId is missing in input event'); 24 | } 25 | 26 | const glue = new AWS.Glue(); 27 | const stopJobRunResponse = await glue 28 | .batchStopJobRun({ 29 | JobName: GLUE_JOB_NAME, 30 | JobRunIds: [glueJobRunId] 31 | }) 32 | .promise(); 33 | if (stopJobRunResponse.Errors!.length > 0) { 34 | logger.error('Failed to stop job', JSON.stringify(stopJobRunResponse)); 35 | throw new Error(`Failed to stop job ${glueJobRunId}`); 36 | } 37 | return event; 38 | }; 39 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/bulkExport/updateStatus.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { ExportJobStatus } from '@aws/fhir-works-on-aws-interface'; 7 | import { Handler } from 'aws-lambda'; 8 | import AWS from '../AWS'; 9 | import DynamoDbParamBuilder from '../dataServices/dynamoDbParamBuilder'; 10 | import { BulkExportStateMachineGlobalParameters } from './types'; 11 | 12 | const EXPORT_JOB_STATUS = ['completed', 'failed', 'in-progress', 'canceled', 'canceling']; 13 | const isJobStatus = (x: string): x is ExportJobStatus => EXPORT_JOB_STATUS.includes(x); 14 | 15 | export const updateStatusStatusHandler: Handler< 16 | { globalParams: BulkExportStateMachineGlobalParameters; status: string }, 17 | void 18 | > = async (event) => { 19 | const { globalParams, status } = event; 20 | if (!isJobStatus(status)) { 21 | throw new Error(`Invalid status "${event.status}"`); 22 | } 23 | await new AWS.DynamoDB() 24 | .updateItem( 25 | DynamoDbParamBuilder.buildUpdateExportRequestJobStatus( 26 | globalParams.jobId, 27 | status, 28 | globalParams.tenantId 29 | ) 30 | ) 31 | .promise(); 32 | }; 33 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/constants.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | export const SEPARATOR: string = '_'; 6 | export const DDB_HASH_KEY_SEPARATOR: string = '|'; 7 | 8 | export const MAX_BATCH_WRITE_ITEMS = 25; 9 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/dataServices/documentStatus.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | const enum DOCUMENT_STATUS { 7 | LOCKED = 'LOCKED', 8 | PENDING = 'PENDING', 9 | PENDING_DELETE = 'PENDING_DELETE', 10 | DELETED = 'DELETED', 11 | AVAILABLE = 'AVAILABLE' 12 | } 13 | 14 | export default DOCUMENT_STATUS; 15 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/dataServices/dynamoDb.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import AWS from '../AWS'; 7 | 8 | export const DynamoDb = new AWS.DynamoDB(); 9 | 10 | export const DynamoDBConverter = AWS.DynamoDB.Converter; 11 | 12 | export const RESOURCE_TABLE = process.env.RESOURCE_TABLE || ''; 13 | 14 | export const EXPORT_REQUEST_TABLE = process.env.EXPORT_REQUEST_TABLE || ''; 15 | 16 | export const EXPORT_REQUEST_TABLE_JOB_STATUS_INDEX = process.env.EXPORT_REQUEST_TABLE_JOB_STATUS_INDEX || ''; 17 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/ddbToEs/ESBulkCommand.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | export type OperationType = 'delete' | 'upsert-AVAILABLE' | 'upsert-DELETED'; 7 | 8 | export default interface ESBulkCommand { 9 | bulkCommand: any[]; 10 | /** 11 | * This will be a unique identifier or composite id i.e. `_` 12 | */ 13 | id: string; 14 | type: OperationType; 15 | } 16 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/ddbToEs/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { DdbToEsSync } from './ddbToEsSync'; 7 | 8 | const ddbToEsSync = new DdbToEsSync(); 9 | 10 | // This is a separate lambda function from the main FHIR API server lambda. 11 | // This lambda picks up changes from DDB by way of DDB stream, and sends those changes to ElasticSearch Service for indexing. 12 | // This allows the FHIR API Server to query ElasticSearch service for search requests 13 | export async function handleDdbToEsEvent(event: any) { 14 | return ddbToEsSync.handleDDBStreamEvent(event); 15 | } 16 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | export * from './dataServices/dynamoDbBundleService'; 6 | export * from './dataServices/dynamoDbDataService'; 7 | export * from './dataServices/dynamoDbUtil'; 8 | export { DynamoDb } from './dataServices/dynamoDb'; 9 | export * from './objectStorageService/s3DataService'; 10 | export { handleDdbToEsEvent } from './ddbToEs/index'; 11 | export { DdbToEsSync } from './ddbToEs/ddbToEsSync'; 12 | export { startExportJobHandler } from './bulkExport/startExportJob'; 13 | export { stopExportJobHandler } from './bulkExport/stopExportJob'; 14 | export { getJobStatusHandler } from './bulkExport/getJobStatus'; 15 | export { updateStatusStatusHandler } from './bulkExport/updateStatus'; 16 | export { BulkExportResultsUrlGenerator } from './bulkExport/bulkExportResultsUrlGenerator'; 17 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/loggerBuilder.ts: -------------------------------------------------------------------------------- 1 | import { makeLogger } from '@aws/fhir-works-on-aws-interface'; 2 | 3 | const componentLogger = makeLogger({ 4 | component: 'persistence' 5 | }); 6 | 7 | export default function getComponentLogger(): any { 8 | return componentLogger; 9 | } 10 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/objectStorageService/ObjectNotFoundError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | export default class ObjectNotFoundError extends Error { 7 | readonly filename: string; 8 | 9 | constructor(filename: string, message?: string) { 10 | const msg = message || 'Object not found'; 11 | // Node Error class requires passing a string message to the parent class 12 | super(msg); 13 | Object.setPrototypeOf(this, ObjectNotFoundError.prototype); 14 | this.filename = filename; 15 | this.name = this.constructor.name; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/objectStorageService/__mocks__/s3ObjectStorageService.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | /* eslint-disable @typescript-eslint/no-unused-vars */ 7 | import ObjectStorageInterface from '../objectStorageInterface'; 8 | 9 | const ObjectStorageService: ObjectStorageInterface = class { 10 | static async uploadObject(base64Data: string, fileName: string, contentType: string) { 11 | return { success: true, message: '' }; 12 | } 13 | 14 | static async readObject(fileName: string) { 15 | return { success: true, message: '' }; 16 | } 17 | 18 | static async deleteObject(fileName: string) { 19 | return { success: true, message: '' }; 20 | } 21 | 22 | static async getPresignedPutUrl(fileName: string) { 23 | return { success: true, message: `https://VALID_S3_PUT_URL.com/${fileName}/VALID_TEMP_CREDENTIAL` }; 24 | } 25 | 26 | static async getPresignedGetUrl(fileName: string) { 27 | return { success: true, message: `https://VALID_S3_GET_URL.com/${fileName}/VALID_TEMP_CREDENTIAL` }; 28 | } 29 | 30 | static async deleteBasedOnPrefix(fileName: string) { 31 | return { success: true, message: '' }; 32 | } 33 | }; 34 | 35 | export default ObjectStorageService; 36 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/objectStorageService/objectStorageInterface.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | // eslint-disable-next-line no-unused-vars 7 | import { GenericResponse } from '@aws/fhir-works-on-aws-interface'; 8 | 9 | export default interface ObjectStorageInterface { 10 | uploadObject(base64Data: string, fileName: string, contentType: string): Promise; 11 | readObject(fileName: string): Promise; 12 | deleteObject(fileName: string): Promise; 13 | getPresignedPutUrl(fileName: string): Promise; 14 | deleteBasedOnPrefix(prefix: string): Promise; 15 | getPresignedGetUrl(fileName: string): Promise; 16 | } 17 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/objectStorageService/s3.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import AWS from '../AWS'; 7 | 8 | const { IS_OFFLINE } = process.env; 9 | 10 | let binaryBucket = process.env.FHIR_BINARY_BUCKET || ''; 11 | let s3KMSKey = process.env.S3_KMS_KEY || ''; 12 | if (IS_OFFLINE === 'true') { 13 | binaryBucket = process.env.OFFLINE_BINARY_BUCKET || ''; 14 | s3KMSKey = process.env.OFFLINE_S3_KMS_KEY || ''; 15 | } 16 | 17 | export const FHIR_BINARY_BUCKET = binaryBucket; 18 | export const S3_KMS_KEY = s3KMSKey; 19 | 20 | export const S3 = new AWS.S3({ signatureVersion: 'v4', sslEnabled: true }); 21 | 22 | export default S3; 23 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/offlineEnvVariables.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | const { IS_OFFLINE } = process.env; 7 | // Set environment variables that are convenient when testing locally with "serverless offline" 8 | if (IS_OFFLINE === 'true') { 9 | // https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs-configuration.html#xray-sdk-nodejs-configuration-envvars 10 | process.env.AWS_XRAY_CONTEXT_MISSING = 'LOG_ERROR'; 11 | process.env.AWS_XRAY_LOG_LEVEL = 'silent'; 12 | } 13 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/sampleData/validV3Account.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "Account", 3 | "text": { 4 | "status": "generated", 5 | "div": "
HACC Funded Billing for Peter James Chalmers
" 6 | }, 7 | "identifier": [ 8 | { 9 | "system": "urn:oid:0.1.2.3.4.5.6.7", 10 | "value": "654321" 11 | } 12 | ], 13 | "status": "active", 14 | "type": { 15 | "coding": [ 16 | { 17 | "system": "http://hl7.org/fhir/v3/ActCode", 18 | "code": "PBILLACCT", 19 | "display": "patient billing account" 20 | } 21 | ], 22 | "text": "patient" 23 | }, 24 | "name": "HACC Funded Billing for Peter James Chalmers", 25 | "subject": { 26 | "reference": "Patient/example", 27 | "display": "Peter James Chalmers" 28 | }, 29 | "period": { 30 | "start": "2016-01-01", 31 | "end": "2016-06-30" 32 | }, 33 | "active": { 34 | "start": "2016-01-01", 35 | "end": "2016-06-30" 36 | }, 37 | "balance": { 38 | "value": -1200, 39 | "unit": "USD", 40 | "system": "urn:iso:std:iso:4217", 41 | "code": "USD" 42 | }, 43 | "coverage": [ 44 | { 45 | "coverage": { 46 | "reference": "Coverage/7546D" 47 | }, 48 | "priority": 1 49 | } 50 | ], 51 | "owner": { 52 | "reference": "Organization/hl7" 53 | }, 54 | "description": "Hospital charges" 55 | } 56 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/sampleData/validV4Account.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "Account", 3 | "id": "example", 4 | "text": { 5 | "status": "generated", 6 | "div": "
HACC Funded Billing for Peter James Chalmers
" 7 | }, 8 | "identifier": [ 9 | { 10 | "system": "urn:oid:0.1.2.3.4.5.6.7", 11 | "value": "654321" 12 | } 13 | ], 14 | "status": "active", 15 | "type": { 16 | "coding": [ 17 | { 18 | "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", 19 | "code": "PBILLACCT", 20 | "display": "patient billing account" 21 | } 22 | ], 23 | "text": "patient" 24 | }, 25 | "name": "HACC Funded Billing for Peter James Chalmers", 26 | "subject": [ 27 | { 28 | "reference": "Patient/example", 29 | "display": "Peter James Chalmers" 30 | } 31 | ], 32 | "servicePeriod": { 33 | "start": "2016-01-01", 34 | "end": "2016-06-30" 35 | }, 36 | "coverage": [ 37 | { 38 | "coverage": { 39 | "reference": "Coverage/7546D" 40 | }, 41 | "priority": 1 42 | } 43 | ], 44 | "owner": { 45 | "reference": "Organization/hl7" 46 | }, 47 | "description": "Hospital charges" 48 | } 49 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/sampleData/validV4Patient.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "Patient", 3 | "id": "xcda", 4 | "text": { 5 | "status": "generated", 6 | "div": "

Henry Levin the 7th

" 7 | }, 8 | "active": true, 9 | "name": [ 10 | { 11 | "family": "Levin", 12 | "given": ["Henry"] 13 | } 14 | ], 15 | "gender": "male", 16 | "birthDate": "1932-09-24", 17 | "managingOrganization": { 18 | "reference": "Organization/2.16.840.1.113883.19.5", 19 | "display": "Good Health Clinic" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/testUtilities/ConditionalCheckFailedException.ts: -------------------------------------------------------------------------------- 1 | export class ConditionalCheckFailedExceptionMock extends Error { 2 | public code: string; 3 | 4 | constructor() { 5 | super(''); 6 | this.code = 'ConditionalCheckFailedException'; 7 | 8 | // Set the prototype explicitly. 9 | Object.setPrototypeOf(this, ConditionalCheckFailedExceptionMock.prototype); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/src/testUtilities/regExpressions.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | export const timeFromEpochInMsRegExp = /\d{13}/; 7 | export const utcTimeRegExp = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+Z/; 8 | export const uuidRegExp = /\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/; 9 | -------------------------------------------------------------------------------- /fwoa-core/persistence-ddb/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/tsconfig", 3 | "extends": "./node_modules/@rushstack/heft-node-rig/profiles/default/tsconfig-base.json", 4 | "compilerOptions": { 5 | "lib": ["es2019"], 6 | "types": ["heft-jest", "node"], 7 | "target": "es2019", // Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. 8 | "module": "commonjs", // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 9 | "strict": true, // // Enable all strict type-checking options. 10 | "esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 11 | "forceConsistentCasingInFileNames": true, // Disallow inconsistently-cased references to the same file. 12 | "outDir": "lib", 13 | "declaration": true, 14 | "sourceMap": true, 15 | "resolveJsonModule": true, 16 | "baseUrl": "." 17 | }, 18 | "include": ["src/**/*"] 19 | } 20 | -------------------------------------------------------------------------------- /fwoa-core/routing/.eslintignore: -------------------------------------------------------------------------------- 1 | .eslintrc.js 2 | node_modules 3 | lib 4 | temp -------------------------------------------------------------------------------- /fwoa-core/routing/.npmignore: -------------------------------------------------------------------------------- 1 | # Don't include original .ts files when doing `npm pack` 2 | *.ts 3 | !*.template.ts 4 | !*.d.ts 5 | coverage 6 | .nyc_output 7 | *.tgz 8 | sampleData 9 | 10 | src 11 | dist 12 | .github 13 | *.tsbuildinfo 14 | tsconfig.json 15 | .eslintrc.js 16 | .eslintignore 17 | .prettierrc.js 18 | .github 19 | CODE_OF_CONDUCT.md 20 | CONTRIBUTING.md -------------------------------------------------------------------------------- /fwoa-core/routing/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | 3 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 4 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 5 | opensource-codeofconduct@amazon.com with any additional questions or comments. 6 | -------------------------------------------------------------------------------- /fwoa-core/routing/config/jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rushstack/heft-node-rig/profiles/default/config/jest.config.json", 3 | "collectCoverage": true, 4 | "coverageThreshold": { 5 | "global": { 6 | "branches": 70, 7 | "functions": 70, 8 | "lines": 70, 9 | "statements": 70 10 | } 11 | }, 12 | "coveragePathIgnorePatterns": [ 13 | "/src/index.ts", 14 | "/src/operationDefinitions/USCoreDocRef/index.ts" 15 | ], 16 | "coverageReporters": ["json-summary", "json", "lcov", "text"] 17 | } 18 | -------------------------------------------------------------------------------- /fwoa-core/routing/config/rig.json: -------------------------------------------------------------------------------- 1 | // The "rig.json" file directs tools to look for their config files in an external package. 2 | // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package 3 | { 4 | "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", 5 | 6 | /** 7 | * (Required) The name of the rig package to inherit from. 8 | * It should be an NPM package name with the "-rig" suffix. 9 | */ 10 | "rigPackageName": "@rushstack/heft-node-rig" 11 | 12 | /** 13 | * (Optional) Selects a config profile from the rig package. The name must consist of 14 | * lowercase alphanumeric words separated by hyphens, for example "sample-profile". 15 | * If omitted, then the "default" profile will be used." 16 | */ 17 | // "rigProfile": "your-profile-name" 18 | } 19 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/AWS.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import './offlineEnvVariables'; 7 | import AWS from 'aws-sdk'; 8 | import AWSXRay from 'aws-xray-sdk'; 9 | 10 | const AWSWithXray = AWSXRay.captureAWS(AWS); 11 | 12 | AWS.config.update({ 13 | customUserAgent: process.env.CUSTOM_USER_AGENT 14 | }); 15 | 16 | const { IS_OFFLINE } = process.env; 17 | if (IS_OFFLINE === 'true') { 18 | AWS.config.update({ 19 | region: process.env.AWS_REGION || 'us-west-2', 20 | accessKeyId: process.env.ACCESS_KEY, 21 | secretAccessKey: process.env.SECRET_KEY 22 | }); 23 | } 24 | 25 | export default AWSWithXray; 26 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/constants.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | export const MAX_BUNDLE_ENTRIES = 100; 7 | export const MAX_REFERENCE_URL_LENGTH = 500; 8 | export const MAX_BUNDLE_ENTRY_URL_LENGTH = 500; 9 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | export { generateServerlessRouter } from './app'; 7 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/loggerBuilder.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | import { makeLogger, makeEncryptLogger } from '@aws/fhir-works-on-aws-interface'; 8 | 9 | const componentLogger = makeLogger({ 10 | component: 'routing' 11 | }); 12 | 13 | export default function getComponentLogger(): any { 14 | return componentLogger; 15 | } 16 | export function getEncryptLogger(metaData?: any): any { 17 | const metaDataTotal = metaData ? { component: 'routing', ...metaData } : { component: 'routing' }; 18 | const encryptedComponentLogger = makeEncryptLogger(metaDataTotal); 19 | return encryptedComponentLogger; 20 | } 21 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/offlineEnvVariables.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | const { IS_OFFLINE } = process.env; 7 | // Set environment variables that are convenient when testing locally with "serverless offline" 8 | if (IS_OFFLINE === 'true') { 9 | // https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs-configuration.html#xray-sdk-nodejs-configuration-envvars 10 | process.env.AWS_XRAY_CONTEXT_MISSING = 'LOG_ERROR'; 11 | process.env.AWS_XRAY_LOG_LEVEL = 'silent'; 12 | } 13 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/operationDefinitions/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | import ConfigHandler from '../configHandler'; 8 | import { OperationDefinitionRegistry } from './OperationDefinitionRegistry'; 9 | import { OperationDefinitionImplementation } from './types'; 10 | import { USCoreDocRef } from './USCoreDocRef'; 11 | 12 | export const initializeOperationRegistry = (configHandler: ConfigHandler) => { 13 | const { compiledImplementationGuides } = configHandler.config.profile; 14 | const operations: OperationDefinitionImplementation[] = []; 15 | 16 | // Add the operations to enable on this FHIR server. 17 | // The recommended approach is to enable operations if the corresponding `OperationDefinition` is found on the `compiledImplementationGuides`, 18 | // but this file can be updated to use a different enablement criteria or to disable operations altogether. 19 | if ( 20 | compiledImplementationGuides && 21 | compiledImplementationGuides.find( 22 | (x: any) => x.resourceType === 'OperationDefinition' && x.url === USCoreDocRef.canonicalUrl 23 | ) 24 | ) { 25 | operations.push(USCoreDocRef); 26 | } 27 | 28 | return new OperationDefinitionRegistry(configHandler, operations); 29 | }; 30 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/registry/ResourceCapabilityInterface.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | export interface ResourceCapability { 7 | type: string; 8 | supportedProfile: string[]; 9 | } 10 | 11 | export interface ResourceCapabilityStatement { 12 | [resourceType: string]: ResourceCapability; 13 | } 14 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/router/__mocks_/elasticSearchService.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Search, 3 | SearchResponse, 4 | GlobalSearchRequest, 5 | TypeSearchRequest, 6 | SearchCapabilityStatement 7 | } from '@aws/fhir-works-on-aws-interface'; 8 | 9 | const ElasticSearchService: Search = class { 10 | /* 11 | searchParams => {field: value} 12 | */ 13 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 14 | static async typeSearch(request: TypeSearchRequest) { 15 | return { 16 | success: true, 17 | result: { 18 | numberOfResults: 0, 19 | message: '', 20 | entries: [] 21 | } 22 | }; 23 | } 24 | 25 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 26 | static globalSearch(request: GlobalSearchRequest): Promise { 27 | throw new Error('Method not implemented.'); 28 | } 29 | 30 | static async getCapabilities(): Promise { 31 | throw new Error('Method not implemented.'); 32 | } 33 | 34 | static validateSubscriptionSearchCriteria(searchCriteria: string): void { 35 | console.log(searchCriteria); 36 | } 37 | }; 38 | export default ElasticSearchService; 39 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/router/bundle/bundleHandlerInterface.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | import { KeyValueMap, RequestContext } from '@aws/fhir-works-on-aws-interface'; 6 | 7 | export default interface BundleHandlerInterface { 8 | processBatch( 9 | resource: any, 10 | userIdentity: KeyValueMap, 11 | requestContext: RequestContext, 12 | serverUrl: string, 13 | tenantId?: string 14 | ): any; 15 | processTransaction( 16 | resource: any, 17 | userIdentity: KeyValueMap, 18 | requestContext: RequestContext, 19 | serverUrl: string, 20 | tenantId?: string 21 | ): any; 22 | } 23 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/router/handlers/crudHandlerInterface.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { KeyValueMap, RequestContext } from '@aws/fhir-works-on-aws-interface'; 7 | 8 | export default interface CrudHandlerInterface { 9 | create(resourceType: string, resource: any, tenantId?: string): any; 10 | update(resourceType: string, id: string, resource: any, tenantId?: string): any; 11 | patch(resourceType: string, id: string, resource: any, tenantId?: string): any; 12 | read(resourceType: string, id: string, tenantId?: string): any; 13 | vRead(resourceType: string, id: string, vid: string, tenantId?: string): any; 14 | delete(resourceType: string, id: string, tenantId?: string): any; 15 | typeSearch( 16 | resourceType: string, 17 | searchParams: any, 18 | userIdentity: KeyValueMap, 19 | requestContext: RequestContext, 20 | serverUrl: string, 21 | tenantId?: string 22 | ): any; 23 | typeHistory( 24 | resourceType: string, 25 | searchParams: any, 26 | userIdentity: KeyValueMap, 27 | requestContext: RequestContext, 28 | serverUrl: string, 29 | tenantId?: string 30 | ): any; 31 | instanceHistory( 32 | resourceType: string, 33 | id: string, 34 | searchParams: any, 35 | userIdentity: KeyValueMap, 36 | requestContext: RequestContext, 37 | serverUrl: string, 38 | tenantId?: string 39 | ): any; 40 | } 41 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/router/handlers/utils.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | import { createHash } from 'crypto'; 8 | import sanitizeHTML, { defaults } from 'sanitize-html'; 9 | 10 | export const hash = (o: any): any => createHash('sha256').update(JSON.stringify(o)).digest('hex'); 11 | 12 | export const validateXHTMLResource = (resource: any): boolean => { 13 | // we want to ignore the text field as it requires unencoded html as per the FHIR spec 14 | // https://www.hl7.org/fhir/datatypes-definitions.html#HumanName.text (for example) 15 | const originalResource = JSON.stringify({ ...resource, text: {} }); 16 | const validatedResource = sanitizeHTML(originalResource, { 17 | allowedAttributes: { 18 | ...defaults.allowedAttributes, 19 | div: ['xmlns'] 20 | } 21 | }); 22 | return originalResource === validatedResource; 23 | }; 24 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/router/handlers/wellKnownUriHandler.ts: -------------------------------------------------------------------------------- 1 | import { SmartStrategy } from '@aws/fhir-works-on-aws-interface'; 2 | import { mapKeys } from 'lodash'; 3 | 4 | export function camelToSnakeCase(str: string) { 5 | const camelCaseStr = str.replace(/[A-Z]/g, (letter: string) => `_${letter.toLowerCase()}`); 6 | // Handle mis-capitalized first letter, example Red => red 7 | if (camelCaseStr.substring(0, 1) === '_') { 8 | return camelCaseStr.substring(1, camelCaseStr.length); 9 | } 10 | return camelCaseStr; 11 | } 12 | 13 | export function getWellKnownUriResponse(smartStrategy: SmartStrategy) { 14 | return mapKeys(smartStrategy, (value, key) => { 15 | return camelToSnakeCase(key); 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/router/middlewares/setContentType.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unused-vars */ 2 | /* 3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | */ 7 | 8 | import express from 'express'; 9 | 10 | /** 11 | * Set default content-type to 'application/fhir+json' 12 | */ 13 | export const setContentTypeMiddleware = ( 14 | req: express.Request, 15 | res: express.Response, 16 | next: express.NextFunction 17 | ) => { 18 | try { 19 | res.contentType(req.headers.accept === 'application/json' ? 'application/json' : 'application/fhir+json'); 20 | next(); 21 | } catch (e) { 22 | next(e); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/router/middlewares/setServerUrl.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unused-vars */ 2 | /* 3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | */ 7 | 8 | import { FhirConfig } from '@aws/fhir-works-on-aws-interface'; 9 | import express from 'express'; 10 | import RouteHelper from '../routes/routeHelper'; 11 | 12 | /** 13 | * Sets the value of `res.locals.serverUrl` 14 | * the serverUrl can either be a static value from FhirConfig of a dynamic value for some multi-tenancy setups. 15 | */ 16 | export const setServerUrlMiddleware: ( 17 | fhirConfig: FhirConfig 18 | ) => (req: express.Request, res: express.Response, next: express.NextFunction) => void = ( 19 | fhirConfig: FhirConfig 20 | ) => { 21 | return RouteHelper.wrapAsync( 22 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { 23 | if (req.baseUrl && req.baseUrl !== '/') { 24 | res.locals.serverUrl = fhirConfig.server.url + req.baseUrl; 25 | } else { 26 | res.locals.serverUrl = fhirConfig.server.url; 27 | } 28 | next(); 29 | } 30 | ); 31 | }; 32 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/router/routes/routeHelper.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import express from 'express'; 7 | 8 | export default class RouteHelper { 9 | // https://thecodebarbarian.com/80-20-guide-to-express-error-handling 10 | static wrapAsync = (fn: any) => { 11 | // eslint-disable-next-line func-names 12 | return function (req: express.Request, res: express.Response, next: express.NextFunction) { 13 | // Make sure to `.catch()` any errors and pass them along to the `next()` 14 | // middleware in the chain, in this case the error handler. 15 | fn(req, res, next).catch(next); 16 | }; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/router/routes/wellKnownUriRoute.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { SmartStrategy } from '@aws/fhir-works-on-aws-interface'; 7 | import express, { Router } from 'express'; 8 | import { getWellKnownUriResponse } from '../handlers/wellKnownUriHandler'; 9 | 10 | export default class WellKnownUriRouteRoute { 11 | readonly router: Router; 12 | 13 | readonly smartStrategy: SmartStrategy; 14 | 15 | constructor(smartStrategy: SmartStrategy) { 16 | this.router = express.Router(); 17 | this.smartStrategy = smartStrategy; 18 | this.init(); 19 | } 20 | 21 | private init() { 22 | this.router.get('/', async (req: express.Request, res: express.Response) => { 23 | const response = getWellKnownUriResponse(this.smartStrategy); 24 | res.contentType('application/json'); 25 | res.send(response); 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/router/validation/subscriptionSchema.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "properties": { 4 | "resourceType": { 5 | "const": "Subscription" 6 | }, 7 | "status": { 8 | "type": "string", 9 | "enum": ["requested", "off"], 10 | "errorMessage": "should be 'requested' or 'off'" 11 | }, 12 | "reason": { 13 | "type": "string" 14 | }, 15 | "criteria": { 16 | "type": "string" 17 | }, 18 | "channel": { 19 | "type": "object", 20 | "properties": { 21 | "type": { 22 | "const": "rest-hook", 23 | "errorMessage": "should be equal to 'rest-hook'" 24 | }, 25 | "endpoint": { 26 | "type": "string", 27 | "pattern": "^https:" 28 | }, 29 | "payload": { 30 | "const": "application/fhir+json", 31 | "errorMessage": "should be equal to 'application/fhir+json'" 32 | }, 33 | "header": { 34 | "type": "array", 35 | "items": [ 36 | { 37 | "type": "string" 38 | } 39 | ] 40 | } 41 | }, 42 | "required": ["type", "endpoint"] 43 | } 44 | }, 45 | "required": ["resourceType", "status", "criteria", "channel"] 46 | } 47 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/router/validation/validationUtilities.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { InvalidResourceError, TypeOperation, Validator } from '@aws/fhir-works-on-aws-interface'; 7 | import { validateXHTMLResource } from '../handlers/utils'; 8 | 9 | export async function validateResource( 10 | validators: Validator[], 11 | resourceType: string, 12 | resource: any, 13 | params: { tenantId?: string; typeOperation?: TypeOperation } = {} 14 | ): Promise { 15 | if (resourceType !== resource.resourceType) { 16 | throw new InvalidResourceError(`not a valid '${resourceType}'`); 17 | } 18 | if (process.env.VALIDATE_XHTML === 'true' && !validateXHTMLResource(resource)) { 19 | throw new InvalidResourceError(`invalid resource html present in ${resourceType}`); 20 | } 21 | for (let i = 0; i < validators.length; i += 1) { 22 | // eslint-disable-next-line no-await-in-loop 23 | await validators[i].validate(resource, params); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/sampleData/invalidV4Patient.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "Patient", 3 | "id": "xcda", 4 | "text": { 5 | "status": "generated" 6 | }, 7 | "active": true, 8 | "name": [ 9 | { 10 | "family": "Levin", 11 | "given": ["Henry"] 12 | } 13 | ], 14 | "gender": "NONEXISTING_GENDER", 15 | "birthDate": "1932-09-24", 16 | "managingOrganization": { 17 | "reference": "Organization/2.16.840.1.113883.19.5", 18 | "display": "Good Health Clinic" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/sampleData/r4FhirConfigGeneric.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Authorization, 3 | BulkDataAccess, 4 | Bundle, 5 | FhirConfig, 6 | History, 7 | Persistence, 8 | Search, 9 | stubs as fwoaStubs 10 | } from '@aws/fhir-works-on-aws-interface'; 11 | 12 | const config = (stubs: { 13 | bundle: Bundle; 14 | search: Search; 15 | history: History; 16 | passThroughAuthz: Authorization; 17 | persistence: Persistence; 18 | bulkDataAccess: BulkDataAccess; 19 | }): FhirConfig => ({ 20 | configVersion: 1, 21 | validators: [], 22 | productInfo: { 23 | orgName: 'Organization Name' 24 | }, 25 | auth: { 26 | strategy: {}, 27 | authorization: stubs.passThroughAuthz 28 | }, 29 | server: { 30 | url: 'http://example.com' 31 | }, 32 | profile: { 33 | fhirVersion: '4.0.1', 34 | systemOperations: [], 35 | bundle: stubs.bundle, 36 | systemSearch: stubs.search, 37 | systemHistory: stubs.history, 38 | genericResource: { 39 | operations: ['create', 'read', 'update', 'delete', 'vread', 'history-instance'], 40 | fhirVersions: ['4.0.1'], 41 | persistence: stubs.persistence, 42 | typeSearch: stubs.search, 43 | typeHistory: stubs.history 44 | } 45 | } 46 | }); 47 | 48 | const configFn = (overrideStubs?: any) => { 49 | return config({ ...fwoaStubs, ...overrideStubs }); 50 | }; 51 | 52 | export default configFn; 53 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/sampleData/validV3Account.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "Account", 3 | "text": { 4 | "status": "generated", 5 | "div": "
HACC Funded Billing for Peter James Chalmers
" 6 | }, 7 | "identifier": [ 8 | { 9 | "system": "urn:oid:0.1.2.3.4.5.6.7", 10 | "value": "654321" 11 | } 12 | ], 13 | "status": "active", 14 | "type": { 15 | "coding": [ 16 | { 17 | "system": "http://hl7.org/fhir/v3/ActCode", 18 | "code": "PBILLACCT", 19 | "display": "patient billing account" 20 | } 21 | ], 22 | "text": "patient" 23 | }, 24 | "name": "HACC Funded Billing for Peter James Chalmers", 25 | "subject": { 26 | "reference": "Patient/example", 27 | "display": "Peter James Chalmers" 28 | }, 29 | "period": { 30 | "start": "2016-01-01", 31 | "end": "2016-06-30" 32 | }, 33 | "active": { 34 | "start": "2016-01-01", 35 | "end": "2016-06-30" 36 | }, 37 | "balance": { 38 | "value": -1200, 39 | "unit": "USD", 40 | "system": "urn:iso:std:iso:4217", 41 | "code": "USD" 42 | }, 43 | "coverage": [ 44 | { 45 | "coverage": { 46 | "reference": "Coverage/7546D" 47 | }, 48 | "priority": 1 49 | } 50 | ], 51 | "owner": { 52 | "reference": "Organization/hl7" 53 | }, 54 | "description": "Hospital charges" 55 | } 56 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/sampleData/validV4Account.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "Account", 3 | "id": "example", 4 | "text": { 5 | "status": "generated", 6 | "div": "
HACC Funded Billing for Peter James Chalmers
" 7 | }, 8 | "identifier": [ 9 | { 10 | "system": "urn:oid:0.1.2.3.4.5.6.7", 11 | "value": "654321" 12 | } 13 | ], 14 | "status": "active", 15 | "type": { 16 | "coding": [ 17 | { 18 | "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", 19 | "code": "PBILLACCT", 20 | "display": "patient billing account" 21 | } 22 | ], 23 | "text": "patient" 24 | }, 25 | "name": "HACC Funded Billing for Peter James Chalmers", 26 | "subject": [ 27 | { 28 | "reference": "Patient/example", 29 | "display": "Peter James Chalmers" 30 | } 31 | ], 32 | "servicePeriod": { 33 | "start": "2016-01-01", 34 | "end": "2016-06-30" 35 | }, 36 | "coverage": [ 37 | { 38 | "coverage": { 39 | "reference": "Coverage/7546D" 40 | }, 41 | "priority": 1 42 | } 43 | ], 44 | "owner": { 45 | "reference": "Organization/hl7" 46 | }, 47 | "description": "Hospital charges" 48 | } 49 | -------------------------------------------------------------------------------- /fwoa-core/routing/src/sampleData/validV4Patient.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "Patient", 3 | "id": "xcda", 4 | "text": { 5 | "status": "generated", 6 | "div": "

Henry Levin the 7th

" 7 | }, 8 | "active": true, 9 | "name": [ 10 | { 11 | "family": "Levin", 12 | "given": ["Henry"] 13 | } 14 | ], 15 | "gender": "male", 16 | "birthDate": "1932-09-24", 17 | "managingOrganization": { 18 | "reference": "Organization/2.16.840.1.113883.19.5", 19 | "display": "Good Health Clinic" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /fwoa-core/routing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/tsconfig", 3 | "extends": "./node_modules/@rushstack/heft-node-rig/profiles/default/tsconfig-base.json", 4 | "compilerOptions": { 5 | "types": ["heft-jest", "node"], 6 | "target": "es2019", // Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. 7 | "module": "commonjs", // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 8 | "strict": true, // // Enable all strict type-checking options. 9 | "esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 10 | "forceConsistentCasingInFileNames": true, // Disallow inconsistently-cased references to the same file. 11 | "outDir": "lib", 12 | "lib": ["ES2020.Promise", "dom"], 13 | "declaration": true, 14 | "sourceMap": true, 15 | "resolveJsonModule": true, 16 | "baseUrl": "." 17 | }, 18 | "include": ["src/**/*"] 19 | } 20 | -------------------------------------------------------------------------------- /fwoa-core/search-es/.eslintignore: -------------------------------------------------------------------------------- 1 | .eslintrc.js 2 | node_modules 3 | lib 4 | temp 5 | scripts -------------------------------------------------------------------------------- /fwoa-core/search-es/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This is a workaround for https://github.com/eslint/eslint/issues/3458 2 | require('@rushstack/eslint-config/patch/modern-module-resolution'); 3 | 4 | module.exports = { 5 | extends: ['@aws/eslint-config-fwoa-eslint-custom'], 6 | parserOptions: { tsconfigRootDir: __dirname }, 7 | overrides: [ 8 | { 9 | files: ['*.ts'], 10 | rules: { 11 | '@typescript-eslint/no-explicit-any': 'off', 12 | '@typescript-eslint/explicit-member-accessibility': 'off', 13 | 'security/detect-object-injection': 'off', 14 | '@typescript-eslint/explicit-function-return-type': 'off', 15 | '@rushstack/typedef-var': 'off', 16 | '@typescript-eslint/typedef': 'off', 17 | 'tsdoc/syntax': 'off', 18 | 'security/detect-unsafe-regex': 'off', 19 | 'import/no-named-as-default-member': 'off' 20 | } 21 | } 22 | ] 23 | }; 24 | -------------------------------------------------------------------------------- /fwoa-core/search-es/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | 3 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 4 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 5 | opensource-codeofconduct@amazon.com with any additional questions or comments. 6 | -------------------------------------------------------------------------------- /fwoa-core/search-es/config/jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rushstack/heft-node-rig/profiles/default/config/jest.config.json", 3 | "collectCoverage": true, 4 | "coverageThreshold": { 5 | "global": { 6 | "branches": 70, 7 | "functions": 50, 8 | "lines": 70, 9 | "statements": 70 10 | } 11 | }, 12 | "coveragePathIgnorePatterns": [], 13 | "coverageReporters": ["json-summary", "json", "lcov", "text"] 14 | } 15 | -------------------------------------------------------------------------------- /fwoa-core/search-es/config/rig.json: -------------------------------------------------------------------------------- 1 | // The "rig.json" file directs tools to look for their config files in an external package. 2 | // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package 3 | { 4 | "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", 5 | 6 | /** 7 | * (Required) The name of the rig package to inherit from. 8 | * It should be an NPM package name with the "-rig" suffix. 9 | */ 10 | "rigPackageName": "@rushstack/heft-node-rig" 11 | 12 | /** 13 | * (Optional) Selects a config profile from the rig package. The name must consist of 14 | * lowercase alphanumeric words separated by hyphens, for example "sample-profile". 15 | * If omitted, then the "default" profile will be used." 16 | */ 17 | // "rigProfile": "your-profile-name" 18 | } 19 | -------------------------------------------------------------------------------- /fwoa-core/search-es/jest.env.js: -------------------------------------------------------------------------------- 1 | global.setImmediate = global.setImmediate || ((fn, ...args) => global.setTimeout(fn, 0, ...args)); 2 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/FhirQueryParser/typeParsers/numberParser.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | import { InvalidSearchParameterError } from '@aws/fhir-works-on-aws-interface'; 8 | import { parseNumber } from '../../QueryBuilder/typeQueries/common/number'; 9 | 10 | export interface NumberSearchValue { 11 | prefix: string; 12 | number: number; 13 | implicitRange: { 14 | start: number; 15 | end: number; 16 | }; 17 | } 18 | 19 | const NUMBER_SEARCH_PARAM_REGEX = /^(?eq|ne|lt|gt|ge|le|sa|eb|ap)?(?[\d.+-eE]+)$/; 20 | export const parseNumberSearchValue = (param: string): NumberSearchValue => { 21 | const match = param.match(NUMBER_SEARCH_PARAM_REGEX); 22 | if (match === null) { 23 | throw new InvalidSearchParameterError(`Invalid number search parameter: ${param}`); 24 | } 25 | 26 | const { numberString } = match.groups!; 27 | 28 | // If no prefix is present, the prefix eq is assumed. 29 | // https://www.hl7.org/fhir/search.html#prefix 30 | const prefix = match.groups!.prefix ?? 'eq'; 31 | 32 | const fhirNumber = parseNumber(numberString); 33 | return { 34 | prefix, 35 | ...fhirNumber 36 | }; 37 | }; 38 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/FhirQueryParser/typeParsers/quantityParser.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | import { InvalidSearchParameterError } from '@aws/fhir-works-on-aws-interface'; 8 | import { parseNumber } from '../../QueryBuilder/typeQueries/common/number'; 9 | 10 | export interface QuantitySearchValue { 11 | prefix: string; 12 | system: string; 13 | code: string; 14 | number: number; 15 | implicitRange: { 16 | start: number; 17 | end: number; 18 | }; 19 | } 20 | 21 | const QUANTITY_SEARCH_PARAM_REGEX = 22 | /^(?eq|ne|lt|gt|ge|le|sa|eb|ap)?(?[\d.+-eE]+)(\|(?[^|\s]*)\|(?[^|\s]*))?$/; 23 | export const parseQuantitySearchValue = (param: string): QuantitySearchValue => { 24 | const match = param.match(QUANTITY_SEARCH_PARAM_REGEX); 25 | if (match === null) { 26 | throw new InvalidSearchParameterError(`Invalid quantity search parameter: ${param}`); 27 | } 28 | 29 | const { numberString, system = '', code = '' } = match.groups!; 30 | 31 | // If no prefix is present, the prefix eq is assumed. 32 | // https://www.hl7.org/fhir/search.html#prefix 33 | const prefix = match.groups!.prefix ?? 'eq'; 34 | 35 | const fhirNumber = parseNumber(numberString); 36 | return { 37 | prefix, 38 | system, 39 | code, 40 | ...fhirNumber 41 | }; 42 | }; 43 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/FhirQueryParser/typeParsers/tokenParser.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | import { InvalidSearchParameterError } from '@aws/fhir-works-on-aws-interface'; 8 | 9 | export interface TokenSearchValue { 10 | system?: string; 11 | code?: string; 12 | explicitNoSystemProperty: boolean; 13 | } 14 | 15 | // eslint-disable-next-line import/prefer-default-export 16 | export const parseTokenSearchValue = (param: string): TokenSearchValue => { 17 | if (param === '|') { 18 | throw new InvalidSearchParameterError(`Invalid token search parameter: ${param}`); 19 | } 20 | const parts = param.split('|'); 21 | if (parts.length > 2) { 22 | throw new InvalidSearchParameterError(`Invalid token search parameter: ${param}`); 23 | } 24 | let system; 25 | let code; 26 | let explicitNoSystemProperty = false; 27 | if (parts.length === 1) { 28 | [code] = parts; 29 | } else { 30 | [system, code] = parts; 31 | if (system === '') { 32 | system = undefined; 33 | explicitNoSystemProperty = true; 34 | } 35 | if (code === '') { 36 | code = undefined; 37 | } 38 | } 39 | return { system, code, explicitNoSystemProperty }; 40 | }; 41 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/FhirQueryParser/util.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { parseSearchModifiers } from './util'; 7 | 8 | describe('getSearchModifiers', () => { 9 | test('name:exact', () => { 10 | expect(parseSearchModifiers('name:exact')).toMatchInlineSnapshot(` 11 | Object { 12 | "modifier": "exact", 13 | "parameterName": "name", 14 | } 15 | `); 16 | }); 17 | 18 | test('name', () => { 19 | expect(parseSearchModifiers('name')).toMatchInlineSnapshot(` 20 | Object { 21 | "modifier": undefined, 22 | "parameterName": "name", 23 | } 24 | `); 25 | }); 26 | 27 | test('name:contains', () => { 28 | expect(parseSearchModifiers('name:contains')).toMatchInlineSnapshot(` 29 | Object { 30 | "modifier": "contains", 31 | "parameterName": "name", 32 | } 33 | `); 34 | }); 35 | 36 | test('name:', () => { 37 | expect(parseSearchModifiers('name:')).toMatchInlineSnapshot(` 38 | Object { 39 | "modifier": "", 40 | "parameterName": "name", 41 | } 42 | `); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/InMemoryMatcher/matchers/numberMatch.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | import { NumberSearchValue } from '../../FhirQueryParser'; 8 | import { applyPrefixRulesToRange, compareNumberToRange } from './common/numericComparison'; 9 | 10 | // eslint-disable-next-line import/prefer-default-export 11 | export const numberMatch = (value: NumberSearchValue, resourceValue: any): boolean => { 12 | const { prefix, implicitRange, number } = value; 13 | 14 | if (typeof resourceValue !== 'number') { 15 | return false; 16 | } 17 | 18 | return compareNumberToRange(prefix, applyPrefixRulesToRange(prefix, number, implicitRange), resourceValue); 19 | }; 20 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/InMemoryMatcher/matchers/quantityMatch.ts: -------------------------------------------------------------------------------- 1 | import { isEmpty } from 'lodash'; 2 | import { QuantitySearchValue } from '../../FhirQueryParser'; 3 | import { applyPrefixRulesToRange, compareNumberToRange } from './common/numericComparison'; 4 | 5 | // eslint-disable-next-line import/prefer-default-export 6 | export const quantityMatch = (value: QuantitySearchValue, resourceValue: any): boolean => { 7 | const { prefix, implicitRange, number, system, code } = value; 8 | 9 | if (typeof resourceValue?.value !== 'number') { 10 | return false; 11 | } 12 | 13 | if ( 14 | !compareNumberToRange(prefix, applyPrefixRulesToRange(prefix, number, implicitRange), resourceValue.value) 15 | ) { 16 | return false; 17 | } 18 | 19 | if (isEmpty(system) && isEmpty(code)) { 20 | return true; 21 | } 22 | 23 | if (!isEmpty(system) && !isEmpty(code)) { 24 | return resourceValue?.code === code && resourceValue?.system === system; 25 | } 26 | if (!isEmpty(code)) { 27 | // when there is no system, search either the code (code) or the stated human unit (unit) 28 | // https://www.hl7.org/fhir/search.html#quantity 29 | return resourceValue?.code === code || resourceValue?.unit === code; 30 | } 31 | 32 | return false; 33 | }; 34 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/InMemoryMatcher/matchers/uriMatch.test.ts: -------------------------------------------------------------------------------- 1 | import { uriMatch } from './uriMatch'; 2 | 3 | describe('uriMatch', () => { 4 | test('matches string', () => { 5 | expect(uriMatch('https://fwoa.com', 'https://fwoa.com')).toBe(true); 6 | expect(uriMatch('https://fwoa.com', 'something else')).toBe(false); 7 | }); 8 | 9 | test('not a string', () => { 10 | expect(uriMatch('https://fwoa.com', [])).toBe(false); 11 | expect(uriMatch('https://fwoa.com', {})).toBe(false); 12 | expect(uriMatch('https://fwoa.com', 23.1)).toBe(false); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/InMemoryMatcher/matchers/uriMatch.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | import { StringLikeSearchValue } from '../../FhirQueryParser'; 8 | 9 | // eslint-disable-next-line import/prefer-default-export 10 | export const uriMatch = (searchValue: StringLikeSearchValue, resourceValue: any): boolean => { 11 | return searchValue === resourceValue; 12 | }; 13 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/QueryBuilder/typeQueries/dateQuery.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { InvalidSearchParameterError } from '@aws/fhir-works-on-aws-interface'; 7 | import { DateSearchValue } from '../../FhirQueryParser'; 8 | import { CompiledSearchParam } from '../../FHIRSearchParametersRegistry'; 9 | import { prefixRangeDate } from './common/prefixRange'; 10 | 11 | const SUPPORTED_MODIFIERS: string[] = []; 12 | 13 | // eslint-disable-next-line import/prefer-default-export 14 | export const dateQuery = ( 15 | compiledSearchParam: CompiledSearchParam, 16 | value: DateSearchValue, 17 | modifier?: string 18 | ): any => { 19 | if (modifier && !SUPPORTED_MODIFIERS.includes(modifier)) { 20 | throw new InvalidSearchParameterError(`Unsupported date search modifier: ${modifier}`); 21 | } 22 | const { prefix, range } = value; 23 | return prefixRangeDate(prefix, range, compiledSearchParam.path); 24 | }; 25 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/QueryBuilder/typeQueries/numberQuery.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { InvalidSearchParameterError } from '@aws/fhir-works-on-aws-interface'; 7 | import { NumberSearchValue } from '../../FhirQueryParser'; 8 | import { CompiledSearchParam } from '../../FHIRSearchParametersRegistry'; 9 | import { prefixRangeNumber } from './common/prefixRange'; 10 | 11 | const SUPPORTED_MODIFIERS: string[] = []; 12 | 13 | // eslint-disable-next-line import/prefer-default-export 14 | export const numberQuery = ( 15 | compiledSearchParam: CompiledSearchParam, 16 | value: NumberSearchValue, 17 | modifier?: string 18 | ): any => { 19 | if (modifier && !SUPPORTED_MODIFIERS.includes(modifier)) { 20 | throw new InvalidSearchParameterError(`Unsupported number search modifier: ${modifier}`); 21 | } 22 | const { prefix, implicitRange, number } = value; 23 | return prefixRangeNumber(prefix, number, implicitRange, compiledSearchParam.path); 24 | }; 25 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/QueryBuilder/typeQueries/uriQuery.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { InvalidSearchParameterError } from '@aws/fhir-works-on-aws-interface'; 7 | import { CompiledSearchParam } from '../../FHIRSearchParametersRegistry'; 8 | 9 | const SUPPORTED_MODIFIERS: string[] = []; 10 | 11 | // eslint-disable-next-line import/prefer-default-export 12 | export function uriQuery( 13 | compiled: CompiledSearchParam, 14 | value: string, 15 | useKeywordSubFields: boolean, 16 | modifier?: string 17 | ): any { 18 | if (modifier && !SUPPORTED_MODIFIERS.includes(modifier)) { 19 | throw new InvalidSearchParameterError(`Unsupported URI search modifier: ${modifier}`); 20 | } 21 | const keywordSuffix = useKeywordSubFields ? '.keyword' : ''; 22 | 23 | return { 24 | multi_match: { 25 | fields: [`${compiled.path}${keywordSuffix}`], 26 | query: value, 27 | lenient: true 28 | } 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/StreamSubscriptionMatcher/AsyncRefreshCache.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | /** 7 | * Periodically calls an async fn and keeps its latest response value cached. 8 | */ 9 | // eslint-disable-next-line import/prefer-default-export 10 | export class AsyncRefreshCache { 11 | private values: Promise; 12 | 13 | // eslint-disable-next-line no-undef 14 | private readonly interval: NodeJS.Timeout; 15 | 16 | /** 17 | * @param loadFn - async function to be called periodically 18 | * @param period - wait time in seconds before calling `loadFn` again 19 | */ 20 | constructor(loadFn: () => Promise, period = 3000) { 21 | this.values = loadFn(); 22 | this.interval = setInterval(() => { 23 | this.values = loadFn(); 24 | }, period); 25 | } 26 | 27 | async get(): Promise { 28 | return this.values; 29 | } 30 | 31 | stop() { 32 | clearInterval(this.interval); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/StreamSubscriptionMatcher/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | export * from './StreamSubscriptionMatcher'; 8 | export * from './subscriptions'; 9 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/__mocks__/elasticSearch.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/prefer-default-export 2 | export const ElasticSearch = { 3 | search: jest.fn().mockName('searchMock'), 4 | msearch: jest.fn().mockName('msearchMock') 5 | }; 6 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/constants.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | export const DEFAULT_SEARCH_RESULTS_PER_PAGE = 20; 7 | 8 | export const enum SEARCH_PAGINATION_PARAMS { 9 | PAGES_OFFSET = '_getpagesoffset', 10 | COUNT = '_count' 11 | } 12 | 13 | export const SEPARATOR: string = '_'; 14 | export const ITERATIVE_INCLUSION_PARAMETERS = ['_include:iterate', '_revinclude:iterate']; 15 | export const INCLUSION_PARAMETERS = ['_include', '_revinclude', ...ITERATIVE_INCLUSION_PARAMETERS]; 16 | export const UNSUPPORTED_GENERAL_PARAMETERS = ['_format', '_pretty', '_summary', '_elements']; 17 | export const SORT_PARAMETER = '_sort'; 18 | export const COMPILED_CONDITION_OPERATOR_RESOLVE = 'resolve'; 19 | export const NON_SEARCHABLE_PARAMETERS = [ 20 | SORT_PARAMETER, 21 | SEARCH_PAGINATION_PARAMS.PAGES_OFFSET, 22 | SEARCH_PAGINATION_PARAMS.COUNT, 23 | ...INCLUSION_PARAMETERS, 24 | ...UNSUPPORTED_GENERAL_PARAMETERS 25 | ]; 26 | 27 | export const MAX_ES_WINDOW_SIZE: number = 10000; 28 | 29 | export const MAX_CHAINED_PARAMS_RESULT: number = 100; 30 | 31 | export const MAX_INCLUSION_PARAM_RESULTS: number = 1000; 32 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/elasticSearch.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { Client } from '@elastic/elasticsearch'; 7 | // @ts-ignore 8 | import { AmazonConnection, AmazonTransport } from 'aws-elasticsearch-connector'; 9 | import AWS from 'aws-sdk'; 10 | 11 | const { IS_OFFLINE } = process.env; 12 | 13 | let esDomainEndpoint = process.env.ELASTICSEARCH_DOMAIN_ENDPOINT || 'https://fake-es-endpoint.com'; 14 | if (IS_OFFLINE === 'true') { 15 | AWS.config.update({ 16 | region: process.env.AWS_REGION || 'us-west-2', 17 | accessKeyId: process.env.ACCESS_KEY, 18 | secretAccessKey: process.env.SECRET_KEY 19 | }); 20 | esDomainEndpoint = process.env.OFFLINE_ELASTICSEARCH_DOMAIN_ENDPOINT || 'https://fake-es-endpoint.com'; 21 | } 22 | 23 | // eslint-disable-next-line import/prefer-default-export 24 | export const ElasticSearch = new Client({ 25 | node: esDomainEndpoint, 26 | Connection: AmazonConnection, 27 | Transport: AmazonTransport 28 | }); 29 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | export * from './elasticSearchService'; 7 | export * from './implementationGuides'; 8 | export * from './searchMappings'; 9 | export * from './searchMappingsManager'; 10 | export * from './StreamSubscriptionMatcher'; 11 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/loggerBuilder.ts: -------------------------------------------------------------------------------- 1 | import { makeLogger } from '@aws/fhir-works-on-aws-interface'; 2 | 3 | const componentLogger = makeLogger({ 4 | component: 'search' 5 | }); 6 | 7 | export default function getComponentLogger(): any { 8 | return componentLogger; 9 | } 10 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/searchMappings/customMappings.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | /** 8 | * This mappings will be applied to ALL resource types (they override any existing mappings). 9 | */ 10 | // eslint-disable-next-line import/prefer-default-export 11 | export const CUSTOM_MAPPINGS = { 12 | id: { 13 | type: 'keyword', 14 | index: true 15 | }, 16 | resourceType: { 17 | type: 'keyword', 18 | index: true 19 | }, 20 | _references: { 21 | type: 'keyword', 22 | index: true 23 | }, 24 | documentStatus: { 25 | type: 'keyword', 26 | index: true 27 | }, 28 | _tenantId: { 29 | type: 'keyword', 30 | index: true 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/searchMappings/index.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | import { getSearchMappings } from './index'; 8 | 9 | describe('getSearchMappings', () => { 10 | test('R4 snapshot', () => { 11 | expect(getSearchMappings('4.0.1')).toMatchSnapshot(); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/searchParametersMapping.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | const SEARCH_PARAMETER_TO_DOCUMENT_FIELD = { 6 | _id: 'id', 7 | id: 'id' 8 | }; 9 | 10 | const hasMapping = ( 11 | searchParameter: string 12 | ): searchParameter is keyof typeof SEARCH_PARAMETER_TO_DOCUMENT_FIELD => { 13 | return searchParameter in SEARCH_PARAMETER_TO_DOCUMENT_FIELD; 14 | }; 15 | 16 | // eslint-disable-next-line import/prefer-default-export 17 | export const getDocumentField = (searchParameter: string) => { 18 | if (hasMapping(searchParameter)) { 19 | return SEARCH_PARAMETER_TO_DOCUMENT_FIELD[searchParameter]; 20 | } 21 | return `${searchParameter}.*`; 22 | }; 23 | -------------------------------------------------------------------------------- /fwoa-core/search-es/src/tsUtils.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/prefer-default-export 2 | export function isPresent(t: T | undefined | void): t is T { 3 | return t !== undefined; 4 | } 5 | -------------------------------------------------------------------------------- /fwoa-core/search-es/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/tsconfig", 3 | "extends": "./node_modules/@rushstack/heft-node-rig/profiles/default/tsconfig-base.json", 4 | "compilerOptions": { 5 | "types": ["heft-jest", "node"], 6 | "target": "es2019", // Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. 7 | "module": "commonjs", // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 8 | "strict": true, // // Enable all strict type-checking options. 9 | "esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 10 | "forceConsistentCasingInFileNames": true, // Disallow inconsistently-cased references to the same file. 11 | "outDir": "lib", 12 | "lib": ["es2019"], 13 | "declaration": true, 14 | "sourceMap": true, 15 | "resolveJsonModule": true, 16 | "baseUrl": "." 17 | }, 18 | "include": ["src/**/*"] 19 | } 20 | -------------------------------------------------------------------------------- /fwoa-tools/.eslintignore: -------------------------------------------------------------------------------- 1 | .eslintrc.js 2 | node_modules 3 | lib 4 | temp -------------------------------------------------------------------------------- /fwoa-tools/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This is a workaround for https://github.com/eslint/eslint/issues/3458 2 | require('@rushstack/eslint-config/patch/modern-module-resolution'); 3 | 4 | module.exports = { 5 | extends: ['@aws/eslint-config-fwoa-eslint-custom'], 6 | parserOptions: { tsconfigRootDir: __dirname } 7 | }; 8 | -------------------------------------------------------------------------------- /fwoa-tools/config/jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rushstack/heft-node-rig/profiles/default/config/jest.config.json", 3 | "collectCoverage": true, 4 | "coverageThreshold": { 5 | "global": { 6 | "branches": 60, 7 | "functions": 80, 8 | "lines": 80, 9 | "statements": 80 10 | } 11 | }, 12 | "coveragePathIgnorePatterns": ["/src/index.ts"], 13 | "testPathIgnorePatterns": ["/node_modules/", "/integration-tests/"], 14 | "coverageReporters": ["json-summary", "json", "lcov", "text"] 15 | } 16 | -------------------------------------------------------------------------------- /fwoa-tools/config/rig.json: -------------------------------------------------------------------------------- 1 | // The "rig.json" file directs tools to look for their config files in an external package. 2 | // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package 3 | { 4 | "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", 5 | 6 | /** 7 | * (Required) The name of the rig package to inherit from. 8 | * It should be an NPM package name with the "-rig" suffix. 9 | */ 10 | "rigPackageName": "@rushstack/heft-node-rig" 11 | 12 | /** 13 | * (Optional) Selects a config profile from the rig package. The name must consist of 14 | * lowercase alphanumeric words separated by hyphens, for example "sample-profile". 15 | * If omitted, then the "default" profile will be used." 16 | */ 17 | // "rigProfile": "your-profile-name" 18 | } 19 | -------------------------------------------------------------------------------- /fwoa-tools/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | export * from './migrationUtils'; 6 | -------------------------------------------------------------------------------- /fwoa-tools/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/tsconfig", 3 | "extends": "./node_modules/@rushstack/heft-node-rig/profiles/default/tsconfig-base.json", 4 | "compilerOptions": { 5 | "types": ["heft-jest", "node"], 6 | "target": "es2019", 7 | "module": "commonjs", 8 | "strict": true, 9 | "esModuleInterop": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "outDir": "lib", 12 | "declaration": true, 13 | "sourceMap": true, 14 | "resolveJsonModule": true, 15 | "baseUrl": ".", 16 | "moduleResolution": "node" 17 | }, 18 | "include": ["src/**/*"] 19 | } 20 | -------------------------------------------------------------------------------- /fwoa-utilities/.eslintignore: -------------------------------------------------------------------------------- 1 | .eslintrc.js 2 | node_modules 3 | lib 4 | temp -------------------------------------------------------------------------------- /fwoa-utilities/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This is a workaround for https://github.com/eslint/eslint/issues/3458 2 | require('@rushstack/eslint-config/patch/modern-module-resolution'); 3 | 4 | module.exports = { 5 | extends: ['@aws/eslint-config-fwoa-eslint-custom'], 6 | parserOptions: { tsconfigRootDir: __dirname } 7 | }; 8 | -------------------------------------------------------------------------------- /fwoa-utilities/javaHapiValidatorLambda/src/main/java/software/amazon/fwoa/ValidatorResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package software.amazon.fwoa; 7 | 8 | import java.util.List; 9 | 10 | import lombok.Builder; 11 | import lombok.Value; 12 | 13 | @Builder 14 | @Value 15 | class ValidatorResponse { 16 | private boolean isSuccessful; 17 | private List errorMessages; 18 | } 19 | 20 | @Builder 21 | @Value 22 | class ValidatorErrorMessage { 23 | private String severity; 24 | private String msg; 25 | } 26 | -------------------------------------------------------------------------------- /fwoa-utilities/javaHapiValidatorLambda/src/main/java/software/amazon/fwoa/models/IgFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package software.amazon.fwoa.models; 7 | 8 | import com.google.gson.annotations.Expose; 9 | import com.google.gson.annotations.SerializedName; 10 | 11 | public class IgFile { 12 | @SerializedName("filename") 13 | @Expose 14 | public String filename; 15 | @SerializedName("resourceType") 16 | @Expose 17 | public String resourceType; 18 | @SerializedName("id") 19 | @Expose 20 | public String id; 21 | @SerializedName("url") 22 | @Expose 23 | public String url; 24 | @SerializedName("version") 25 | @Expose 26 | public String version; 27 | @SerializedName("type") 28 | @Expose 29 | public String type; 30 | @SerializedName("kind") 31 | @Expose 32 | public String kind; 33 | } 34 | -------------------------------------------------------------------------------- /fwoa-utilities/javaHapiValidatorLambda/src/main/java/software/amazon/fwoa/models/IgIndex.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package software.amazon.fwoa.models; 7 | 8 | import java.util.List; 9 | 10 | import com.google.gson.annotations.Expose; 11 | import com.google.gson.annotations.SerializedName; 12 | 13 | public class IgIndex { 14 | @SerializedName("index-version") 15 | @Expose 16 | public Integer indexVersion; 17 | @SerializedName("files") 18 | @Expose 19 | public List files = null; 20 | } 21 | -------------------------------------------------------------------------------- /fwoa-utilities/javaHapiValidatorLambda/src/main/resources/implementationGuides/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/fwoa-utilities/javaHapiValidatorLambda/src/main/resources/implementationGuides/.gitkeep -------------------------------------------------------------------------------- /fwoa-utilities/javaHapiValidatorLambda/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{yyyy-MM-dd HH:mm:ss} %X{AWSRequestId} %-5p %c{1}:%L - %m%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /fwoa-utilities/javaHapiValidatorLambda/src/test/resources/testImplementationGuides-r4/us-core/ValueSet-us-core-documentreference-category.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "ValueSet", 3 | "id": "us-core-documentreference-category", 4 | "text": { 5 | "status": "generated", 6 | "div": "" 7 | }, 8 | "url": "http://hl7.org/fhir/us/core/ValueSet/us-core-documentreference-category", 9 | "version": "3.1.1", 10 | "name": "USCoreDocumentReferenceCategory", 11 | "title": "US Core DocumentReference Category", 12 | "status": "active", 13 | "date": "2019-05-21", 14 | "publisher": "HL7 US Realm Steering Committee", 15 | "contact": [{ "telecom": [{ "system": "other", "value": "http://hl7.org/fhir" }] }], 16 | "description": "The US Core DocumentReferences Category Value Set is a 'starter set' of categories supported for fetching and storing clinical notes.", 17 | "jurisdiction": [ 18 | { "coding": [{ "system": "urn:iso:std:iso:3166", "code": "US", "display": "United States of America" }] } 19 | ], 20 | "compose": { 21 | "include": [{ "system": "http://hl7.org/fhir/us/core/CodeSystem/us-core-documentreference-category" }] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /fwoa-utilities/javaHapiValidatorLambda/src/test/resources/testImplementationGuides-r4/us-core/ValueSet-us-core-observation-smokingstatus-max.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "ValueSet", 3 | "id": "us-core-observation-smokingstatus-max", 4 | "text": { 5 | "status": "generated", 6 | "div": "
" 7 | }, 8 | "url": "http://hl7.org/fhir/us/core/ValueSet/us-core-observation-smokingstatus-max", 9 | "version": "3.1.1", 10 | "name": "USCoreSmokingStatusmaxValueSet", 11 | "title": "US Core Smoking Status Max-Binding", 12 | "status": "active", 13 | "date": "2020-06-29", 14 | "publisher": "HL7 US Realm Steering Committee", 15 | "contact": [{ "telecom": [{ "system": "other", "value": "http://hl7.org/fhir" }] }], 16 | "description": "Representing a patient’s smoking behavior using concepts from SNOMED CT.", 17 | "jurisdiction": [ 18 | { "coding": [{ "system": "urn:iso:std:iso:3166", "code": "US", "display": "United States of America" }] } 19 | ], 20 | "copyright": "This value set includes content from SNOMED CT, which is copyright © 2002+ International Health Terminology Standards Development Organisation (IHTSDO), and distributed by agreement between IHTSDO and HL7. Implementer use of SNOMED CT is not covered by this agreement", 21 | "compose": { "include": [{ "system": "http://snomed.info/sct" }] } 22 | } 23 | -------------------------------------------------------------------------------- /fwoa-utilities/javaHapiValidatorLambda/src/test/resources/testImplementationGuides-stu3/us-core/Encounter-1036.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "Encounter", 3 | "id": "1036", 4 | "text": { 5 | "status": "generated", 6 | "div": "

Generated Narrative with Details

id: 1036

status: in-progress

class: inpatient encounter (Details: http://hl7.org/fhir/v3/ActCode code IMP = 'inpatient encounter', stated as 'inpatient encounter')

subject: Generated Summary: id: example; Medical Record Number = 1032702 (USUAL); active; Amy V. Shaw ; ph: 555-555-5555(HOME), amy.shaw@example.com; gender: female; birthDate: 20/02/2007

" 7 | }, 8 | "status": "in-progress", 9 | "class": { "system": "http://hl7.org/fhir/v3/ActCode", "code": "IMP", "display": "inpatient encounter" }, 10 | "subject": { "reference": "Patient/example" } 11 | } 12 | -------------------------------------------------------------------------------- /fwoa-utilities/javaHapiValidatorLambda/src/test/resources/testImplementationGuides-stu3/us-core/Goal-goal-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "Goal", 3 | "id": "goal-1", 4 | "meta": { "profile": ["http://hl7.org/fhir/us/core/StructureDefinition/us-core-goal"] }, 5 | "text": { 6 | "status": "generated", 7 | "div": "

Generated Narrative with Details

id: goal-1

meta:

status: in-progress

description: Patient is targeting a pulse oximetry of 92% and a weight of 195 lbs (Details )

subject: Amy Shaw. Generated Summary: id: example; Medical Record Number = 1032702 (USUAL); active; Amy V. Shaw ; ph: 555-555-5555(HOME), amy.shaw@example.com; gender: female; birthDate: 20/02/2007

" 8 | }, 9 | "status": "in-progress", 10 | "description": { "text": "Patient is targeting a pulse oximetry of 92% and a weight of 195 lbs" }, 11 | "subject": { "reference": "Patient/example", "display": "Amy Shaw" } 12 | } 13 | -------------------------------------------------------------------------------- /fwoa-utilities/javaHapiValidatorLambda/src/test/resources/testImplementationGuides-stu3/us-core/Medication-uscore-med1.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "Medication", 3 | "id": "uscore-med1", 4 | "meta": { "profile": ["http://hl7.org/fhir/us/core/StructureDefinition/us-core-medication"] }, 5 | "text": { 6 | "status": "generated", 7 | "div": "

Generated Narrative with Details

id: uscore-med1

meta:

code: Prinivil 10 MG Oral Tablet (Details : {RxNorm code '206765' = 'Prinivil 10 MG Oral Tablet', given as 'Prinivil 10 MG Oral Tablet'})

" 8 | }, 9 | "code": { 10 | "coding": [ 11 | { 12 | "system": "http://www.nlm.nih.gov/research/umls/rxnorm", 13 | "code": "206765", 14 | "display": "Prinivil 10 MG Oral Tablet" 15 | } 16 | ], 17 | "text": "Prinivil 10 MG Oral Tablet" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fwoa-utilities/javaHapiValidatorLambda/src/test/resources/testImplementationGuides-stu3/us-core/Medication-uscore-med2.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "Medication", 3 | "id": "uscore-med2", 4 | "meta": { "profile": ["http://hl7.org/fhir/us/core/StructureDefinition/us-core-medication"] }, 5 | "text": { 6 | "status": "generated", 7 | "div": "

Generated Narrative with Details

id: uscore-med2

meta:

code: Nizatidine 15 MG/ML Oral Solution [Axid] (Details : {RxNorm code '582620' = 'Nizatidine 15 MG/ML Oral Solution [Axid]', given as 'Nizatidine 15 MG/ML Oral Solution [Axid]'})

" 8 | }, 9 | "code": { 10 | "coding": [ 11 | { 12 | "system": "http://www.nlm.nih.gov/research/umls/rxnorm", 13 | "code": "582620", 14 | "display": "Nizatidine 15 MG/ML Oral Solution [Axid]" 15 | } 16 | ], 17 | "text": "Nizatidine 15 MG/ML Oral Solution [Axid]" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fwoa-utilities/javaHapiValidatorLambda/src/test/resources/testImplementationGuides-stu3/us-core/Practitioner-practitioner-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "Practitioner", 3 | "id": "practitioner-1", 4 | "meta": { "profile": ["http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitioner"] }, 5 | "text": { 6 | "status": "generated", 7 | "div": "

Generated Narrative with Details

id: practitioner-1

meta:

identifier: 9941339108, 25456

name: Ronald Bone

address: 1003 Healthcare Drive Amherst MA 01002 (HOME)

" 8 | }, 9 | "identifier": [ 10 | { "system": "http://hl7.org.fhir/sid/us-npi", "value": "9941339108" }, 11 | { "system": "http://www.acme.org/practitioners", "value": "25456" } 12 | ], 13 | "name": [{ "family": "Bone", "given": ["Ronald"], "prefix": ["Dr"] }], 14 | "address": [ 15 | { 16 | "use": "home", 17 | "line": ["1003 Healthcare Drive"], 18 | "city": "Amherst", 19 | "state": "MA", 20 | "postalCode": "01002" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /fwoa-utilities/javaHapiValidatorLambda/src/test/resources/testImplementationGuides-stu3/us-core/Practitioner-practitioner-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "Practitioner", 3 | "id": "practitioner-2", 4 | "meta": { "profile": ["http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitioner"] }, 5 | "text": { 6 | "status": "generated", 7 | "div": "

Generated Narrative with Details

id: practitioner-2

meta:

identifier: 1245319599, 456789

name: Fielding Kathy

address: 1080 FIRST COLONIAL RD Virginia Beach VA 21454-2406 (WORK)

" 8 | }, 9 | "identifier": [ 10 | { "system": "http://hl7.org.fhir/sid/us-npi", "value": "1245319599" }, 11 | { "system": "http://www.acme.org/practitioners", "value": "456789" } 12 | ], 13 | "name": [{ "family": "Kathy", "given": ["Fielding"], "prefix": ["Dr"] }], 14 | "address": [ 15 | { 16 | "use": "work", 17 | "line": ["1080 FIRST COLONIAL RD"], 18 | "city": "Virginia Beach", 19 | "state": "VA", 20 | "postalCode": "21454-2406" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /fwoa-utilities/javaHapiValidatorLambda/src/test/resources/testImplementationGuides-stu3/us-core/ValueSet-us-core-cvx.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "ValueSet", 3 | "id": "us-core-cvx", 4 | "text": { 5 | "status": "generated", 6 | "div": "

Vaccine Administered Value Set (CVX)

This identifies the vaccine substance administered - CVX codes

\n

This value set includes codes from the following code systems:

  • Include all codes defined in http://hl7.org/fhir/sid/cvx
" 7 | }, 8 | "url": "http://hl7.org/fhir/us/core/ValueSet/us-core-cvx", 9 | "identifier": [{ "system": "urn:ietf:rfc:3986", "value": "urn:oid:2.16.840.1.113883.3.88.12.80.22" }], 10 | "version": "2.0.0", 11 | "name": "Vaccine Administered Value Set (CVX)", 12 | "status": "active", 13 | "date": "2016-08-10T00:00:00+10:00", 14 | "publisher": "HL7 US Realm Steering Committee", 15 | "contact": [{ "telecom": [{ "system": "other", "value": "http://hl7.org/fhir" }] }], 16 | "description": "This identifies the vaccine substance administered - CVX codes", 17 | "jurisdiction": [ 18 | { "coding": [{ "system": "urn:iso:std:iso:3166", "code": "US", "display": "United States of America" }] } 19 | ], 20 | "compose": { "include": [{ "system": "http://hl7.org/fhir/sid/cvx" }] } 21 | } 22 | -------------------------------------------------------------------------------- /fwoa-utilities/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | export { FhirWorksAppRegistry } from './fhirWorksAppRegistry'; 7 | export { getTestCondition, getMedicationRequest } from './testData'; 8 | -------------------------------------------------------------------------------- /fwoa-utilities/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/tsconfig", 3 | "extends": "./node_modules/@rushstack/heft-node-rig/profiles/default/tsconfig-base.json", 4 | "compilerOptions": { 5 | "types": ["heft-jest", "node"], 6 | "target": "es2019", // Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. 7 | "module": "commonjs", // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 8 | "strict": true, // // Enable all strict type-checking options. 9 | "esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 10 | "forceConsistentCasingInFileNames": true, // Disallow inconsistently-cased references to the same file. 11 | "outDir": "lib", 12 | "declaration": true, 13 | "sourceMap": true, 14 | "resolveJsonModule": true, 15 | "baseUrl": "." 16 | }, 17 | "include": ["src/**/*"] 18 | } 19 | -------------------------------------------------------------------------------- /imgs/awscliterminal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/imgs/awscliterminal.jpg -------------------------------------------------------------------------------- /imgs/awscloudshell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/imgs/awscloudshell.jpg -------------------------------------------------------------------------------- /imgs/chooseloggroups.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/imgs/chooseloggroups.jpg -------------------------------------------------------------------------------- /imgs/createbucket.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/imgs/createbucket.jpg -------------------------------------------------------------------------------- /imgs/monitorexporttasks.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/imgs/monitorexporttasks.jpg -------------------------------------------------------------------------------- /imgs/searchlogsbytimerange.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/imgs/searchlogsbytimerange.jpg -------------------------------------------------------------------------------- /imgs/selectloggroup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/imgs/selectloggroup.jpg -------------------------------------------------------------------------------- /imgs/successfullycreatedexporttask.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/imgs/successfullycreatedexporttask.jpg -------------------------------------------------------------------------------- /imgs/verifyexportins3bucket.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/imgs/verifyexportins3bucket.jpg -------------------------------------------------------------------------------- /solutions/deployment/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | -------------------------------------------------------------------------------- /solutions/deployment/.eslintignore: -------------------------------------------------------------------------------- 1 | auditLogMover/ 2 | cdk.out/ 3 | .eslintrc.js 4 | node_modules 5 | lib 6 | temp 7 | bin 8 | bulkExport 9 | scripts -------------------------------------------------------------------------------- /solutions/deployment/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | // This is a workaround for https://github.com/eslint/eslint/issues/3458 7 | require('@rushstack/eslint-config/patch/modern-module-resolution'); 8 | 9 | module.exports = { 10 | extends: ['@aws/eslint-config-fwoa-eslint-custom'], 11 | parserOptions: { tsconfigRootDir: __dirname }, 12 | overrides: [ 13 | { 14 | files: ['*.ts'], 15 | rules: { 16 | '@typescript-eslint/no-explicit-any': 'off', 17 | '@typescript-eslint/explicit-member-accessibility': 'off', 18 | 'security/detect-object-injection': 'off', 19 | '@typescript-eslint/explicit-function-return-type': 'off', 20 | '@rushstack/typedef-var': 'off', 21 | 'import/namespace': 'off' 22 | } 23 | } 24 | ] 25 | }; 26 | -------------------------------------------------------------------------------- /solutions/deployment/.npmignore: -------------------------------------------------------------------------------- 1 | *.ts 2 | !*.d.ts 3 | 4 | # CDK asset staging directory 5 | .cdk.staging 6 | cdk.out 7 | -------------------------------------------------------------------------------- /solutions/deployment/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | 3 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact opensource-codeofconduct@amazon.com with any additional questions or comments. 4 | -------------------------------------------------------------------------------- /solutions/deployment/bin/cdk-infra.test.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from 'aws-cdk-lib'; 2 | import { Template } from 'aws-cdk-lib/assertions'; 3 | import FhirWorksStack from '../lib/cdk-infra-stack'; 4 | 5 | test('Resources created', () => { 6 | const app = new cdk.App(); 7 | // WHEN 8 | const stack = new FhirWorksStack(app, 'MyTestStack'); 9 | // THEN 10 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 11 | const template = Template.fromStack(stack); 12 | 13 | // template.hasResourceProperties('AWS::SQS::Queue', { 14 | // VisibilityTimeout: 300 15 | // }); 16 | }); 17 | -------------------------------------------------------------------------------- /solutions/deployment/bulkExport/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { 7 | startExportJobHandler, 8 | stopExportJobHandler, 9 | getJobStatusHandler, 10 | updateStatusStatusHandler 11 | } from '@aws/fhir-works-on-aws-persistence-ddb'; 12 | 13 | exports.startExportJobHandler = startExportJobHandler; 14 | exports.stopExportJobHandler = stopExportJobHandler; 15 | exports.getJobStatusHandler = getJobStatusHandler; 16 | exports.updateStatusStatusHandler = updateStatusStatusHandler; 17 | -------------------------------------------------------------------------------- /solutions/deployment/bulkExport/schema/transitiveReferenceParams.json: -------------------------------------------------------------------------------- 1 | { 2 | "CareTeam": { 3 | "participant.member": "Practitioner", 4 | "managingOrganization": "Organization" 5 | }, 6 | "Patient": { 7 | "managingOrganization": "Organization" 8 | }, 9 | "DiagnosticReport": { 10 | "performer": "Organization" 11 | }, 12 | "Encounter": { 13 | "location.location": "Location" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /solutions/deployment/cdk-nag-deny-list.yaml: -------------------------------------------------------------------------------- 1 | RulesToSuppress: 2 | - id: W28 3 | reason: Resource found with an explicit name, this disallows updates that require replacement of this resource 4 | - id: W76 5 | reason: SPCM for IAM policy document is higher than 25 6 | - id: W89 7 | reason: We do not deploy Lambda functions inside a VPC, but we have guide for customers who would like to 8 | - id: W11 9 | reason: All resources with IAM Policy with a wildcard require access from many resources 10 | - id: W12 11 | reason: glueJobRelatedLambdaRole requires access frommany resources 12 | - id: W59 13 | reason: SMART on FHIR utilizes a third-party IdP for authorization 14 | -------------------------------------------------------------------------------- /solutions/deployment/compiledImplementationGuides/gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/solutions/deployment/compiledImplementationGuides/gitkeep -------------------------------------------------------------------------------- /solutions/deployment/config/jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rushstack/heft-node-rig/profiles/default/config/jest.config.json", 3 | "collectCoverage": true, 4 | "coverageThreshold": { 5 | "global": { 6 | "branches": 70, 7 | "functions": 70, 8 | "lines": 70, 9 | "statements": 70 10 | } 11 | }, 12 | "coveragePathIgnorePatterns": [ 13 | "/src/index.ts", 14 | "/src/integration-tests/*", 15 | "src/ddbToEsLambda/index.ts", 16 | "src/updateSearchMappings/index.ts", 17 | "src/subscriptions/reaperLambda/index.ts", 18 | "src/subscriptions/matcherLambda/index.ts", 19 | "src/subscriptions/restHookLambda/index.ts", 20 | 21 | // TODO: these files were not tested previously, tests should be added for coverage 22 | "src/RBACRules.ts", 23 | "src/config.ts", 24 | "src/subscriptions/allowList.ts", 25 | "src/implementationGuides/loadCompiledIGs.ts", 26 | "src/subscriptions/reaperLambda/subscriptionReaper.ts" 27 | ], 28 | "testPathIgnorePatterns": ["/node_modules/", "/integration-tests/"], 29 | "coverageReporters": ["json-summary", "json", "lcov", "text"] 30 | } 31 | -------------------------------------------------------------------------------- /solutions/deployment/config/rig.json: -------------------------------------------------------------------------------- 1 | // The "rig.json" file directs tools to look for their config files in an external package. 2 | // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package 3 | { 4 | "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", 5 | 6 | /** 7 | * (Required) The name of the rig package to inherit from. 8 | * It should be an NPM package name with the "-rig" suffix. 9 | */ 10 | "rigPackageName": "@rushstack/heft-node-rig" 11 | 12 | /** 13 | * (Optional) Selects a config profile from the rig package. The name must consist of 14 | * lowercase alphanumeric words separated by hyphens, for example "sample-profile". 15 | * If omitted, then the "default" profile will be used." 16 | */ 17 | // "rigProfile": "your-profile-name" 18 | } 19 | -------------------------------------------------------------------------------- /solutions/deployment/postman/Fhir_Dev_Env.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "FHIR Dev", 3 | "values": [ 4 | { 5 | "enabled": true, 6 | "key": "API_URL", 7 | "value": "", 8 | "type": "text" 9 | }, 10 | { 11 | "enabled": true, 12 | "key": "API_KEY", 13 | "value": "", 14 | "type": "text" 15 | }, 16 | { 17 | "enabled": true, 18 | "key": "COGNITO_TOKEN", 19 | "value": "", 20 | "type": "text" 21 | } 22 | ], 23 | "_postman_variable_scope": "environment", 24 | "_postman_exported_using": "Postman/4.10.3" 25 | } 26 | -------------------------------------------------------------------------------- /solutions/deployment/postman/Fhir_Local_Env.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "FHIR Local", 3 | "values": [ 4 | { 5 | "enabled": true, 6 | "key": "API_URL", 7 | "value": "localhost:3000", 8 | "type": "text" 9 | }, 10 | { 11 | "enabled": true, 12 | "key": "API_KEY", 13 | "value": "", 14 | "type": "text" 15 | } 16 | ], 17 | "_postman_variable_scope": "environment", 18 | "_postman_exported_using": "Postman/4.10.3" 19 | } 20 | -------------------------------------------------------------------------------- /solutions/deployment/postman/Fhir_Prod_Env.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "FHIR Prod", 3 | "values": [ 4 | { 5 | "enabled": true, 6 | "key": "API_URL", 7 | "value": "", 8 | "type": "text" 9 | }, 10 | { 11 | "enabled": true, 12 | "key": "API_KEY", 13 | "value": "", 14 | "type": "text" 15 | }, 16 | { 17 | "enabled": true, 18 | "key": "COGNITO_TOKEN", 19 | "value": "", 20 | "type": "text" 21 | } 22 | ], 23 | "_postman_variable_scope": "environment", 24 | "_postman_exported_using": "Postman/4.10.3" 25 | } 26 | -------------------------------------------------------------------------------- /solutions/deployment/resources/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/solutions/deployment/resources/architecture.png -------------------------------------------------------------------------------- /solutions/deployment/resources/billableperiod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/solutions/deployment/resources/billableperiod.png -------------------------------------------------------------------------------- /solutions/deployment/resources/kibanaurl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/solutions/deployment/resources/kibanaurl.png -------------------------------------------------------------------------------- /solutions/deployment/resources/opensearchservice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/solutions/deployment/resources/opensearchservice.png -------------------------------------------------------------------------------- /solutions/deployment/resources/postman_body_request_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/solutions/deployment/resources/postman_body_request_settings.png -------------------------------------------------------------------------------- /solutions/deployment/scripts/build_lambda.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const fse = require('fs-extra'); 3 | const path = require('path'); 4 | 5 | // expected usage: `node build_lambda.js ` 6 | // for use with NodeJsFunction command hooks to add files to Lambda functions, 7 | // so will usually be the inputDir and outputDir variables, respectively 8 | const inputDir = process.argv[2]; 9 | const outputDir = process.argv[3]; 10 | const fileToMove = process.argv[4]; 11 | const isDirectory = process.argv.length > 5 ? true : false; 12 | 13 | function ensureDirectoryExistence(filePath) { 14 | const dirname = path.dirname(filePath); 15 | if (fs.existsSync(dirname)) { 16 | return true; 17 | } 18 | fs.mkdirSync(dirname, { recursive: true }); 19 | } 20 | 21 | if (isDirectory) { 22 | fse.copySync(inputDir, outputDir); 23 | } else { 24 | ensureDirectoryExistence(`${outputDir}/${fileToMove}`); 25 | fs.copyFileSync(`${inputDir}/${fileToMove}`, `${outputDir}/${fileToMove}`); 26 | } 27 | -------------------------------------------------------------------------------- /solutions/deployment/scripts/iam_policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": [ 7 | "cloudwatch:*", 8 | "dynamodb:*", 9 | "events:*", 10 | "iam:*", 11 | "lambda:*", 12 | "logs:*", 13 | "s3:*", 14 | "xray:PutTelemetryRecords", 15 | "xray:PutTraceSegments", 16 | "tag:GetResources", 17 | "logs:*", 18 | "cognito-identity:*", 19 | "cognito-idp:*", 20 | "cognito-sync:*", 21 | "es:*", 22 | "cloudformation:*", 23 | "kms:*", 24 | "states:*", 25 | "backup:*", 26 | "backup-storage:MountCapsule", 27 | "sns:*" 28 | ], 29 | "Resource": "*" 30 | }, 31 | { 32 | "Effect": "Allow", 33 | "Action": ["apigateway:*"], 34 | "Resource": "arn:aws:apigateway:*::/*" 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /solutions/deployment/scripts/init-auth.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | SPDX-License-Identifier: Apache-2.0 4 | """ 5 | import boto3 6 | import sys 7 | import json 8 | 9 | client = boto3.client('cognito-idp', region_name=sys.argv[2]) 10 | ''' 11 | python3 init-auth.py 12 | example run: 13 | python3 init-auth.py 12pgvi3gsl32qp9h8lg130arr0 us-west-2 example_user example_password 14 | ''' 15 | response = client.initiate_auth( 16 | AuthFlow='USER_PASSWORD_AUTH', 17 | AuthParameters={ 18 | 'USERNAME': sys.argv[3], 19 | 'PASSWORD': sys.argv[4] 20 | }, 21 | 22 | ClientId=sys.argv[1] 23 | ) 24 | 25 | id_token = response['AuthenticationResult']['IdToken'] 26 | print(id_token) 27 | -------------------------------------------------------------------------------- /solutions/deployment/src/RBACRules.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { RBACConfig } from '@aws/fhir-works-on-aws-authz-rbac'; 7 | 8 | export const financialResources: string[] = [ 9 | 'Coverage', 10 | 'CoverageEligibilityRequest', 11 | 'CoverageEligibilityResponse', 12 | 'EnrollmentRequest', 13 | 'EnrollmentResponse', 14 | 'Claim', 15 | 'ClaimResponse', 16 | 'Invoice', 17 | 'PaymentNotice', 18 | 'PaymentReconciliation', 19 | 'Account', 20 | 'ChargeItem', 21 | 'ChargeItemDefinition', 22 | 'Contract', 23 | 'ExplanationOfBenefit', 24 | 'InsurancePlan' 25 | ]; 26 | 27 | const RBACRules = (baseResources: string[]): RBACConfig => { 28 | return { 29 | version: 1.0, 30 | groupRules: { 31 | practitioner: { 32 | operations: ['create', 'read', 'update', 'delete', 'vread', 'search-type', 'transaction'], 33 | resources: baseResources 34 | }, 35 | 'non-practitioner': { 36 | operations: ['read', 'vread', 'search-type'], 37 | resources: financialResources 38 | }, 39 | auditor: { 40 | operations: ['read', 'vread', 'search-type'], 41 | resources: ['Patient'] 42 | } 43 | } 44 | }; 45 | }; 46 | 47 | export default RBACRules; 48 | -------------------------------------------------------------------------------- /solutions/deployment/src/ddbToEsLambda/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { handleDdbToEsEvent } from '@aws/fhir-works-on-aws-persistence-ddb'; 7 | 8 | exports.handler = async (event: any) => { 9 | await handleDdbToEsEvent(event); 10 | }; 11 | -------------------------------------------------------------------------------- /solutions/deployment/src/implementationGuides/loadCompiledIGs.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { existsSync, PathLike, readFileSync } from 'fs'; 7 | import path from 'path'; 8 | 9 | export const COMPILED_IGS_DIRECTORY = 'compiledImplementationGuides'; 10 | 11 | /** 12 | * Loads the compiled Implementation Guides for a given 'fhir-works-at-aws' module. 13 | * By default they are located on a file named "compiledImplementationGuides/.json" 14 | * @param moduleName - module name 15 | * @param implementationGuidesPath - allows to override the path to the compiled Implementation Guides directory 16 | */ 17 | // eslint-disable-next-line import/prefer-default-export 18 | export const loadImplementationGuides = ( 19 | moduleName: string, 20 | implementationGuidesPath?: PathLike 21 | ): any[] | undefined => { 22 | const resolvedImplementationGuidesPath = 23 | implementationGuidesPath ?? path.join(__dirname, COMPILED_IGS_DIRECTORY); 24 | 25 | const igsPath = path.join(resolvedImplementationGuidesPath.toString(), `${moduleName}.json`); 26 | 27 | /* eslint-disable security/detect-non-literal-fs-filename */ 28 | if (existsSync(igsPath)) { 29 | return JSON.parse(readFileSync(igsPath, { encoding: 'utf8' })); 30 | } 31 | 32 | /* eslint-enable security/detect-non-literal-fs-filename */ 33 | return undefined; 34 | }; 35 | -------------------------------------------------------------------------------- /solutions/deployment/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { generateServerlessRouter } from '@aws/fhir-works-on-aws-routing'; 7 | import serverless from 'serverless-http'; 8 | import { getFhirConfig, genericResources } from './config'; 9 | 10 | export const ensureAsyncInit = async (initPromise: Promise): Promise => { 11 | try { 12 | await initPromise; 13 | } catch (e) { 14 | console.error('Async initialization failed', e); 15 | // Explicitly exit the process so that next invocation re-runs the init code. 16 | // This prevents Lambda containers from caching a rejected init promise 17 | process.exit(1); 18 | } 19 | }; 20 | 21 | async function asyncServerless() { 22 | return serverless(generateServerlessRouter(await getFhirConfig(), genericResources), { 23 | request(request: any, event: any) { 24 | request.user = event.user; 25 | } 26 | }); 27 | } 28 | 29 | const serverlessHandler: Promise = asyncServerless(); 30 | 31 | export const handler = async (event: any = {}, context: any = {}): Promise => { 32 | await ensureAsyncInit(serverlessHandler); 33 | return (await serverlessHandler)(event, context); 34 | }; 35 | -------------------------------------------------------------------------------- /solutions/deployment/src/integration-tests/infrastructure/allowList-integTests.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | /** 8 | * This file will overwrite the default src/subscriptions/allowList.ts when deploying to integ test environments. 9 | */ 10 | 11 | import { SubscriptionEndpoint } from '@aws/fhir-works-on-aws-routing/lib/router/validation/subscriptionValidator'; 12 | 13 | const getAllowListedSubscriptionEndpoints = async (): Promise => { 14 | // any API Gateway endpoint 15 | const testEndpoint: RegExp = /^https:\/\/\w+\.execute-api\.[\w-]+\.amazonaws.com\/\w+/; 16 | return [ 17 | { 18 | tenantId: 'tenant1', 19 | endpoint: testEndpoint 20 | }, 21 | { 22 | tenantId: 'tenant2', 23 | endpoint: testEndpoint 24 | }, 25 | { 26 | endpoint: testEndpoint 27 | } 28 | ]; 29 | }; 30 | 31 | export default getAllowListedSubscriptionEndpoints; 32 | -------------------------------------------------------------------------------- /solutions/deployment/src/integration-tests/infrastructure/subscriptions-endpoint/README.md: -------------------------------------------------------------------------------- 1 | # FHIR Subscriptions Test Endpoint 2 | 3 | This small SAM app creates an API (APIGW + Lambda) that can be used as an endpoint in FHIR Subscriptions integration tests. 4 | 5 | The Lambda function replies successfully to all requests and records the notification message in DynamoDB. 6 | The integration tests can query DynamoDB to verify that notifications were received. 7 | 8 | To build and deploy your application for the first time, run the following in your shell: 9 | 10 | ```bash 11 | sam build 12 | sam deploy --guided 13 | ``` 14 | 15 | Use the outputs of the CFN stack as values for the `SUBSCRIPTIONS_NOTIFICATIONS_TABLE` and `SUBSCRIPTIONS_ENDPOINT` environment variables when running the integration tests 16 | -------------------------------------------------------------------------------- /solutions/deployment/src/integration-tests/infrastructure/subscriptions-endpoint/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fhir-subscriptions-test-endpoint", 3 | "version": "1.0.0", 4 | "description": "Simple endpoint used for FHIR Subscriptions integ tests", 5 | "homepage": "https://github.com/aws-solutions/fhir-works-on-aws", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/aws-solutions/fhir-works-on-aws.git" 9 | }, 10 | "author": { 11 | "name": "Amazon Web Services", 12 | "email": "fhir-works-on-aws-dev@amazon.com", 13 | "url": "https://aws.amazon.com/solutions" 14 | }, 15 | "main": "app.js", 16 | "license": "Apache-2.0", 17 | "dependencies": {}, 18 | "scripts": {}, 19 | "devDependencies": {} 20 | } 21 | -------------------------------------------------------------------------------- /solutions/deployment/src/subscriptions/matcherLambda/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | import { DynamoDb, DynamoDbDataService } from '@aws/fhir-works-on-aws-persistence-ddb'; 8 | import { StreamSubscriptionMatcher } from '@aws/fhir-works-on-aws-search-es'; 9 | 10 | import { fhirVersion } from '../../config'; 11 | import { loadImplementationGuides } from '../../implementationGuides/loadCompiledIGs'; 12 | 13 | const dynamoDbDataService = new DynamoDbDataService(DynamoDb); 14 | 15 | const topicArn = process.env.SUBSCRIPTIONS_TOPIC as string; 16 | 17 | const streamSubscriptionMatcher = new StreamSubscriptionMatcher(dynamoDbDataService, topicArn, { 18 | fhirVersion, 19 | compiledImplementationGuides: loadImplementationGuides('fhir-works-on-aws-search-es') 20 | }); 21 | 22 | exports.handler = async (event: any) => { 23 | await streamSubscriptionMatcher.match(event); 24 | }; 25 | -------------------------------------------------------------------------------- /solutions/deployment/src/subscriptions/reaperLambda/index.ts: -------------------------------------------------------------------------------- 1 | import { DynamoDbDataService, DynamoDb } from '@aws/fhir-works-on-aws-persistence-ddb'; 2 | import reaperHandler from './subscriptionReaper'; 3 | 4 | const enableMultitenancy = process.env.ENABLE_MULTI_TENANCY === 'true'; 5 | const dbServiceWithTenancy = new DynamoDbDataService(DynamoDb, false, { 6 | enableMultiTenancy: enableMultitenancy 7 | }); 8 | const dbService = new DynamoDbDataService(DynamoDb); 9 | 10 | /** 11 | * Custom lambda handler that handles deleting expired subscriptions. 12 | */ 13 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 14 | exports.handler = async (event: any) => { 15 | return reaperHandler(dbService, dbServiceWithTenancy, enableMultitenancy); 16 | }; 17 | -------------------------------------------------------------------------------- /solutions/deployment/src/subscriptions/restHookLambda/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | import { AllowListInfo, getAllowListInfo } from './allowListUtil'; 8 | import RestHookHandler from './restHook'; 9 | 10 | const enableMultitenancy = process.env.ENABLE_MULTI_TENANCY === 'true'; 11 | 12 | const allowListPromise: Promise<{ [key: string]: AllowListInfo }> = getAllowListInfo({ 13 | enableMultitenancy 14 | }); 15 | 16 | const restHookHandler = new RestHookHandler({ enableMultitenancy }); 17 | 18 | exports.handler = async (event: any) => { 19 | return restHookHandler.sendRestHookNotification(event, allowListPromise); 20 | }; 21 | -------------------------------------------------------------------------------- /solutions/deployment/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/tsconfig", 3 | "extends": "./node_modules/@rushstack/heft-node-rig/profiles/default/tsconfig-base.json", 4 | "compilerOptions": { 5 | "types": ["heft-jest", "node"], 6 | "lib": ["es2019"], 7 | "target": "ES2020", 8 | "moduleResolution": "node", 9 | "strict": true, 10 | "esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 11 | "alwaysStrict": true, 12 | "outDir": "dist", 13 | "sourceMap": true, 14 | "resolveJsonModule": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "baseUrl": "." 17 | }, 18 | "include": ["src/**/*"] 19 | } 20 | -------------------------------------------------------------------------------- /solutions/documentation/bulkExport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/solutions/documentation/bulkExport.png -------------------------------------------------------------------------------- /solutions/smart-deployment/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | -------------------------------------------------------------------------------- /solutions/smart-deployment/.eslintignore: -------------------------------------------------------------------------------- 1 | auditLogMover/ 2 | cdk.out/ 3 | .eslintrc.js 4 | node_modules 5 | lib 6 | temp 7 | bin 8 | bulkExport 9 | scripts -------------------------------------------------------------------------------- /solutions/smart-deployment/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This is a workaround for https://github.com/eslint/eslint/issues/3458 2 | require('@rushstack/eslint-config/patch/modern-module-resolution'); 3 | 4 | module.exports = { 5 | extends: ['@aws/eslint-config-fwoa-eslint-custom'], 6 | parserOptions: { tsconfigRootDir: __dirname }, 7 | overrides: [ 8 | { 9 | files: ['*.ts'], 10 | rules: { 11 | '@typescript-eslint/no-explicit-any': 'off', 12 | '@typescript-eslint/explicit-member-accessibility': 'off', 13 | 'security/detect-object-injection': 'off', 14 | '@typescript-eslint/explicit-function-return-type': 'off', 15 | '@rushstack/typedef-var': 'off', 16 | 'import/namespace': 'off', 17 | 'tsdoc/syntax': 'off', 18 | 'import/no-named-as-default-member': 'off' 19 | } 20 | }, 21 | { 22 | files: [ 23 | 'src/implementationGuides/loadCompiledIGs.ts', 24 | 'src/implementationGuides/IGCompiler.test.ts', 25 | 'src/implementationGuides/IGCompiler.ts' 26 | ], 27 | rules: { 'security/detect-non-literal-fs-filename': 'off' } 28 | } 29 | ] 30 | }; 31 | -------------------------------------------------------------------------------- /solutions/smart-deployment/.npmrc: -------------------------------------------------------------------------------- 1 | scripts-prepend-node-path=auto 2 | auto-install-peers=true 3 | -------------------------------------------------------------------------------- /solutions/smart-deployment/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | 3 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact opensource-codeofconduct@amazon.com with any additional questions or comments. 4 | -------------------------------------------------------------------------------- /solutions/smart-deployment/bulkExport/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { 7 | startExportJobHandler, 8 | stopExportJobHandler, 9 | getJobStatusHandler, 10 | updateStatusStatusHandler 11 | } from '@aws/fhir-works-on-aws-persistence-ddb'; 12 | 13 | exports.startExportJobHandler = startExportJobHandler; 14 | exports.stopExportJobHandler = stopExportJobHandler; 15 | exports.getJobStatusHandler = getJobStatusHandler; 16 | exports.updateStatusStatusHandler = updateStatusStatusHandler; 17 | -------------------------------------------------------------------------------- /solutions/smart-deployment/bulkExport/schema/transitiveReferenceParams.json: -------------------------------------------------------------------------------- 1 | { 2 | "CareTeam": { 3 | "participant.member": "Practitioner", 4 | "managingOrganization": "Organization" 5 | }, 6 | "Patient": { 7 | "managingOrganization": "Organization" 8 | }, 9 | "DiagnosticReport": { 10 | "performer": "Organization" 11 | }, 12 | "Encounter": { 13 | "location.location": "Location" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /solutions/smart-deployment/cdk-nag-deny-list.yaml: -------------------------------------------------------------------------------- 1 | RulesToSuppress: 2 | - id: W28 3 | reason: Resource found with an explicit name, this disallows updates that require replacement of this resource 4 | - id: W76 5 | reason: SPCM for IAM policy document is higher than 25 6 | - id: W89 7 | reason: We do not deploy Lambda functions inside a VPC, but we have guide for customers who would like to 8 | - id: W11 9 | reason: All resources with IAM Policy with a wildcard require access from many resources 10 | - id: W12 11 | reason: glueJobRelatedLambdaRole requires access frommany resources 12 | - id: W59 13 | reason: SMART on FHIR utilizes a third-party IdP for authorization 14 | -------------------------------------------------------------------------------- /solutions/smart-deployment/compiledImplementationGuides/gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/solutions/smart-deployment/compiledImplementationGuides/gitkeep -------------------------------------------------------------------------------- /solutions/smart-deployment/config/jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rushstack/heft-node-rig/profiles/default/config/jest.config.json", 3 | "collectCoverage": true, 4 | "coverageThreshold": { 5 | "global": { 6 | "branches": 55, 7 | "functions": 70, 8 | "lines": 70, 9 | "statements": 70 10 | } 11 | }, 12 | "coveragePathIgnorePatterns": [ 13 | "/src/integration-tests", 14 | "/src/ddbToEsLambda/index.ts", 15 | "/src/subscriptions/matcherLambda/index.ts", 16 | "/src/subscriptions/reaperLambda/index.ts", 17 | "/src/subscriptions/restHookLambda/index.ts", 18 | "/src/index.ts", 19 | "/src/updateSearchMappings/index.ts", 20 | "/src/authZConfig.ts", 21 | "/src/config.ts", 22 | "/src/subscriptions/allowList.ts" 23 | ], 24 | "testPathIgnorePatterns": ["/node_modules/", "/src/integration-tests"], 25 | "coverageReporters": ["json-summary", "json", "lcov", "text"], 26 | "testRunner": "jest-circus/runner" 27 | } 28 | -------------------------------------------------------------------------------- /solutions/smart-deployment/config/rig.json: -------------------------------------------------------------------------------- 1 | // The "rig.json" file directs tools to look for their config files in an external package. 2 | // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package 3 | { 4 | "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", 5 | 6 | /** 7 | * (Required) The name of the rig package to inherit from. 8 | * It should be an NPM package name with the "-rig" suffix. 9 | */ 10 | "rigPackageName": "@rushstack/heft-node-rig" 11 | 12 | /** 13 | * (Optional) Selects a config profile from the rig package. The name must consist of 14 | * lowercase alphanumeric words separated by hyphens, for example "sample-profile". 15 | * If omitted, then the "default" profile will be used." 16 | */ 17 | // "rigProfile": "your-profile-name" 18 | } 19 | -------------------------------------------------------------------------------- /solutions/smart-deployment/postman/FHIR_SMART.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "22577031-c00e-4aae-946f-3d4f9da5f089", 3 | "name": "FHIR SMART", 4 | "values": [ 5 | { 6 | "key": "API_URL", 7 | "value": "https://fake.execute-api.us-west-2.amazonaws.com/stage", 8 | "enabled": true 9 | }, 10 | { 11 | "key": "API_KEY", 12 | "value": "key", 13 | "enabled": true 14 | }, 15 | { 16 | "key": "OAUTH_URL", 17 | "value": "https://fake.execute-api.us-east-1.amazonaws.com/sandbox", 18 | "enabled": true 19 | }, 20 | { 21 | "key": "OAUTH_CLIENT_ID", 22 | "value": "client_id", 23 | "enabled": true 24 | }, 25 | { 26 | "key": "OAUTH_CLIENT_SECRET", 27 | "value": "secret", 28 | "enabled": true 29 | } 30 | ], 31 | "_postman_variable_scope": "environment", 32 | "_postman_exported_at": "2021-01-29T21:18:57.387Z", 33 | "_postman_exported_using": "Postman/7.36.1" 34 | } 35 | -------------------------------------------------------------------------------- /solutions/smart-deployment/resources/architecture-smart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/solutions/smart-deployment/resources/architecture-smart.png -------------------------------------------------------------------------------- /solutions/smart-deployment/resources/oauth2-fwoa-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/solutions/smart-deployment/resources/oauth2-fwoa-flow.png -------------------------------------------------------------------------------- /solutions/smart-deployment/resources/postman_body_request_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-solutions/fhir-works-on-aws/315d94793d4d0369b192d5da9e520222dffb373c/solutions/smart-deployment/resources/postman_body_request_settings.png -------------------------------------------------------------------------------- /solutions/smart-deployment/scripts/build_lambda.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const fse = require('fs-extra'); 3 | const path = require('path'); 4 | 5 | // expected usage: `node build_lambda.js ` 6 | // for use with NodeJsFunction command hooks to add files to Lambda functions, 7 | // so will usually be the inputDir and outputDir variables, respectively 8 | const inputDir = process.argv[2]; 9 | const outputDir = process.argv[3]; 10 | const fileToMove = process.argv[4]; 11 | const isDirectory = process.argv.length > 5 ? true : false; 12 | 13 | function ensureDirectoryExistence(filePath) { 14 | const dirname = path.dirname(filePath); 15 | if (fs.existsSync(dirname)) { 16 | return true; 17 | } 18 | fs.mkdirSync(dirname, { recursive: true }); 19 | } 20 | 21 | if (isDirectory) { 22 | fse.copySync(inputDir, outputDir); 23 | } else { 24 | ensureDirectoryExistence(`${outputDir}/${fileToMove}`); 25 | fs.copyFileSync(`${inputDir}/${fileToMove}`, `${outputDir}/${fileToMove}`); 26 | } 27 | -------------------------------------------------------------------------------- /solutions/smart-deployment/scripts/iam_policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": [ 7 | "cloudwatch:*", 8 | "dynamodb:*", 9 | "events:*", 10 | "iam:*", 11 | "lambda:*", 12 | "logs:*", 13 | "s3:*", 14 | "xray:PutTelemetryRecords", 15 | "xray:PutTraceSegments", 16 | "tag:GetResources", 17 | "logs:*", 18 | "cognito-identity:*", 19 | "cognito-idp:*", 20 | "cognito-sync:*", 21 | "es:*", 22 | "cloudformation:*", 23 | "kms:*", 24 | "states:*", 25 | "backup:*", 26 | "backup-storage:MountCapsule", 27 | "sns:*" 28 | ], 29 | "Resource": "*" 30 | }, 31 | { 32 | "Effect": "Allow", 33 | "Action": ["apigateway:*"], 34 | "Resource": "arn:aws:apigateway:*::/*" 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /solutions/smart-deployment/src/ddbToEsLambda/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { handleDdbToEsEvent } from '@aws/fhir-works-on-aws-persistence-ddb'; 7 | 8 | exports.handler = async (event: any) => { 9 | await handleDdbToEsEvent(event); 10 | }; 11 | -------------------------------------------------------------------------------- /solutions/smart-deployment/src/implementationGuides/loadCompiledIGs.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { existsSync, PathLike, readFileSync } from 'fs'; 7 | import path from 'path'; 8 | 9 | export const COMPILED_IGS_DIRECTORY = 'compiledImplementationGuides'; 10 | 11 | /** 12 | * Loads the compiled Implementation Guides for a given 'fhir-works-at-aws' module. 13 | * By default they are located on a file named "compiledImplementationGuides/.json" 14 | * @param moduleName 15 | * @param implementationGuidesPath - allows to override the path to the compiled Implementation Guides directory 16 | */ 17 | // eslint-disable-next-line import/prefer-default-export 18 | export const loadImplementationGuides = ( 19 | moduleName: string, 20 | implementationGuidesPath?: PathLike 21 | ): any[] | undefined => { 22 | const resolvedImplementationGuidesPath = 23 | implementationGuidesPath ?? path.join(__dirname, COMPILED_IGS_DIRECTORY); 24 | 25 | const igsPath = path.join(resolvedImplementationGuidesPath.toString(), `${moduleName}.json`); 26 | 27 | if (existsSync(igsPath)) { 28 | return JSON.parse(readFileSync(igsPath, { encoding: 'utf8' })); 29 | } 30 | return undefined; 31 | }; 32 | -------------------------------------------------------------------------------- /solutions/smart-deployment/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | import { generateServerlessRouter } from '@aws/fhir-works-on-aws-routing'; 6 | import serverless from 'serverless-http'; 7 | import { getFhirConfig, genericResources } from './config'; 8 | 9 | export const ensureAsyncInit = async (initPromise: Promise): Promise => { 10 | try { 11 | await initPromise; 12 | } catch (e) { 13 | console.error('Async initialization failed', e); 14 | // Explicitly exit the process so that next invocation re-runs the init code. 15 | // This prevents Lambda containers from caching a rejected init promise 16 | process.exit(1); 17 | } 18 | }; 19 | 20 | async function asyncServerless() { 21 | return serverless(generateServerlessRouter(await getFhirConfig(), genericResources), { 22 | request(request: any, event: any) { 23 | request.user = event.user; 24 | } 25 | }); 26 | } 27 | 28 | const serverlessHandler: Promise = asyncServerless(); 29 | 30 | export const handler = async (event: any = {}, context: any = {}): Promise => { 31 | await ensureAsyncInit(serverlessHandler); 32 | return (await serverlessHandler)(event, context); 33 | }; 34 | -------------------------------------------------------------------------------- /solutions/smart-deployment/src/integration-tests/infrastructure/allowList-integTests.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | /** 8 | * This file will overwrite the default src/subscriptions/allowList.ts when deploying to integ test environments. 9 | */ 10 | 11 | import { SubscriptionEndpoint } from '@aws/fhir-works-on-aws-routing/lib/router/validation/subscriptionValidator'; 12 | 13 | const getAllowListedSubscriptionEndpoints = async (): Promise => { 14 | // any API Gateway endpoint 15 | const testEndpoint: RegExp = /^https:\/\/\w+\.execute-api\.[\w-]+\.amazonaws.com\/\w+/; 16 | return [ 17 | { 18 | tenantId: 'tenant1', 19 | endpoint: testEndpoint 20 | }, 21 | { 22 | tenantId: 'tenant2', 23 | endpoint: testEndpoint 24 | }, 25 | { 26 | endpoint: testEndpoint 27 | } 28 | ]; 29 | }; 30 | 31 | export default getAllowListedSubscriptionEndpoints; 32 | -------------------------------------------------------------------------------- /solutions/smart-deployment/src/integration-tests/infrastructure/subscriptions-endpoint/README.md: -------------------------------------------------------------------------------- 1 | # FHIR Subscriptions Test Endpoint 2 | 3 | This small SAM app creates an API (APIGW + Lambda) that can be used as an endpoint in FHIR Subscriptions integration tests. 4 | 5 | The Lambda function replies successfully to all requests and records the notification message in DynamoDB. 6 | The integration tests can query DynamoDB to verify that notifications were received. 7 | 8 | To build and deploy your application for the first time, run the following in your shell: 9 | 10 | ```bash 11 | sam build 12 | sam deploy --guided 13 | ``` 14 | 15 | Use the outputs of the CFN stack as values for the `SUBSCRIPTIONS_NOTIFICATIONS_TABLE` and `SUBSCRIPTIONS_ENDPOINT` environment variables when running the integration tests 16 | -------------------------------------------------------------------------------- /solutions/smart-deployment/src/integration-tests/infrastructure/subscriptions-endpoint/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fhir-subscriptions-test-endpoint", 3 | "version": "1.0.0", 4 | "description": "Simple endpoint used for FHIR Subscriptions integ tests", 5 | "main": "app.js", 6 | "license": "Apache-2.0", 7 | "dependencies": {}, 8 | "scripts": {}, 9 | "devDependencies": {} 10 | } 11 | -------------------------------------------------------------------------------- /solutions/smart-deployment/src/subscriptions/matcherLambda/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | import { DynamoDb, DynamoDbDataService } from '@aws/fhir-works-on-aws-persistence-ddb'; 8 | import { StreamSubscriptionMatcher } from '@aws/fhir-works-on-aws-search-es'; 9 | 10 | import { fhirVersion } from '../../config'; 11 | import { loadImplementationGuides } from '../../implementationGuides/loadCompiledIGs'; 12 | 13 | const dynamoDbDataService = new DynamoDbDataService(DynamoDb); 14 | 15 | const topicArn = process.env.SUBSCRIPTIONS_TOPIC as string; 16 | 17 | const streamSubscriptionMatcher = new StreamSubscriptionMatcher(dynamoDbDataService, topicArn, { 18 | fhirVersion, 19 | compiledImplementationGuides: loadImplementationGuides('fhir-works-on-aws-search-es') 20 | }); 21 | 22 | exports.handler = async (event: any) => { 23 | await streamSubscriptionMatcher.match(event); 24 | }; 25 | -------------------------------------------------------------------------------- /solutions/smart-deployment/src/subscriptions/reaperLambda/index.ts: -------------------------------------------------------------------------------- 1 | import { DynamoDbDataService, DynamoDb } from '@aws/fhir-works-on-aws-persistence-ddb'; 2 | import reaperHandler from './subscriptionReaper'; 3 | 4 | const enableMultitenancy = process.env.ENABLE_MULTI_TENANCY === 'true'; 5 | const dbServiceWithTenancy = new DynamoDbDataService(DynamoDb, false, { 6 | enableMultiTenancy: enableMultitenancy 7 | }); 8 | const dbService = new DynamoDbDataService(DynamoDb); 9 | 10 | /** 11 | * Custom lambda handler that handles deleting expired subscriptions. 12 | */ 13 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 14 | exports.handler = async (event: any) => { 15 | return reaperHandler(dbService, dbServiceWithTenancy, enableMultitenancy); 16 | }; 17 | -------------------------------------------------------------------------------- /solutions/smart-deployment/src/subscriptions/restHookLambda/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | */ 6 | 7 | import { AllowListInfo, getAllowListInfo } from './allowListUtil'; 8 | import RestHookHandler from './restHook'; 9 | 10 | const enableMultitenancy = process.env.ENABLE_MULTI_TENANCY === 'true'; 11 | 12 | const allowListPromise: Promise<{ [key: string]: AllowListInfo }> = getAllowListInfo({ 13 | enableMultitenancy 14 | }); 15 | 16 | const restHookHandler = new RestHookHandler({ enableMultitenancy }); 17 | 18 | exports.handler = async (event: any) => { 19 | return restHookHandler.sendRestHookNotification(event, allowListPromise); 20 | }; 21 | -------------------------------------------------------------------------------- /solutions/smart-deployment/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/tsconfig", 3 | "extends": "./node_modules/@rushstack/heft-node-rig/profiles/default/tsconfig-base.json", 4 | "compilerOptions": { 5 | "types": ["heft-jest", "node"], 6 | "lib": ["es2019"], 7 | "target": "es2020", // Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. 8 | "moduleResolution": "node", 9 | "strict": true, // // Enable all strict type-checking options. 10 | "esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 11 | "forceConsistentCasingInFileNames": true, // Disallow inconsistently-cased references to the same file. 12 | "outDir": "dist", 13 | "sourceMap": true, 14 | "resolveJsonModule": true, 15 | "baseUrl": "." 16 | }, 17 | "include": ["src/**/*", "src/integration-tests/**/*"] 18 | } 19 | --------------------------------------------------------------------------------