diff --git a/frontend/src/lib/conduit/factory.ts b/frontend/src/lib/conduit/factory.ts index e69de29b..f4b9894e 100644 --- a/frontend/src/lib/conduit/factory.ts +++ b/frontend/src/lib/conduit/factory.ts @@ -0,0 +1,40 @@ +import {SourceType} from '../models/database/types'; +import {Source} from '../models/database/source'; +import {IClient} from './interface'; +import {AetnaClient} from './fhir/aetna_client'; +import {BlueButtonClient} from './fhir/bluebutton_client'; +import {CareEvolutionClient} from './fhir/careevolution_client'; +import {CernerClient} from './fhir/cerner_client'; +import {AthenaClient} from './fhir/athena_client'; +import {CignaClient} from './fhir/cigna_client'; +import {EpicClient} from './fhir/epic_client'; +import {HealthITClient} from './fhir/healthit_client'; +import {LogicaClient} from './fhir/logica_client'; + +export function NewClient(sourceType: SourceType, source: Source): IClient { + + switch(sourceType) { + case SourceType.Aetna: + return new AetnaClient(source) + case SourceType.Athena: + return new AthenaClient(source) + case SourceType.BlueButtonMedicare: + return new BlueButtonClient(source) + case SourceType.CareEvolution: + return new CareEvolutionClient(source) + case SourceType.Cerner: + return new CernerClient(source) + case SourceType.Cigna: + return new CignaClient(source) + case SourceType.Epic: + return new EpicClient(source) + case SourceType.HealthIT: + return new HealthITClient(source) + case SourceType.Logica: + return new LogicaClient(source) + // case SourceType.Manual: + // return new ManualClient(source) + default: + throw new Error(`Unknown Source Type: ${sourceType}`) + } +} diff --git a/frontend/src/lib/conduit/fhir/aetna_client.ts b/frontend/src/lib/conduit/fhir/aetna_client.ts new file mode 100644 index 00000000..cc3c57cd --- /dev/null +++ b/frontend/src/lib/conduit/fhir/aetna_client.ts @@ -0,0 +1,23 @@ +import {IClient} from '../interface'; +import {FHIR401Client} from './base/fhir401_r4_client'; +import {Source} from '../../models/database/source'; +import {IDatabaseRepository} from '../../database/interface'; + +export class AetnaClient extends FHIR401Client implements IClient { + constructor(source: Source) { + super(source); + } + + /** + * Aetna overrides the SyncAll function because Patient-everything operation uses a non-standard endpoint + * @param db + * @constructor + */ + async SyncAll(db: IDatabaseRepository): Promise { + const bundle = await this.GetResourceBundlePaginated("Patient") + + const wrappedResourceModels = await this.ProcessBundle(bundle) + //todo, create the resources in dependency order + return await db.CreateResources(wrappedResourceModels) + } +} diff --git a/frontend/src/lib/conduit/fhir/athena_client.ts b/frontend/src/lib/conduit/fhir/athena_client.ts new file mode 100644 index 00000000..05493fff --- /dev/null +++ b/frontend/src/lib/conduit/fhir/athena_client.ts @@ -0,0 +1,42 @@ +import {IClient} from '../interface'; +import {FHIR401Client} from './base/fhir401_r4_client'; +import {Source} from '../../models/database/source'; +import {IDatabaseRepository} from '../../database/interface'; + +export class AthenaClient extends FHIR401Client implements IClient { + constructor(source: Source) { + super(source); + } + + /** + * Athena overrides the SyncAll function because Patient-everything operation is not available. + * @param db + * @constructor + */ + async SyncAll(db: IDatabaseRepository): Promise { + const supportedResources: string[] = [ + "AllergyIntolerance", + //"Binary", + "CarePlan", + "CareTeam", + "Condition", + "Device", + "DiagnosticReport", + "DocumentReference", + "Encounter", + "Goal", + "Immunization", + //"Location", + //"Medication", + //"MedicationRequest", + "Observation", + //"Organization", + //"Patient", + //"Practitioner", + "Procedure", + //"Provenance", + ] + + return this.SyncAllByResourceName(db, supportedResources) + } +} diff --git a/frontend/src/lib/conduit/fhir/base/fhir401_r4_client.ts b/frontend/src/lib/conduit/fhir/base/fhir401_r4_client.ts index 37c1b537..d6779c9a 100644 --- a/frontend/src/lib/conduit/fhir/base/fhir401_r4_client.ts +++ b/frontend/src/lib/conduit/fhir/base/fhir401_r4_client.ts @@ -56,10 +56,7 @@ export class FHIR401Client extends BaseClient implements IClient { try { let bundle = await this.GetResourceBundlePaginated(`${resourceType}?patient=${this.source.patient}`) let wrappedResourceModels = await this.ProcessBundle(bundle) - - for(let apiModel of wrappedResourceModels){ - await db.CreateResource(apiModel) - } + await db.CreateResources(wrappedResourceModels) } catch (e) { console.error(`An error occurred while processing ${resourceType} bundle ${this.source.patient}`) @@ -132,17 +129,13 @@ export class FHIR401Client extends BaseClient implements IClient { }) } - ///////////////////////////////////////////////////////////////////////////// - // Private methods - ///////////////////////////////////////////////////////////////////////////// - /** * Retrieve a resource bundle. While "next" link is present in response, continue to request urls and append BundleEntries * @param relativeResourcePath * @constructor * @private */ - private async GetResourceBundlePaginated(relativeResourcePath: string): Promise { + protected async GetResourceBundlePaginated(relativeResourcePath: string): Promise { // https://www.hl7.org/fhir/patient-operation-everything.html const bundle = await this.GetRequest(relativeResourcePath) as IResourceBundleRaw @@ -181,4 +174,8 @@ export class FHIR401Client extends BaseClient implements IClient { return bundle } + + ///////////////////////////////////////////////////////////////////////////// + // Private methods + ///////////////////////////////////////////////////////////////////////////// } diff --git a/frontend/src/lib/conduit/fhir/bluebutton_client.ts b/frontend/src/lib/conduit/fhir/bluebutton_client.ts new file mode 100644 index 00000000..cb8569cd --- /dev/null +++ b/frontend/src/lib/conduit/fhir/bluebutton_client.ts @@ -0,0 +1,24 @@ +import {IClient} from '../interface'; +import {FHIR401Client} from './base/fhir401_r4_client'; +import {Source} from '../../models/database/source'; +import {IDatabaseRepository} from '../../database/interface'; + +export class BlueButtonClient extends FHIR401Client implements IClient { + constructor(source: Source) { + super(source); + } + + /** + * BlueButton overrides the SyncAll function because Patient-everything operation is not available. + * @param db + * @constructor + */ + async SyncAll(db: IDatabaseRepository): Promise { + const supportedResources: string[] = [ + "ExplanationOfBenefit", + "Coverage", + ] + + return this.SyncAllByResourceName(db, supportedResources) + } +} diff --git a/frontend/src/lib/conduit/fhir/careevolution_client.ts b/frontend/src/lib/conduit/fhir/careevolution_client.ts new file mode 100644 index 00000000..fd9b714b --- /dev/null +++ b/frontend/src/lib/conduit/fhir/careevolution_client.ts @@ -0,0 +1,12 @@ +import {IClient} from '../interface'; +import {FHIR401Client} from './base/fhir401_r4_client'; +import {Source} from '../../models/database/source'; + +export class CareEvolutionClient extends FHIR401Client implements IClient { + constructor(source: Source) { + super(source); + //CareEvolution API requires the following Accept header for every request + this.headers["Accept"] = "application/json+fhir" + } + +} diff --git a/frontend/src/lib/conduit/fhir/cerner_client.ts b/frontend/src/lib/conduit/fhir/cerner_client.ts new file mode 100644 index 00000000..487cfad6 --- /dev/null +++ b/frontend/src/lib/conduit/fhir/cerner_client.ts @@ -0,0 +1,47 @@ +import {IClient} from '../interface'; +import {FHIR401Client} from './base/fhir401_r4_client'; +import {Source} from '../../models/database/source'; +import {IDatabaseRepository} from '../../database/interface'; + +export class CernerClient extends FHIR401Client implements IClient { + constructor(source: Source) { + super(source); + //Cerner API requires the following Accept header for every request + this.headers["Accept"] = "application/json+fhir" + } + + /** + * Cerner overrides the SyncAll function because Patient-everything operation is not available. + * @param db + * @constructor + */ + async SyncAll(db: IDatabaseRepository): Promise { + const supportedResources: string[] = [ + "AllergyIntolerance", + "CarePlan", + "CareTeam", + "Condition", + "Consent", + "Device", + "Encounter", + "FamilyMemberHistory", + "Goal", + "Immunization", + "InsurancePlan", + "MedicationRequest", + "NutritionOrder", + "Observation", + "Person", + "Procedure", + "Provenance", + "Questionnaire", + "QuestionnaireResponse", + "RelatedPerson", + "Schedule", + "ServiceRequest", + "Slot", + ] + + return this.SyncAllByResourceName(db, supportedResources) + } +} diff --git a/frontend/src/lib/conduit/fhir/cigna_client.ts b/frontend/src/lib/conduit/fhir/cigna_client.ts new file mode 100644 index 00000000..7e2428bb --- /dev/null +++ b/frontend/src/lib/conduit/fhir/cigna_client.ts @@ -0,0 +1,10 @@ +import {IClient} from '../interface'; +import {FHIR401Client} from './base/fhir401_r4_client'; +import {Source} from '../../models/database/source'; + +export class CignaClient extends FHIR401Client implements IClient { + constructor(source: Source) { + super(source); + } + +} diff --git a/frontend/src/lib/conduit/fhir/epic_client.ts b/frontend/src/lib/conduit/fhir/epic_client.ts new file mode 100644 index 00000000..ae98863a --- /dev/null +++ b/frontend/src/lib/conduit/fhir/epic_client.ts @@ -0,0 +1,47 @@ +import {IClient} from '../interface'; +import {FHIR401Client} from './base/fhir401_r4_client'; +import {Source} from '../../models/database/source'; +import {IDatabaseRepository} from '../../database/interface'; + +export class EpicClient extends FHIR401Client implements IClient { + constructor(source: Source) { + super(source); + //Epic API requires the following Accept header for every request + this.headers["Accept"] = "application/json+fhir" + } + + /** + * Epic overrides the SyncAll function because Patient-everything operation is not available. + * @param db + * @constructor + */ + async SyncAll(db: IDatabaseRepository): Promise { + const supportedResources: string[] = [ + "AllergyIntolerance", + "CarePlan", + "CareTeam", + "Condition", + "Consent", + "Device", + "Encounter", + "FamilyMemberHistory", + "Goal", + "Immunization", + "InsurancePlan", + "MedicationRequest", + "NutritionOrder", + "Observation", + "Person", + "Procedure", + "Provenance", + "Questionnaire", + "QuestionnaireResponse", + "RelatedPerson", + "Schedule", + "ServiceRequest", + "Slot", + ] + + return this.SyncAllByResourceName(db, supportedResources) + } +} diff --git a/frontend/src/lib/conduit/fhir/healthit_client.ts b/frontend/src/lib/conduit/fhir/healthit_client.ts new file mode 100644 index 00000000..dddd52bb --- /dev/null +++ b/frontend/src/lib/conduit/fhir/healthit_client.ts @@ -0,0 +1,47 @@ +import {IClient} from '../interface'; +import {FHIR401Client} from './base/fhir401_r4_client'; +import {Source} from '../../models/database/source'; +import {IDatabaseRepository} from '../../database/interface'; + +export class HealthITClient extends FHIR401Client implements IClient { + constructor(source: Source) { + super(source); + //HealthIT API requires the following Accept header for every request + this.headers["Accept"] = "application/json+fhir" + } + + /** + * HealthIT overrides the SyncAll function because Patient-everything operation is not available. + * @param db + * @constructor + */ + async SyncAll(db: IDatabaseRepository): Promise { + const supportedResources: string[] = [ + "AllergyIntolerance", + "CarePlan", + "CareTeam", + "Condition", + "Consent", + "Device", + "Encounter", + "FamilyMemberHistory", + "Goal", + "Immunization", + "InsurancePlan", + "MedicationRequest", + "NutritionOrder", + "Observation", + "Person", + "Procedure", + "Provenance", + "Questionnaire", + "QuestionnaireResponse", + "RelatedPerson", + "Schedule", + "ServiceRequest", + "Slot", + ] + + return this.SyncAllByResourceName(db, supportedResources) + } +} diff --git a/frontend/src/lib/conduit/fhir/logica_client.ts b/frontend/src/lib/conduit/fhir/logica_client.ts new file mode 100644 index 00000000..1ab3ac6b --- /dev/null +++ b/frontend/src/lib/conduit/fhir/logica_client.ts @@ -0,0 +1,10 @@ +import {IClient} from '../interface'; +import {FHIR401Client} from './base/fhir401_r4_client'; +import {Source} from '../../models/database/source'; +import {IDatabaseRepository} from '../../database/interface'; + +export class LogicaClient extends FHIR401Client implements IClient { + constructor(source: Source) { + super(source); + } +}