oro-sdk 5.3.4 → 5.3.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- {"version":3,"file":"oro-sdk.cjs.production.min.js","sources":["../src/helpers/client.ts","../src/models/error.ts","../src/helpers/workflow.ts","../src/helpers/consult.ts","../src/helpers/patient-registration.ts","../src/helpers/vault-grants.ts","../src/helpers/prescription-refill.ts","../src/sdk-revision/client.ts","../src/client.ts","../src/services/external/clinia.ts","../src/index.ts"],"sourcesContent":["import {\n PopulatedWorkflowData,\n MetadataCategory,\n SelectedAnswersData,\n} from 'oro-sdk-apis'\nimport { PersonalInformations } from '../models/client'\n\nconst personalMetaToPrefix = {\n [MetadataCategory.Personal]: 'you',\n [MetadataCategory.ChildPersonal]: 'child',\n [MetadataCategory.OtherPersonal]: 'other',\n}\n\n/**\n * This function extract PersonalInformations from data input object coming from workflow\n * @param data extracted from WorkflowData\n * @returns PersonalInformations of a patient\n */\nexport function identificationToPersonalInformations(\n data: any,\n category:\n | MetadataCategory.Personal\n | MetadataCategory.ChildPersonal\n | MetadataCategory.OtherPersonal\n): PersonalInformations {\n const prefix = personalMetaToPrefix[category]\n\n return {\n birthday: data[`${prefix}Birthday`],\n firstname: data[`${prefix}Firstname`],\n gender: data[`${prefix}Gender`],\n name: data[`${prefix}Name`],\n phone: data[`${prefix}Phone`],\n zip: data[`${prefix}Zip`],\n hid: data[`${prefix}HID`] ?? data[`${prefix}ID`], // This is done for backward compatibility (historically youID was used)\n pharmacy: data[`${prefix}Pharmacy`],\n address: data[`${prefix}Address`],\n }\n}\n\nexport function toActualObject(data: PopulatedWorkflowData) {\n const ret: any = {}\n\n Object.entries(data.fields).forEach(([key, field]) => {\n ret[key] = field.displayedAnswer ? field.displayedAnswer : field.answer\n })\n\n return ret\n}\n\n/**\n * This function update a PopulatedWorkflowData with PersonalInformations\n * @param infos the personal informations\n * @param data the PopulatedWorkflowData\n * @returns an updated PopulatedWorkflowData\n */\nexport function updatePersonalIntoPopulatedWorkflowData(\n infos: PersonalInformations,\n data: PopulatedWorkflowData,\n category:\n | MetadataCategory.Personal\n | MetadataCategory.ChildPersonal\n | MetadataCategory.OtherPersonal\n) {\n const prefix = personalMetaToPrefix[category]\n\n const ret = JSON.parse(JSON.stringify(data)) // deep copy PopulatedWorkflowData\n\n if (infos.birthday && ret.fields[`${prefix}Birthday`])\n ret.fields[`${prefix}Birthday`].answer = infos.birthday\n if (infos.firstname && ret.fields[`${prefix}Firstname`])\n ret.fields[`${prefix}Firstname`].answer = infos.firstname\n if (infos.gender && ret.fields[`${prefix}Gender`])\n ret.fields[`${prefix}Gender`].answer = infos.gender\n if (infos.name && ret.fields[`${prefix}Name`])\n ret.fields[`${prefix}Name`].answer = infos.name\n if (infos.phone && ret.fields[`${prefix}Phone`])\n ret.fields[`${prefix}Phone`].answer = infos.phone\n if (infos.zip && ret.fields[`${prefix}Zip`])\n ret.fields[`${prefix}Zip`].answer = infos.zip\n if (infos.hid) {\n if (ret.fields[`${prefix}HID`]) {\n ret.fields[`${prefix}HID`].answer = infos.hid\n } else if (ret.fields[`${prefix}ID`]) {\n // This is done for backward compatibility (historically youID was used)\n ret.fields[`${prefix}ID`].answer = infos.hid\n } else {\n // If does not exist create it\n ret.fields[`${prefix}HID`] = { kind: 'text', answer: infos.hid }\n }\n }\n\n return ret\n}\n\n/**\n * This function extract an ISO 3166-1 alpha-2 country and subdivision code from data input object coming from workflow\n * @param answers answers from the WorkflowData\n * @returns an ISO 3166 alpha-2 code or undefined\n */\nexport function extractISOLocalityForConsult(\n answers?: SelectedAnswersData\n): string | undefined {\n if (!answers) {\n return undefined\n }\n\n const arrAnswersWithLocality = answers\n .flatMap((currentAnswerPage) => {\n const arrCountryFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Country') !== -1\n )\n .flat()\n const arrProvinceFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Province') !== -1\n )\n .flat()\n const arrConsultLocalFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Locality') !== -1\n )\n .flat()\n //returning the actual selected values, skipping if their IDs are more complex than a string\n return [\n ...arrCountryFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ...arrProvinceFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ...arrConsultLocalFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ]\n })\n .filter((item) => item !== undefined)\n\n const arrSelectedLocality = arrAnswersWithLocality.filter(\n (currentSelectedLocality) =>\n currentSelectedLocality.startsWith('isoLocalityConsult')\n )\n if (!arrSelectedLocality || arrSelectedLocality.length === 0) {\n console.log('no locality found in ' + arrSelectedLocality)\n return undefined\n }\n //to allow enforcing of an order, we will allow the following pattern in the isoLocalityConsult field name\n // isoLocalityConsult-QC-CA and isoLocalityConsult_1-QC-CA\n // or generally: isoLocalityConsult-<isoValue> or isoLocalityConsult_<priority>-<isoValue>\n const allowedLocalityPatterns = /isoLocalityConsult(?:_(?<indexPriority>\\d*))?-(?<isoValue>[a-zA-Z0-9]{2}-[a-zA-Z0-9]{1,3})/\n const finalLocality = arrSelectedLocality.reduce<string | undefined>(\n (finalLocality, currentSelectedLocality) => {\n const extractedSelected = allowedLocalityPatterns.exec(\n currentSelectedLocality\n )\n const [, indexSelectedPriority, isoSelectedValue] =\n extractedSelected ?? []\n if (!finalLocality) {\n return isoSelectedValue\n }\n\n const extractedFinal = allowedLocalityPatterns.exec(finalLocality)\n const [, indexFinalPriority, isoFinalValue] = extractedFinal ?? []\n //we only keep the old value if there's priority used\n // and the new value is of lower priority\n if (\n !indexSelectedPriority ||\n (indexFinalPriority &&\n indexFinalPriority > indexSelectedPriority)\n ) {\n return isoFinalValue\n }\n\n return isoSelectedValue\n },\n undefined\n )\n\n console.log('Picking locality ' + finalLocality)\n return finalLocality\n}\n\nconst sessionPrivateKeyPrefix = 'sess-pkey'\nexport function sessionStorePrivateKeyName(id: string): string {\n return sessionPrivateKeyPrefix + id\n}\n","export class IncompleteAuthentication extends Error { }\nexport class MissingGrant extends Error { }\nexport class MissingGrantFilter extends Error { }\nexport class MissingLockbox extends Error { }\nexport class MissingLockboxOwner extends Error { }\nexport class AssociatedLockboxNotFound extends Error { }\nexport class WorkflowAnswersMissingError extends Error { }\n","import { getMany } from 'idb-keyval'\nimport { WorkflowAnswersMissingError } from '../models'\nimport {\n MetadataCategory,\n PopulatedWorkflowData,\n PopulatedWorkflowField,\n QuestionData,\n SelectedAnswerData,\n SelectedAnswersData,\n WorkflowData,\n WorkflowPageData,\n WorkflowUploadedImage,\n} from 'oro-sdk-apis'\n\nexport async function filterTriggeredAnsweredWithKind(\n workflowData: WorkflowData,\n kind:\n | 'text'\n | 'text-area'\n | 'text-select-group'\n | 'date'\n | 'number'\n | 'images'\n | 'images-alias'\n | 'body-parts'\n | 'pharmacy-picker'\n | 'online-pharmacy-picker'\n | 'hair-selector-women'\n | 'hair-selector-men'\n | 'hair-loss-stage'\n | 'hair-loss-frontal'\n): Promise<SelectedAnswerData[]> {\n if (!workflowData.selectedAnswers) throw WorkflowAnswersMissingError\n // Flattens the list of answered questions\n let flattenedAnswers = flattenSelectedAnswers(workflowData.selectedAnswers)\n // Generates a list of applicable questions\n let triggeredQuestionsWithKind = Object.fromEntries(\n workflowData.pages\n .map((a) => {\n return Object.entries(a.questions).filter(\n ([_, question]) => isTriggered(question.triggers || [], flattenedAnswers) && question.kind === kind\n )\n })\n .flat()\n )\n\n const samePageAnswers = workflowData.selectedAnswers.reduce((prev, cur) => {\n return { ...prev, ...cur }\n }, {})\n\n const res = Object.keys(triggeredQuestionsWithKind).map((questionFieldName) => {\n return samePageAnswers[questionFieldName]\n })\n\n return res\n}\n\n/**\n * Filters and Populates the `selectedAnswers` from the workflow by\n * Cross-referencing the `MetaCategory` of the answer's respective question\n * Populates the fields labels and values that are of radio, dropdown and checkbox types\n *\n * @param workflowData\n * @param category\n * @returns An array of record key, value pairs\n */\nexport async function getWorkflowDataByCategory(\n workflowData: WorkflowData,\n category: MetadataCategory\n): Promise<PopulatedWorkflowData> {\n if (!workflowData.selectedAnswers) throw WorkflowAnswersMissingError\n\n // Flattens the list of answered questions\n let flattenedAnswers = flattenSelectedAnswers(workflowData.selectedAnswers)\n // Generates a list of applicable questions\n let triggeredQuestions = Object.fromEntries(\n workflowData.pages\n .map((a) => {\n return Object.entries(a.questions).filter(([_, question]) =>\n isTriggered(question.triggers || [], flattenedAnswers)\n )\n })\n .flat()\n )\n\n const fields: Record<string, PopulatedWorkflowField> = {}\n\n // Generates the answers of the specified category and adds the appropriate values if any are missing\n return Promise.all(\n workflowData.selectedAnswers\n .map((e) => Object.entries(e))\n .flat()\n .filter(([k, v]) => triggeredQuestions[k] && triggeredQuestions[k]['metaCategory'] === category)\n .map(([k, v]) => {\n return populateWorkflowField(triggeredQuestions[k], v).then((populatedValue) => {\n fields[k] = populatedValue\n })\n })\n )\n .then(() => {\n const ret: PopulatedWorkflowData = {\n workflowCreatedAt: workflowData.createdAt,\n workflowId: workflowData.id,\n locale: workflowData.locale,\n fields,\n }\n return ret\n })\n .catch((err) => {\n console.error(`Error while extracting ${category} data from workflow`, err)\n throw err\n })\n}\n\nexport async function getImagesFromIndexDb(answer: SelectedAnswerData): Promise<WorkflowUploadedImage[]> {\n return await getMany<WorkflowUploadedImage>((answer as any[]).map((v) => v.id ?? v) as string[])\n}\n\n/**\n * (If applicable) Based on the question kind, and the answer type this function will add and replace the appropriate fields to the\n * field values if they are radio, dropdown and checkbox fields\n *\n *\n * @param question\n * @param answerValue\n * @returns\n */\nasync function populateWorkflowField(\n question: QuestionData,\n answerValue: SelectedAnswerData\n): Promise<PopulatedWorkflowField> {\n let answer: any\n let displayedAnswer: string | string[] | undefined = undefined\n switch (question.kind) {\n case 'text-select-group':\n if (question.answers) {\n displayedAnswer = `${answerValue[0]} ${question.answers[answerValue[1] as string].text}`\n }\n answer = answerValue\n break\n case 'radio':\n case 'radio-card':\n case 'select':\n if (question.answers) {\n displayedAnswer = question.answers[answerValue as string].text\n }\n\n answer = answerValue\n break\n case 'multiple':\n case 'checkbox-group':\n displayedAnswer = (answerValue as string[]).map((value) => {\n if (question.answers) {\n return question.answers[value].text\n }\n\n throw new WorkflowAnswersMissingError()\n })\n\n answer = answerValue\n break\n case 'images':\n answer = await getImagesFromIndexDb(answerValue).then((images) =>\n images.map((image) => {\n const { name, imageData } = image\n\n return { name, imageData }\n })\n )\n break\n default:\n answer = answerValue\n }\n\n return Promise.resolve({\n answer,\n displayedAnswer,\n kind: question.kind,\n })\n}\n\n/**\n * Determine if a question is triggered by some answers\n *\n * We use the following logical combinations of rules:\n *\n * #### Single string\n *\n * ```\n * // Required: rule1\n * rules: rule1\n * ```\n *\n * #### Array of strings (AND is applied between statements):\n *\n * ```\n * // Required: rule1 AND rule2\n * rules: [ rule1, rule2 ]\n * ```\n *\n * #### Array of arrays of strings (OR is applied between inner arrays. AND is applied between inner arrays statements)\n *\n * ```\n * // Required: rule1 OR rule2\n * rules: [\n * [ rule1 ],\n * [ rule2 ]\n * ]\n *\n * // Required: rule1 OR (rule2 AND rule3)\n * rules: [\n * [ rule1 ],\n * [ rule2, rule3 ]\n * ]\n *\n * // THIS IS FORBIDDEN\n * rules: [\n * rule1, // <-- THIS IS FORBIDDEN. Instead use [ rule1 ]\n * [ rule2, rule3 ]\n * ]\n * ```\n *\n * @param triggers the triggering rules\n * @param answers the answers to check againts triggering rules\n * @returns `true` if triggers are verified against ansers. Otherwise, returns `false`.\n * @throws an Error if triggers typing is wrong\n */\nexport function isTriggered(triggers: string[][] | string[] | string, answers: string[]): boolean {\n // is triggers contained in answers\n if (typeof triggers === 'string') {\n return answers.includes(triggers)\n }\n\n if (Array.isArray(triggers)) {\n // rule combination kind: rule1 OR (rule2 AND rule3)\n if (Array.isArray(triggers[0])) {\n return (triggers as string[][]).some((subSetTriggers) =>\n subSetTriggers.every((trigger) => answers.includes(trigger))\n )\n } else {\n // rule combination kind: rule1 AND rule2\n return (triggers as string[]).every((trigger) => answers.includes(trigger))\n }\n }\n\n throw Error('[isTriggered] triggers is not typed well')\n}\n\nexport function flattenSelectedAnswers(answers: SelectedAnswersData) {\n const linearAnswers: SelectedAnswerData[] = []\n\n for (const answer of answers) {\n linearAnswers.push(...Object.values(answer))\n }\n\n return linearAnswers.flat(1)\n}\n\n/**\n * This function helps you to get a valid workflow selectedAnswers structure\n * @param workflow the workflow data to use to initialize selectedAnswers\n * @param useDefault use workflow default values or not (this is used to avoid having unset values to appear in summaries)\n * @returns a valid selectedAnswers structure\n */\nexport function getInitialisedSelectedAnswers(workflow: WorkflowData, useDefault: boolean = true) {\n return workflow.pages.map((page) => {\n const ret: any = {}\n for (const [id, question] of Object.entries(page.questions)) {\n if (question.kind === 'body-parts') {\n ret[id] = useDefault ? [] : undefined\n } else {\n ret[id] = useDefault && question.defaultValue ? question.defaultValue : undefined\n }\n }\n return ret\n })\n}\n\nexport function fillWorkflowFromPopulatedWorkflow(workflow: WorkflowData, populatedWorkflow: PopulatedWorkflowData) {\n const filledWorkflow = JSON.parse(JSON.stringify(workflow))\n\n if (!filledWorkflow.selectedAnswers) {\n filledWorkflow.selectedAnswers = getInitialisedSelectedAnswers(filledWorkflow, false)\n }\n\n filledWorkflow.pages.forEach((page: WorkflowPageData, pageIdx: number) => {\n const ret: any = {}\n for (const [id] of Object.entries(page.questions)) {\n if (populatedWorkflow.fields[id]) {\n if (filledWorkflow.selectedAnswers)\n filledWorkflow.selectedAnswers[pageIdx][id] = populatedWorkflow.fields[id].answer as\n | string\n | string[]\n }\n }\n })\n\n return filledWorkflow\n}\n","import { Consult, ConsultRequest } from 'oro-sdk-apis'\nimport { OroClient } from '..'\n\n/**\n * Creates a consultation if one has not been created and fails to be retrieved by the payment intent\n * @param consult\n * @param oroClient\n * @returns the consult Uuid\n */\nexport async function getOrCreatePatientConsultationUuid(\n consult: ConsultRequest,\n oroClient: OroClient\n): Promise<Consult> {\n let payment = await oroClient.practiceClient.practiceGetPayment(\n consult.uuidPractice,\n consult.idStripeInvoiceOrPaymentIntent\n )\n if (payment && payment.uuidConsult) {\n return oroClient.consultClient.getConsultByUUID(payment.uuidConsult).catch((err) => {\n console.error('Error while retrieving consult', err)\n throw err\n })\n } else {\n return await oroClient.consultClient.consultCreate(consult).catch((err) => {\n console.error('Error while creating consult', err)\n throw err\n })\n }\n}\n","import {\n Consult,\n ConsultationImageMeta,\n ConsultationMeta,\n ConsultRequest,\n DocumentType,\n IdentityResponse,\n IndexKey,\n MedicalMeta,\n MedicalStatus,\n MetadataCategory,\n PersonalMeta,\n PopulatedWorkflowData,\n Practitioner,\n PreferenceMeta,\n RawConsultationMeta,\n Term,\n Terms,\n Uuid,\n VaultIndex,\n WorkflowData,\n} from 'oro-sdk-apis'\nimport {\n filterTriggeredAnsweredWithKind,\n getImagesFromIndexDb,\n getWorkflowDataByCategory,\n identificationToPersonalInformations,\n OroClient,\n RegisterPatientOutput,\n toActualObject,\n} from '..'\nimport { getOrCreatePatientConsultationUuid } from './consult'\n\nconst MAX_RETRIES = 15\n\n/**\n * Completes a registration for a user retrying the complete flow a maximum of 15 times\n *\n * @description The order of importance when registering:\n * Creates a consultation if none exist\n * Retrieves or create's a lockbox if none exist\n * Grants the lockbox (if new) to all practitioners in the practice\n * Stores or fetches the patient data (without images)\n * Indexes the lockbox to the consult for all practitioners (done after inserting since index can be rebuilt from grants)\n * Stores the image data - done last since the majority of failure cases occur here\n * Creates the recovery payloads if they don't exist\n *\n * @param patientUuid\n * @param consultRequest\n * @param workflow\n * @param oroClient\n * @param masterKey\n * @param recoveryQA\n * @param indexSearch create search index for the consultation if true\n * @param onProgress callback that is called whenever a new step of patient registration is executed. Note: progress ranges from 0 to 1, and descriptionKey is a description of the progress as a key so the app would use it to translate the description\n * @returns the successful registration\n */\nexport async function registerPatient(\n patientUuid: Uuid,\n consultRequest: ConsultRequest,\n workflow: WorkflowData,\n oroClient: OroClient,\n masterKey?: Uuid,\n recoveryQA?: {\n recoverySecurityQuestions: string[]\n recoverySecurityAnswers: string[]\n },\n indexSearch: boolean = true,\n onProgress?: (\n progress: number,\n descriptionKey: string,\n extraInfo?: { storedImagesNum?: number; totalImagesNum?: number }\n ) => void\n): Promise<RegisterPatientOutput> {\n let consult: Consult | undefined = undefined\n let lockboxUuid: Uuid | undefined = undefined\n let practitionerAdmin: Uuid | undefined = undefined\n let retry = MAX_RETRIES\n let identity: IdentityResponse | undefined = undefined\n let errorsThrown: Error[] = []\n const stepsTotalNum = 9\n let currentStep: number\n\n for (; retry > 0; retry--) {\n try {\n currentStep = 0\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'retrieve_practitioners')\n\n // Wait a bit each retry (we also want the first one to wait)\n await new Promise((resolve) => setTimeout(resolve, 2000))\n\n // Retrieving practitioners\n if (!practitionerAdmin)\n practitionerAdmin = (await oroClient.practiceClient.practiceGetFromUuid(consultRequest.uuidPractice))\n .uuidAdmin\n\n let practitioners: Practitioner[] = await oroClient.practiceClient\n .practiceGetPractitioners(consultRequest.uuidPractice)\n .catch((err) => {\n console.log(`Error retrieving practitioners`, err)\n return []\n })\n\n // Creating consult\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'create_consult')\n\n if (!consult) {\n consult = await getOrCreatePatientConsultationUuid(consultRequest, oroClient)\n }\n\n // Creating lockbox\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'create_lockbox')\n\n if (!lockboxUuid) lockboxUuid = await getOrCreatePatientLockbox(oroClient)\n\n if (!identity) identity = await oroClient.guardClient.identityGet(patientUuid)\n\n await oroClient.grantLockbox(practitionerAdmin, lockboxUuid).catch((err) => {\n console.error(`Error while granting lockbox to practitioner admin ${practitionerAdmin}`, err)\n // if we cannot grant to the admin, then the registration will fail\n errorsThrown.push(err)\n })\n\n // Patient Grant to practice\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'grant_patient')\n\n let grantPromises = practitioners\n .filter((practitioner) => practitioner.uuid !== practitionerAdmin)\n .map(async (practitioner) => {\n return oroClient.grantLockbox(practitioner.uuid, lockboxUuid!).catch((err) => {\n console.error(`Error while granting lockbox to practitioner`, err)\n // Acceptable to continue as admin has already been granted, but we should still retry until the last retry remains\n if (retry <= 1) return\n errorsThrown.push(err)\n })\n })\n\n const consultIndex: VaultIndex = {\n [IndexKey.ConsultationLockbox]: [\n {\n grant: {\n lockboxUuid,\n lockboxOwnerUuid: patientUuid,\n },\n consultationId: consult.uuid,\n },\n ],\n }\n\n // the index will identify in which lockbox a consultation resides\n let consultIndexPromises = practitioners.map(async (practitioner) => {\n return oroClient.vaultIndexAdd(consultIndex, practitioner.uuid).catch((err) => {\n console.error(\n `[SDK: registration] Error while adding to the practitioner's index ${practitioner.uuid}`,\n err\n )\n // Acceptable to continue as the index can be rebuilt, but we should still retry until the last retry remains\n if (retry <= 1) return\n else errorsThrown.push(err)\n })\n })\n\n await storeImageAliases(\n consult.uuid,\n lockboxUuid,\n workflow,\n oroClient,\n onProgress\n ? {\n onProgress,\n currentStep,\n stepsTotalNum,\n }\n : undefined\n ).catch((err) => {\n console.error('[SDK: registration] Some errors happened during image upload', err)\n // Acceptable to continue as images can be requested during the consultation, but we should still retry until the last retry remains\n if (retry <= 1) return\n else errorsThrown.push(err)\n })\n ++currentStep\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'store_patient_data')\n\n await storePatientData(\n consult.uuid,\n consultRequest.isoLanguageRequired,\n lockboxUuid,\n workflow,\n oroClient\n ).catch((err) => {\n console.error('[SDK: registration] Some errors happened during patient data upload', err)\n errorsThrown.push(err)\n })\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'set_masterkey')\n\n if (masterKey && !identity?.recoveryMasterKey) {\n // generate and store recovery payload and updates the identity\n identity = await oroClient.updateMasterKey(patientUuid, masterKey, lockboxUuid).catch((err) => {\n console.error(`[SDK: registration] Error while updating master key`, err)\n /// it's acceptable to continue registration (return old identity)\n if (retry <= 1) return\n errorsThrown.push(err)\n return identity\n })\n } else {\n // we did not set the master key so we do not return it\n masterKey = undefined\n }\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'set_security_questions')\n\n if (recoveryQA && !identity?.recoverySecurityQuestions)\n // Patient security question recovery threshold is 2 answers and updates the identity\n identity = await oroClient\n .updateSecurityQuestions(\n patientUuid,\n recoveryQA.recoverySecurityQuestions,\n recoveryQA.recoverySecurityAnswers,\n 2\n )\n .catch((err) => {\n console.error(`[SDK: registration] Error while updating security questions`, err)\n /// it's acceptable to continue registration (return old identity)\n if (retry <= 1) return\n errorsThrown.push(err)\n return identity\n })\n\n await Promise.all([...grantPromises, ...consultIndexPromises])\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'search_indexing')\n\n if (indexSearch) {\n await buildConsultSearchIndex(consult, workflow, oroClient).catch((err) => {\n console.error(\n '[SDK: registration] personal information not found or another error occured during search indexing',\n err\n )\n if (retry <= 1) return // this statement is to avoid failing the registration due to the failure in search indexing the consult, this practically implements a soft retry\n errorsThrown.push(err)\n })\n }\n\n if (errorsThrown.length > 0) throw errorsThrown\n\n // Deem the consultation as ready\n await oroClient.consultClient.updateConsultByUUID(consult.uuid, {\n statusMedical: MedicalStatus.New,\n })\n\n // if we got through the complete flow, the registration succeeded\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'success')\n\n break\n } catch (err) {\n console.error(`[SDK] Error occured during registration: ${err}, retrying... Retries remaining: ${retry}`)\n errorsThrown = []\n continue\n }\n }\n\n if (retry <= 0) {\n console.error('[SDK] registration failed: MAX_RETRIES reached')\n throw 'RegistrationFailed'\n }\n\n console.log('Successfully Registered')\n await oroClient.cleanIndex()\n return {\n masterKey,\n consultationId: consult!.uuid,\n lockboxUuid: lockboxUuid!,\n }\n}\n\n/**\n * Creates a new lockbox for the patient if they do not have any, otherwise, use the first (and only one)\n * @param oroClient\n * @returns the lockbox Uuid\n */\nasync function getOrCreatePatientLockbox(oroClient: OroClient): Promise<Uuid> {\n let grants = await oroClient.getGrants()\n if (grants.length > 0) {\n console.log('The grant has already been created, skipping lockbox create step')\n return grants[0].lockboxUuid!\n } else {\n let lockboxResponse = await oroClient.vaultClient.lockboxCreate().catch((err) => {\n console.error('Error while creating lockbox', err)\n throw err\n })\n // Since the creation of a lockbox will change the scope of a user, we will force refresh the tokens\n let tokens = await oroClient.guardClient.authRefresh()\n await oroClient.guardClient.setTokens({ accessToken: tokens.accessToken, refreshToken: tokens.refreshToken })\n await oroClient.guardClient.whoAmI(true)\n\n return lockboxResponse.lockboxUuid\n }\n}\n\n/**\n * Store all patient related information into his/her lockbox\n * @param consultationId The consultation id\n * @param isoLanguage the prefered language of communication (ISO 639-3 https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes)\n * @param lockboxUuid the lockbox uuid to store data in\n * @param workflow the workflow used to extract informations\n * @param oroClient an oroClient instance\n * @returns\n */\nasync function storePatientData(\n consultationId: Uuid,\n isoLanguage: string,\n lockboxUuid: Uuid,\n workflow: WorkflowData,\n oroClient: OroClient\n): Promise<(Uuid | void)[]> {\n // Create and store registration data\n return Promise.all([\n // Storing Raw data first\n oroClient.getOrInsertJsonData<RawConsultationMeta>(\n lockboxUuid,\n workflow,\n {\n category: MetadataCategory.Raw,\n contentType: 'application/json',\n consultationId,\n },\n {}\n ),\n getWorkflowDataByCategory(workflow, MetadataCategory.Consultation).then((data) =>\n oroClient.getOrInsertJsonData<ConsultationMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationId, // TODO: deprecated. Will finally only be in privateMetadata\n },\n { consultationId },\n false,\n true // the only data that needs to include an email notification\n )\n ),\n getWorkflowDataByCategory(workflow, MetadataCategory.Medical).then((data) =>\n oroClient.getOrInsertJsonData<MedicalMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Medical,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId!],\n },\n {}\n )\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.Personal,\n oroClient\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.ChildPersonal,\n oroClient\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.OtherPersonal,\n oroClient\n ),\n oroClient.getOrInsertJsonData<PreferenceMeta>(\n lockboxUuid,\n { isoLanguage },\n {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n },\n {}\n ),\n ]).then((dataUuids) => dataUuids.flat())\n}\n\nasync function storeImageAliases(\n consultationId: Uuid,\n lockboxUuid: Uuid,\n workflow: WorkflowData,\n oroClient: OroClient,\n progress?: {\n currentStep: number\n stepsTotalNum: number\n onProgress: (\n progress: number,\n descriptionKey: string,\n extraInfo?: { storedImagesNum?: number; totalImagesNum?: number }\n ) => void\n }\n): Promise<(Uuid | void)[]> {\n const images = await getImagesFromIndexDb((await filterTriggeredAnsweredWithKind(workflow, 'images-alias')).flat())\n\n const nonNullImages = images.filter((img) => !!img)\n\n if (images.length !== nonNullImages.length) {\n console.error('[SDK] Some images have not been found, they have been skipped.')\n }\n\n let storedImagesNum = 0\n let totalImagesNum = nonNullImages.length\n if (progress)\n progress.onProgress(progress.currentStep / progress.stepsTotalNum, 'store_images', {\n storedImagesNum,\n totalImagesNum,\n })\n\n let promises = nonNullImages.map((image) => {\n return oroClient\n .getOrInsertJsonData<ConsultationImageMeta>(\n lockboxUuid,\n image,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.ImageAlias,\n consultationId,\n idbId: image.idbId as string,\n },\n {}\n )\n .then(() => {\n if (progress) {\n ++storedImagesNum\n let progressStepValue =\n Math.round(\n ((progress.currentStep + 1) / progress.stepsTotalNum -\n progress.currentStep / progress.stepsTotalNum) *\n 100\n ) / 100\n progress.onProgress(\n progress.currentStep / progress.stepsTotalNum +\n progressStepValue * (storedImagesNum / totalImagesNum),\n 'store_images',\n {\n storedImagesNum,\n totalImagesNum,\n }\n )\n }\n })\n })\n return Promise.all(promises)\n}\n\n/**\n * Extracts the workflow MetadataCategory for Personal, ChildPersonal and OtherPersonal\n * then stores it in the vault\n *\n * @param workflow\n * @param lockboxUuid\n * @param category\n * @returns The data uuid\n */\nexport async function extractAndStorePersonalWorkflowData(\n workflow: WorkflowData,\n lockboxUuid: Uuid,\n consultationId: Uuid,\n category: MetadataCategory.Personal | MetadataCategory.ChildPersonal | MetadataCategory.OtherPersonal,\n oroClient: OroClient\n): Promise<Uuid | void> {\n return getWorkflowDataByCategory(workflow, category as unknown as MetadataCategory).then((data) => {\n if (Object.keys(data.fields).length === 0) return\n return oroClient.getOrInsertJsonData<PersonalMeta>(\n lockboxUuid,\n data,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId],\n },\n {}\n )\n })\n}\n\n/**\n * Given workflow data, it populates it with Personal, ChildPersonal, and OtherPersonal workflow data\n * @param workflow\n */\nexport async function extractPersonalInfoFromWorkflowData(workflow: WorkflowData): Promise<{\n personalInfoPopulatedWfData: PopulatedWorkflowData\n childPersonalInfoPopulatedWfData: PopulatedWorkflowData\n otherPersonalInfoPopulatedWfData: PopulatedWorkflowData\n}> {\n return Promise.all([\n getWorkflowDataByCategory(workflow, MetadataCategory.Personal),\n getWorkflowDataByCategory(workflow, MetadataCategory.ChildPersonal),\n getWorkflowDataByCategory(workflow, MetadataCategory.OtherPersonal),\n ]).then(([personalInfoPopulatedWfData, childPersonalInfoPopulatedWfData, otherPersonalInfoPopulatedWfData]) => {\n return {\n personalInfoPopulatedWfData,\n childPersonalInfoPopulatedWfData,\n otherPersonalInfoPopulatedWfData,\n }\n })\n}\n\n/**\n * Creates the search index for the first name, last name, and the short id of the given consultation\n * @param consult the consultation to be search indexed\n * @param workflow the workflow data\n * @param oroClient\n */\nexport async function buildConsultSearchIndex(consult: Consult, workflow: WorkflowData, oroClient: OroClient) {\n let terms: Terms = [\n <Term>{\n kind: 'consult-shortid',\n value: consult.shortId,\n },\n ]\n\n const { personalInfoPopulatedWfData, childPersonalInfoPopulatedWfData, otherPersonalInfoPopulatedWfData } =\n await extractPersonalInfoFromWorkflowData(workflow)\n\n const personalInfo = identificationToPersonalInformations(\n toActualObject(personalInfoPopulatedWfData),\n MetadataCategory.Personal\n )\n const childPersonalInfo = identificationToPersonalInformations(\n toActualObject(childPersonalInfoPopulatedWfData),\n MetadataCategory.ChildPersonal\n )\n const otherPersonalInfo = identificationToPersonalInformations(\n toActualObject(otherPersonalInfoPopulatedWfData),\n MetadataCategory.OtherPersonal\n )\n\n terms.push(\n <Term>{\n kind: 'first-name',\n value: personalInfo.firstname,\n },\n <Term>{\n kind: 'last-name',\n value: personalInfo.name,\n }\n )\n\n if (childPersonalInfo.firstname && childPersonalInfo.name) {\n terms.push(\n <Term>{\n kind: 'first-name',\n value: childPersonalInfo.firstname,\n },\n <Term>{\n kind: 'last-name',\n value: childPersonalInfo.name,\n }\n )\n }\n\n if (otherPersonalInfo.firstname && otherPersonalInfo.name) {\n terms.push(\n <Term>{\n kind: 'first-name',\n value: otherPersonalInfo.firstname,\n },\n <Term>{\n kind: 'last-name',\n value: otherPersonalInfo.name,\n }\n )\n }\n\n await oroClient.searchClient.index(consult.uuid, terms)\n}\n","import { CryptoRSA, uuidParse} from \"oro-toolbox\"\nimport { EncryptedIndexEntry, Grant, IndexConsultLockbox } from \"oro-sdk-apis\"\n\n/**\n * Decrypts and returns the encrypted grants\n * If something went wrong during decryption, that grant will be removed from the list\n *\n * @param encryptedGrants: an array of encrypted grants\n * @param rsaKey: the rsa key used to decrypt the encrypted grants\n * @returns an array of grants\n */\nexport function decryptGrants(encryptedGrants: Grant[], rsaKey: CryptoRSA): Grant[] {\n return encryptedGrants\n .map(grant => {\n if (grant.encryptedLockbox && !grant.lockboxUuid) {\n try {\n grant.lockboxUuid = uuidParse(\n rsaKey.base64DecryptToBytes(grant.encryptedLockbox)\n )\n } catch (e) {\n console.error('[sdk:index] The grant could not be decrypted or was not a valid UUID: ', e)\n }\n }\n return grant\n })\n .filter(grant => grant.lockboxUuid)\n}\n\n/**\n * Decrypts the encrypted consult lockboxes and returns their grants\n * If something went wrong during decryption, that grant will be removed from the list\n *\n * @param encryptedConsultLockboxes: an array of encrypted entries\n * @param rsaKey: the rsa key used to decrypt the encrypted entries\n * @returns an array of grants\n */\nexport function decryptConsultLockboxGrants(encryptedConsultLockboxes: EncryptedIndexEntry[], rsaKey: CryptoRSA): Grant[] {\n return encryptedConsultLockboxes\n .map(encryptedConsultLockboxes => {\n try {\n return [true, (rsaKey.base64DecryptToJson(\n encryptedConsultLockboxes.encryptedIndexEntry\n ) as IndexConsultLockbox).grant]\n } catch(e) {\n console.error('[sdk:index] The consult lockbox grant could not be decrypted: ', e)\n return [false, undefined] // if decryption fails, we want to ignore the grant but not fail the call\n }\n })\n .filter(grantsTuple => grantsTuple[0])\n .map(grantTuples => grantTuples[1] as Grant)\n}","import {\n Consult,\n ConsultRequest,\n DocumentType,\n MedicalStatus,\n MetadataCategory,\n PlaceData,\n SelectedAnswersData,\n Uuid,\n WorkflowData,\n} from 'oro-sdk-apis'\nimport { OroClient } from '..'\nimport { getOrCreatePatientConsultationUuid } from './consult'\n\nconst MAX_RETRIES = 15\n/**\n * Placeholder while the workflow interpreter for the refill flows is complete\n *\n * Creates a fake workflow in which the workflow data will reside\n *\n * @param isTreatmentWorking the value from the `is treatment working` question\n * @param hasSideEffects the value from the `does the treatment have side effects` question\n * @param deliveryAddress the provided delivery address\n * @param pharmacy\n * @returns a workflow\n */\nexport function getRefillAnswersAsWorkflow(\n isTreatmentWorking: string,\n hasSideEffects: string,\n deliveryAddress?: string,\n pharmacy?: PlaceData\n): WorkflowData {\n let selectedAnswers: SelectedAnswersData = [\n {\n ['isTreatmentWorking']: isTreatmentWorking,\n },\n {\n ['hasSideEffects']: hasSideEffects,\n },\n ]\n\n if (deliveryAddress) selectedAnswers.push({ ['deliveryAddress']: deliveryAddress })\n if (pharmacy) selectedAnswers.push({ ['pharmacy']: JSON.stringify(pharmacy) })\n\n return {\n \"id\": \"32573a20-6f1d-49be-9ad3-b87c58074979\",\n \"createdAt\": \"2022-10-03T00:00:00.000Z\",\n \"culDeSacs\": [],\n \"hidePlanRules\": [],\n \"pages\": [\n {\n \"title\": \"Prescription Refill\",\n \"groups\": [\n {\n \"type\": \"field-group\",\n \"fieldsAndGroups\": [\n {\n \"type\": \"field\",\n \"id\": \"isTreatmentWorking\"\n },\n {\n \"type\": \"field\",\n \"id\": \"hasSideEffects\"\n },\n {\n \"type\": \"field\",\n \"id\": \"youPharmacy\"\n },\n {\n \"type\": \"field\",\n \"id\": \"youAddress\"\n }\n ]\n }\n ],\n \"questions\": {\n \"isTreatmentWorking\": {\n \"label\": \"Is the treatment working for you?\",\n \"kind\": \"radio\",\n \"inline\": true,\n \"inlineLabel\": false,\n \"metaCategory\": MetadataCategory.Refill,\n \"answers\": {\n \"73bec6eb-0310-4787-af3c-ac9c291737b2\": {\n \"text\": \"Yes\"\n },\n \"e193951f-986f-4db3-bede-903045a1804a\": {\n \"text\": \"No\"\n }\n }\n },\n \"hasSideEffects\": {\n \"label\": \"Are there any side effects\",\n \"kind\": \"radio\",\n \"inline\": true,\n \"inlineLabel\": false,\n \"metaCategory\": MetadataCategory.Refill,\n \"answers\": {\n \"1b87ad22-d316-4fac-9c7f-8f4ccb841aed\": {\n \"text\": \"Yes\"\n },\n \"ab7f5a41-c351-4f5d-a568-e38f9f200e9a\": {\n \"text\": \"No\"\n }\n }\n },\n \"youPharmacy\": {\n \"kind\": \"online-pharmacy-picker\",\n \"label\": \"Which pharmacy do you want the prescription sent to?\",\n \"metaCategory\": MetadataCategory.Refill,\n \"minorLabel\": \" (Optional)\",\n \"summaryLabel\": \"Your pharmacy\"\n },\n \"youAddress\": {\n \"kind\": \"place-address\",\n \"label\": \"Address\",\n \"metaCategory\": MetadataCategory.Refill\n }\n }\n }\n ],\n \"locale\": \"en\",\n selectedAnswers\n }\n}\n\n/**\n * Complete refill flow, creates a consult, stores refill data and updates consultation status\n * @param consultRequest\n * @param populatedRefillWorkflow the refill workflow data\n * @param oroClient\n */\nexport async function createRefill(\n consultRequest: ConsultRequest,\n populatedRefillWorkflow: WorkflowData,\n oroClient: OroClient\n) {\n let retry = MAX_RETRIES\n let errorsThrown: Error[] = []\n\n let newConsult: Consult | undefined\n let lockboxUuid: Uuid | undefined\n\n for (; retry > 0; retry--) {\n try {\n if (!newConsult) newConsult = await getOrCreatePatientConsultationUuid(consultRequest, oroClient)\n\n if (!lockboxUuid) lockboxUuid = (await oroClient.getGrants())[0].lockboxUuid\n\n await oroClient\n .getOrInsertJsonData(\n lockboxUuid!,\n populatedRefillWorkflow,\n {\n category: MetadataCategory.Refill,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [newConsult.uuid],\n },\n {}\n )\n .catch((err) => {\n console.error('[SDK: prescription refill] Some errors happened during refill data upload', err)\n errorsThrown.push(err)\n })\n\n if (errorsThrown.length > 0) throw errorsThrown\n await oroClient.consultClient.updateConsultByUUID(newConsult.uuid, {\n statusMedical: MedicalStatus.New,\n })\n } catch (err) {\n console.error(`[SDK] Error occured during refill: ${err}, retrying... Retries remaining: ${retry}`)\n errorsThrown = []\n continue\n }\n }\n}\n","import { IndexKey, Grant, IndexConsultLockbox, MetadataCategory, VaultIndex } from 'oro-sdk-apis'\nimport { OroClient, Uuid } from '..'\n\n/**\n * @name filterGrantsWithLockboxMetadata\n * @description searches for the existance of a consult uuid in each granted lockbox\n * @param oroClient\n * @param filter: the consult uuid\n * @returns the grants containing the consult uuid\n */\nexport async function filterGrantsWithLockboxMetadata(\n oroClient: OroClient,\n filter: { consultationId: Uuid },\n): Promise<Grant[]> {\n let grants = await oroClient.getGrants()\n let filteredGrants = []\n for (let grant of grants) {\n // Fetches in each lockbox the existance of a given consult id\n let consultationIdExistsInMetadata = await oroClient.vaultClient.lockboxMetadataGet(grant.lockboxUuid!, ['consultationId'], [], {\n category: MetadataCategory.Consultation,\n consultationId: filter.consultationId\n })\n // If there are entries in the metadata, it means that the consult exists in the lockbox\n if (consultationIdExistsInMetadata[0].length >= 0)\n filteredGrants.push(grant)\n }\n\n return filteredGrants\n}\n","import {\n AllRoleType,\n AuthTokenRequest,\n Consult,\n ConsultRequest,\n ConsultService,\n DataCreateResponse,\n DiagnosisService,\n Document,\n DocumentType,\n EncryptedIndexEntry,\n EncryptedVaultIndex,\n Grant,\n GuardService,\n IdentityCreateRequest,\n IdentityResponse,\n IndexConsultLockbox,\n IndexKey,\n LocalizedData,\n LockboxDataRequest,\n LockboxGrantRequest,\n LockboxManifest,\n ManifestEntry,\n Meta,\n Metadata,\n MetadataCategory,\n OtherRoleType,\n PersonalMeta,\n PopulatedWorkflowData,\n Practice,\n PracticeService,\n PractitionnerRoleType,\n PreferenceMeta,\n RecoveryMeta,\n RoleBasedScopes,\n SearchService,\n SecretShard,\n TellerService,\n TokenData,\n TosAndCpAcceptanceRequest,\n Uuid,\n VaultIndex,\n VaultService,\n WorkflowData,\n WorkflowService,\n} from 'oro-sdk-apis'\nimport * as OroToolbox from 'oro-toolbox'\nimport { CryptoRSA } from 'oro-toolbox'\nimport {\n createRefill,\n decryptConsultLockboxGrants,\n decryptGrants,\n registerPatient,\n sessionStorePrivateKeyName,\n} from './helpers'\nimport {\n AssociatedLockboxNotFound,\n IncompleteAuthentication,\n LocalEncryptedData,\n MissingGrant,\n MissingGrantFilter,\n MissingLockbox,\n MissingLockboxOwner,\n RecoveryData,\n RegisterPatientOutput,\n UserPreference,\n} from './models'\nimport { filterGrantsWithLockboxMetadata } from './sdk-revision'\n\nexport class OroClient {\n private rsa?: CryptoRSA\n private secrets: {\n lockboxUuid: string\n cryptor: OroToolbox.CryptoChaCha\n }[] = []\n private cachedMetadataGrants: {\n [filter: string]: Grant[]\n } = {}\n\n private cachedManifest: {\n [filter: string]: ManifestEntry[]\n } = {}\n\n private vaultIndex?: VaultIndex\n\n constructor(\n private toolbox: typeof OroToolbox,\n public tellerClient: TellerService,\n public vaultClient: VaultService,\n public guardClient: GuardService,\n public searchClient: SearchService,\n public practiceClient: PracticeService,\n public consultClient: ConsultService,\n public workflowClient: WorkflowService,\n public diagnosisClient: DiagnosisService,\n private authenticationCallback?: (err: Error) => void\n ) {}\n\n /**\n * clears the vaultIndex and cached metadata grants\n */\n public async cleanIndex() {\n this.cachedMetadataGrants = {}\n this.cachedManifest = {}\n }\n\n /**\n * Generates an RSA key pair and password payload (rsa private key encrypted with the password)\n * Calls Guard to sign up with the email address, password, practice, legal and token data\n *\n * @param email\n * @param password\n * @param practice\n * @param legal\n * @param tokenData\n * @returns\n */\n public async signUp(\n email: string,\n password: string,\n practice: Practice,\n tosAndCpAcceptance: TosAndCpAcceptanceRequest,\n tokenData?: TokenData,\n subscription?: boolean,\n skipEmailValidation?: boolean\n ): Promise<IdentityResponse> {\n this.rsa = new CryptoRSA()\n const privateKey = this.rsa.private()\n\n const symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(password)\n const recoveryPassword = symmetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n\n const hashedPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(password))\n\n const emailConfirmed = !!skipEmailValidation\n\n const signupRequest: IdentityCreateRequest = {\n practiceUuid: practice.uuid,\n email: email.toLowerCase(),\n emailConfirmed,\n password: hashedPassword,\n publicKey: this.toolbox.encodeToBase64(this.rsa.public()),\n recoveryPassword,\n tosAndCpAcceptance,\n tokenData,\n subscription,\n }\n\n const identity = await this.guardClient.identityCreate(signupRequest)\n\n if (identity.recoveryLogin) {\n //Ensure we can recover from a page reload\n let symetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(identity.recoveryLogin)\n sessionStorage.setItem(\n sessionStorePrivateKeyName(identity.id),\n symetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n )\n }\n\n return identity\n }\n\n /**\n * Parse the given accessToken claims by calling guard whoami and update theidentity to set it's emailConfirmed flag\n * @param accessToken\n * @returns The identity related to confirmedEmail\n */\n public async confirmEmail(accessToken: string): Promise<IdentityResponse> {\n this.guardClient.setTokens({ accessToken })\n const claims = await this.guardClient.whoAmI()\n return this.guardClient.identityUpdate(claims.sub, {\n emailConfirmed: true,\n })\n }\n\n /**\n * Calls Guard to sign in with the email address, password and one time password (if MFA is enabled)\n * Then recover's the rsa private key from the recovery payload\n *\n * @param practiceUuid\n * @param email\n * @param password\n * @param otp\n * @returns the user identity\n */\n public async signIn(practiceUuid: Uuid, email: string, password: string, otp?: string): Promise<IdentityResponse> {\n const hashedPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(password))\n const tokenRequest: AuthTokenRequest = {\n practiceUuid,\n email: email.toLowerCase(),\n password: hashedPassword,\n otp,\n }\n\n await this.guardClient.authToken(tokenRequest)\n const userUuid = (await this.guardClient.whoAmI()).sub\n\n // Updates the rsa key to the one generated on the backend\n await this.recoverPrivateKeyFromPassword(userUuid, password)\n return await this.guardClient.identityGet(userUuid)\n }\n\n /**\n * Will attempt to recover an existing login session and set back\n * the private key in scope\n */\n public async resumeSession() {\n const id = (await this.guardClient.whoAmI()).sub\n const recoveryPayload = sessionStorage.getItem(sessionStorePrivateKeyName(id))\n const recoveryKey = (await this.guardClient.identityGet(id)).recoveryLogin\n\n if (!recoveryKey || !recoveryPayload) throw IncompleteAuthentication\n\n const symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(recoveryKey)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * This function let's you encrypt locally an Object\n * @param value the Object to encrypt\n * @returns a LocalEncryptedData Object\n * @throws IncompleteAuthentication if rsa is not set\n * @calls authenticationCallback if rsa is not set\n */\n public localEncryptToJsonPayload(value: any): LocalEncryptedData {\n if (!this.rsa) {\n if (this.authenticationCallback) {\n this.authenticationCallback(new IncompleteAuthentication())\n }\n\n throw new IncompleteAuthentication()\n }\n\n const chaChaKey = new this.toolbox.CryptoChaCha()\n\n const encryptedData = chaChaKey.jsonEncryptToBase64Payload(value)\n const encryptedKey = this.toolbox.encodeToBase64(this.rsa.encryptToBytes(chaChaKey.key()))\n\n return { encryptedData, encryptedKey }\n }\n\n /**\n * This function let's you decrypt a LocalEncryptedData object\n * @param value a LocalEncryptedData object\n * @returns a decrypted Object\n * @throws IncompleteAuthentication if rsa is not set\n * @calls authenticationCallback if rsa is not set\n */\n public localDecryptJsonPayload({ encryptedKey, encryptedData }: LocalEncryptedData): any {\n if (!this.rsa) {\n if (this.authenticationCallback) {\n this.authenticationCallback(new IncompleteAuthentication())\n }\n\n throw new IncompleteAuthentication()\n }\n\n const chaChaKey = this.rsa.base64DecryptToBytes(encryptedKey)\n const decryptedData = this.toolbox.CryptoChaCha.fromKey(chaChaKey).base64PayloadDecryptToJson(encryptedData)\n\n return decryptedData\n }\n\n /**\n * Effectively kills your \"session\"\n */\n public async signOut() {\n this.rsa = undefined\n this.secrets = []\n this.guardClient.setTokens({\n accessToken: undefined,\n refreshToken: undefined,\n })\n await this.guardClient.authLogout()\n }\n\n /**\n * @name registerPatient\n * @description The complete flow to register a patient\n *\n * Steps:\n * 1. Create a consult (checks if payment has been done)\n * 2. Creates a lockbox\n * 3. Grants lockbox access to all practice personnel\n * 4. Creates secure identification, medical, onboarding data\n * 5. Generates and stores the rsa key pair and recovery payloads\n *\n * @param patientUuid\n * @param consult\n * @param workflow\n * @param recoveryQA\n * @param indexSearch create search index for the consultation if true\n * @param onProgress callback that is called whenever a new step of patient registration is executed. Note: progress ranges from 0 to 1, and descriptionKey is a description of the progress as a key so the app would use it to translate the description\n * @returns\n */\n public async registerPatient(\n patientUuid: Uuid,\n consult: ConsultRequest,\n workflow: WorkflowData,\n recoveryQA?: {\n recoverySecurityQuestions: string[]\n recoverySecurityAnswers: string[]\n },\n indexSearch: boolean = true,\n onProgress?: (progress: number, descriptionKey: string) => void\n ): Promise<RegisterPatientOutput> {\n if (!this.rsa) throw IncompleteAuthentication\n return registerPatient(\n patientUuid,\n consult,\n workflow,\n this,\n this.toolbox.uuid(),\n recoveryQA,\n indexSearch,\n onProgress\n )\n }\n\n /**\n * Creates and stores all relevant refill data\n * - New consultation is created\n * - Stores refill workflow data in the lockbox\n * - Updates the consult to new\n *\n * @param consult\n * @param populatedRefillWorkflow\n * @returns\n */\n public async createRefill(consult: ConsultRequest, populatedRefillWorkflow: WorkflowData): Promise<void> {\n if (!this.rsa) throw IncompleteAuthentication\n return createRefill(consult, populatedRefillWorkflow, this)\n }\n\n /**\n * Fetches all grants, and consultations that exist in each lockbox\n * Then updates the index for the current user with the lockbox consult relationship\n */\n public async forceUpdateIndexEntries() {\n let grants = await this.getGrants()\n\n let indexConsultLockbox: IndexConsultLockbox[] = await Promise.all(\n grants.map(\n async (grant: Grant) =>\n await this.vaultClient\n .lockboxMetadataGet(\n grant.lockboxUuid!,\n ['consultationId'],\n [],\n { category: MetadataCategory.Consultation },\n grant.lockboxOwnerUuid\n )\n .then((consults) => {\n try {\n return consults[0].map((consult: any) => {\n return {\n ...consult,\n grant: {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid,\n },\n }\n })\n } catch (e) {\n // No consultations in lockbox or index could not be created\n return []\n }\n })\n .catch(() => [])\n )\n ).then((consults) => consults.flat())\n this.vaultIndexAdd({\n [IndexKey.Consultation]: indexConsultLockbox,\n })\n .then(() => alert('The Index was successfully updated!'))\n .catch(() => console.error('The index failed to update!'))\n }\n\n /**\n * Generates, encrypts and adds entries to vault index for a given index owner\n *\n * @param entries\n * @param indexOwnerUuid\n */\n public async vaultIndexAdd(entries: VaultIndex, indexOwnerUuid?: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let rsaPub: Uint8Array\n if (indexOwnerUuid) {\n let base64IndexOwnerPubKey = (await this.guardClient.identityGet(indexOwnerUuid)).publicKey\n rsaPub = this.toolbox.decodeFromBase64(base64IndexOwnerPubKey)\n } else {\n rsaPub = this.rsa.public()\n }\n\n let encryptedIndex: EncryptedVaultIndex = {}\n\n for (let keyString of Object.keys(entries)) {\n let key = keyString as keyof VaultIndex\n switch (key) {\n case IndexKey.ConsultationLockbox:\n encryptedIndex[key] = (entries[key] as IndexConsultLockbox[])\n .map((e) => ({\n ...e,\n uniqueHash: e.consultationId,\n }))\n .map(\n (e: IndexConsultLockbox) =>\n ({\n uuid: e.uuid,\n timestamp: e.timestamp,\n uniqueHash: e.uniqueHash,\n encryptedIndexEntry: CryptoRSA.jsonWithPubEncryptToBase64(\n {\n consultationId: e.consultationId,\n grant: e.grant,\n },\n rsaPub\n ),\n } as EncryptedIndexEntry)\n )\n break\n }\n }\n await this.vaultClient.vaultIndexPut(encryptedIndex, indexOwnerUuid)\n }\n\n /**\n * @name grantLockbox\n * @description Grants a lockbox by retrieving the shared secret of the lockbox and encrypting it with the grantees public key\n * @param granteeUuid\n * @param lockboxUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n */\n public async grantLockbox(granteeUuid: Uuid, lockboxUuid: Uuid, lockboxOwnerUuid?: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let secret = (await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)).key()\n let base64GranteePublicKey = (await this.guardClient.identityGet(granteeUuid)).publicKey\n let granteePublicKey = this.toolbox.decodeFromBase64(base64GranteePublicKey)\n\n let granteeEncryptedSecret = CryptoRSA.bytesWithPubEncryptToBase64(secret, granteePublicKey)\n let request: LockboxGrantRequest = {\n encryptedSecret: granteeEncryptedSecret,\n granteeUuid: granteeUuid,\n }\n await this.vaultClient.lockboxGrant(lockboxUuid, request, lockboxOwnerUuid)\n }\n\n /**\n * @name createMessageData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a message string\n * @param lockboxUuid\n * @param message\n * @param consultationId the consultation for which this message is sent\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @returns the data uuid\n */\n public async createMessageData(\n lockboxUuid: Uuid,\n message: string,\n consultationId: string,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n\n let encryptedData = symmetricEncryptor.jsonEncryptToBase64Payload(message)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload({\n author: (await this.guardClient.whoAmI()).sub,\n })\n\n let meta = {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Message,\n contentType: 'text/plain',\n }\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name createMessageAttachmentData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a file\n * @param lockboxUuid\n * @param data the file stored\n * @param consultationId the consultation for which this message is sent\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @returns the data uuid\n */\n public async createMessageAttachmentData(\n lockboxUuid: Uuid,\n data: File,\n consultationId: string,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.bytesEncryptToBase64Payload(new Uint8Array(await data.arrayBuffer()))\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload({\n author: (await this.guardClient.whoAmI()).sub,\n fileName: data.name,\n lastModified: data.lastModified,\n size: data.size,\n })\n\n let meta = {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Message,\n contentType: data.type,\n }\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name createAttachmentData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a file\n * @param lockboxUuid\n * @param data the file stored\n * @param consultationId the consultation for which this message is sent\n * @param category the category for the attachment data\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @param withNotification if the insertion of data requires notification\n * @returns the data uuid\n */\n public async createConsultationAttachmentData(\n lockboxUuid: Uuid,\n data: File,\n consultationId: string,\n documentType: DocumentType,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid,\n withNotification: boolean = false\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n return this.createBytesData<Meta | any>(\n lockboxUuid,\n new Uint8Array(await data.arrayBuffer()),\n {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType,\n contentType: data.type,\n },\n {\n author: (await this.guardClient.whoAmI()).sub,\n fileName: data.name,\n },\n lockboxOwnerUuid,\n previousDataUuid,\n withNotification\n )\n }\n\n /**\n * @name createJsonData\n * @description Creates a Base64 encrypted Payload to send and store in the vault. With the data input as a JSON\n * @param lockboxUuid\n * @param data\n * @param meta\n * @param privateMeta the metadata that will be secured in the vault\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing data, specify the previous data uuid\n * @param withNotification if the insertion of data requires notification\n * @returns the data uuid\n */\n public async createJsonData<T extends Metadata>(\n lockboxUuid: Uuid,\n data: any,\n meta?: T,\n privateMeta?: { [val: string]: any },\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid,\n withNotification: boolean = false\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.jsonEncryptToBase64Payload(data)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload(privateMeta)\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n if (withNotification)\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n else return this.vaultClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * Get or upsert a data in lockbox\n * @param lockboxUuid the lockbox uuid\n * @param data the data to insert\n * @param publicMetadata the public Metadata\n * @param privateMetadata the private Metadata\n * @param forceReplace set true when the insertion of data requires to replace the data when it exists already\n * @param withNotification if the insertion of data requires notification\n * @returns the data uuid\n */\n public async getOrInsertJsonData<M extends Metadata>(\n lockboxUuid: Uuid,\n data: any,\n publicMetadata: M,\n privateMetadata: Metadata,\n forceReplace: boolean = false,\n withNotification: boolean = false\n ): Promise<Uuid> {\n let manifest = await this.vaultClient.lockboxManifestGet(lockboxUuid, publicMetadata)\n if (!forceReplace && manifest.length > 0) {\n console.log(`The data for ${JSON.stringify(publicMetadata)} already exist`)\n return manifest[0].dataUuid\n } else\n return (\n await this.createJsonData<M>(\n lockboxUuid,\n data,\n publicMetadata,\n privateMetadata,\n undefined,\n forceReplace && manifest.length > 0 ? manifest[0].dataUuid : undefined, // if forceReplace and data already exist, then replace data. Otherwise insert it\n withNotification\n ).catch((err) => {\n console.error(`Error while upserting data ${JSON.stringify(publicMetadata)} data`, err)\n throw err\n })\n ).dataUuid\n }\n\n /**\n * @name createBytesData\n * @description Creates a Base64 encrypted Payload to send and store in the vault. With the data input as a Bytes\n * @param lockboxUuid\n * @param data\n * @param meta\n * @param privateMeta the metadata that will be secured in the vault\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing data, specify the previous data uuid\n * @param withNotification if the insertion of data requires notification\n * @returns the data uuid\n */\n public async createBytesData<T extends Metadata>(\n lockboxUuid: Uuid,\n data: Uint8Array,\n meta: T,\n privateMeta: { [val: string]: any },\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid,\n withNotification: boolean = false\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.bytesEncryptToBase64Payload(data)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload(privateMeta)\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n if (withNotification)\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n else return this.vaultClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name getJsonData\n * @description Fetches and decrypts the lockbox data with the cached shared secret.\n * Decrypts the data to a valid JSON object. If this is impossible, the call to the WASM binary will fail\n *\n * @type T is the generic type specifying the return type object of the function\n * @param lockboxUuid\n * @param dataUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns the data specified by the generic type <T>\n */\n public async getJsonData<T = any>(lockboxUuid: Uuid, dataUuid: Uuid, lockboxOwnerUuid?: Uuid): Promise<T> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let [encryptedPayload, symmetricDecryptor] = await Promise.all([\n this.vaultClient.lockboxDataGet(lockboxUuid, dataUuid, lockboxOwnerUuid),\n this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid),\n ])\n\n return symmetricDecryptor.base64PayloadDecryptToJson(encryptedPayload.data)\n }\n /**\n * @description Fetches and decrypts the lockbox data with the cached shared secret.\n * @param lockboxUuid\n * @param dataUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns the bytes data\n */\n public async getBytesData(lockboxUuid: Uuid, dataUuid: Uuid, lockboxOwnerUuid?: Uuid): Promise<Uint8Array> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let [encryptedPayload, symmetricDecryptor] = await Promise.all([\n this.vaultClient.lockboxDataGet(lockboxUuid, dataUuid, lockboxOwnerUuid),\n this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid),\n ])\n\n return symmetricDecryptor.base64PayloadDecryptToBytes(encryptedPayload.data)\n }\n\n /**\n * @name getGrants\n * @description Get all lockboxes granted to user with the applied filter\n * @note this function returns cached grants and will not update unless the page is refreshed\n * @todo some versions of lockboxes do not make use of lockbox metadata\n * in this case, all lockboxes need to be filtered one-by-one to find the correct one\n * Remove if this is no longer the case\n * @param filter: the consultationId in which the grant exists\n * @returns decrypted lockboxes granted to user\n */\n public async getGrants(filter?: { consultationId: Uuid }): Promise<Grant[]> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let filterString = JSON.stringify(filter)\n // retrieves cached grants\n if (this.cachedMetadataGrants[filterString]) return this.cachedMetadataGrants[filterString]\n\n // We're using the account role to determine the way a grant is accessed\n let currentAccountRole = await this.getAccountRole()\n if (currentAccountRole.length === 1 && currentAccountRole[0] === OtherRoleType.User) return []\n\n if (\n [OtherRoleType.Patient, OtherRoleType.User].every((requiredRole) =>\n currentAccountRole.includes(requiredRole)\n )\n ) {\n let encryptedGrants\n // if there are no grants with the applied filter from index, attempt for naive filter with backwards compatibility\n if (filter) {\n encryptedGrants = await filterGrantsWithLockboxMetadata(this, filter)\n } else {\n encryptedGrants = (await this.vaultClient.grantsGet()).grants\n }\n const decryptedGrants = await decryptGrants(encryptedGrants, this.rsa)\n // sets the cached grant\n this.cachedMetadataGrants[filterString] = decryptedGrants\n console.info('[sdk:grant] Found grant for patient')\n return decryptedGrants\n }\n // if not a patient, then a practitioner is trying to retrieve a grant, it **Must** contain a filter, otherwise too many grants are possible\n if (!filter) throw MissingGrantFilter\n // Note: will work only if the filter being applied is exclusively a consult id\n const grantsByConsultLockbox = await this.vaultClient\n .vaultIndexGet([IndexKey.ConsultationLockbox], [filter.consultationId])\n .then((res) => res[IndexKey.ConsultationLockbox])\n .catch((e) => {\n console.error(e)\n return []\n })\n\n const decryptedConsults = decryptConsultLockboxGrants(grantsByConsultLockbox ?? [], this.rsa)\n if (decryptedConsults.length > 0) {\n console.info('[sdk:index] Grants found in user`s constant time secure index')\n this.cachedMetadataGrants[filterString] = decryptedConsults\n return this.cachedMetadataGrants[filterString]\n }\n\n // if we have no valid grants, then return nothing\n return []\n }\n\n /**\n * Fetches the role of the account that is logged in\n *\n * @returns the role based scopes defined by the whoami\n */\n async getAccountRole(): Promise<RoleBasedScopes[]> {\n return (await this.guardClient.whoAmI()).scope.split(' ') as RoleBasedScopes[]\n }\n\n /**\n * @name getCachedSecretCryptor\n * @description Retrieves the cached lockbox secret or fetches the secret from vault, then creates the symmetric cryptor and stores it in memory\n * @param lockboxUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns\n */\n async getCachedSecretCryptor(lockboxUuid: string, lockboxOwnerUuid?: string): Promise<OroToolbox.CryptoChaCha> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let index = this.secrets.findIndex((secret) => secret.lockboxUuid === lockboxUuid)\n if (index === -1) {\n let encryptedSecret = (await this.vaultClient.lockboxSecretGet(lockboxUuid, lockboxOwnerUuid)).sharedSecret\n\n let secret = this.rsa.base64DecryptToBytes(encryptedSecret)\n let cryptor = this.toolbox.CryptoChaCha.fromKey(secret)\n this.secrets.push({ lockboxUuid, cryptor })\n return cryptor\n } else {\n return this.secrets[index].cryptor\n }\n }\n\n /**\n * Retrieves the patient personal information associated to the `consultationId`\n * The `consultationId` only helps to retrieve the patient lockboxes\n * Note: it is possible to have several personal informations data\n * @param consultationId The consultation Id\n * @param category The personal MetadataCategory to fetch\n * @param forceRefresh force data refresh (default to false)\n * @returns the personal data\n */\n public async getPersonalInformationsFromConsultId(\n consultationId: Uuid,\n category: MetadataCategory.Personal | MetadataCategory.ChildPersonal | MetadataCategory.OtherPersonal,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n return this.getMetaCategoryFromConsultId(consultationId, category, forceRefresh)\n }\n\n /**\n * Retrieves the patient medical data associated to the `consultationId`\n * The `consultationId` only helps to retrieve the patient lockboxes\n * Note: it is possible to have several medical data\n * @param consultationId The consultation Id\n * @param forceRefresh force data refresh (default to false)\n * @returns the medical data\n */\n public async getMedicalDataFromConsultId(\n consultationId: Uuid,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n return this.getMetaCategoryFromConsultId(consultationId, MetadataCategory.Medical, forceRefresh)\n }\n\n private async getMetaCategoryFromConsultId(\n consultationId: Uuid,\n category: MetadataCategory,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n let grants = await this.getGrants({ consultationId })\n let workflowData: LocalizedData<PopulatedWorkflowData>[] = []\n for (let grant of grants) {\n let manifest = await this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId],\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n )\n\n // TODO: find another solution for backwards compatibility (those without the metadata consultationIds)\n if (manifest.length === 0) {\n manifest = (\n await this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n // backward compatiblility with TonTest\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n )\n ).filter((entry) => !entry.metadata.consultationIds) // Keep only entries without associated consultationIds\n }\n let data = await Promise.all(\n manifest.map(async (entry) => {\n return {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid!,\n dataUuid: entry.dataUuid,\n data: await this.getJsonData<PopulatedWorkflowData>(grant.lockboxUuid!, entry.dataUuid),\n }\n })\n )\n workflowData = { ...workflowData, ...data }\n }\n return workflowData\n }\n\n /**\n * @description retrieves the personal information stored in the first owned lockbox\n * @param userId The user Id\n * @returns the personal data\n */\n public async getPersonalInformations(userId: Uuid): Promise<LocalizedData<PopulatedWorkflowData>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === userId)\n\n if (!grant) {\n throw MissingGrant\n }\n\n const { lockboxUuid, lockboxOwnerUuid } = grant\n\n if (!lockboxUuid) throw MissingLockbox\n\n if (!lockboxOwnerUuid) throw MissingLockboxOwner\n\n const identificationDataUuid = (\n await this.getLockboxManifest(\n lockboxUuid,\n {\n category: MetadataCategory.Personal,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n false,\n userId\n )\n )[0].dataUuid\n\n return {\n lockboxOwnerUuid,\n lockboxUuid,\n dataUuid: identificationDataUuid,\n data: await this.getJsonData<PopulatedWorkflowData>(lockboxUuid, identificationDataUuid),\n }\n }\n\n /**\n * Retrieves the grant associated to a consultationId\n * @note returns the first grant only\n * @param consultationId The consultationId\n * @returns the grant\n */\n public async getGrantFromConsultId(consultationId: Uuid): Promise<Grant | undefined> {\n let grants = await this.getGrants({ consultationId })\n\n if (grants.length === 0) {\n throw AssociatedLockboxNotFound\n }\n\n return grants[0]\n }\n\n /**\n * retrieves the identity associated to the `consultationId`\n * @param consultationId The consultation Id\n * @returns the identity\n */\n public async getIdentityFromConsultId(consultationId: Uuid): Promise<IdentityResponse | undefined> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (grant && grant.lockboxOwnerUuid) {\n return await this.guardClient.identityGet(grant.lockboxOwnerUuid)\n } else {\n return undefined\n }\n }\n\n /**\n * retrieves the lockbox manifest for a given lockbox and add's its private metadata\n * @note the lockbox manifest will retrieved the cached manifest first unless force refresh is enabled\n * @param lockboxUuid\n * @param filter\n * @param expandPrivateMetadata\n * @param lockboxOwnerUuid\n * @param forceRefresh\n * @returns the lockbox manifest\n */\n public async getLockboxManifest(\n lockboxUuid: Uuid,\n filter: Metadata,\n expandPrivateMetadata: boolean,\n lockboxOwnerUuid?: Uuid,\n forceRefresh: boolean = false\n ): Promise<LockboxManifest> {\n let manifestKey = JSON.stringify({\n lockboxUuid,\n filter,\n expandPrivateMetadata,\n lockboxOwnerUuid,\n })\n if (!forceRefresh && this.cachedManifest[manifestKey]) return this.cachedManifest[manifestKey]\n\n return this.vaultClient.lockboxManifestGet(lockboxUuid, filter, lockboxOwnerUuid).then((manifest) => {\n return Promise.all(\n manifest.map(async (entry) => {\n if (expandPrivateMetadata && entry.metadata.privateMetadata) {\n let privateMeta = await this.getJsonData<Metadata>(\n lockboxUuid!,\n entry.metadata.privateMetadata,\n lockboxOwnerUuid\n )\n entry.metadata = {\n ...entry.metadata,\n ...privateMeta,\n }\n }\n return entry\n })\n ).then((manifest) => (this.cachedManifest[manifestKey] = manifest))\n })\n }\n\n /**\n * @description Create or update the personal information and store it in the first owned lockbox\n * @param identity The identity to use\n * @param data The personal data to store\n * @param dataUuid (optional) The dataUuid to update\n * @returns\n */\n public async createPersonalInformations(\n identity: IdentityResponse,\n data: PopulatedWorkflowData,\n dataUuid?: string\n ): Promise<DataCreateResponse> {\n const lockboxUuid = (await this.getGrants()).find(\n (lockbox) => lockbox.lockboxOwnerUuid === identity.id\n )?.lockboxUuid\n\n if (lockboxUuid) {\n return this.createJsonData<PersonalMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Personal,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n {},\n undefined,\n dataUuid\n )\n } else {\n throw MissingLockbox\n }\n }\n\n /**\n * Create or update user Preference\n * @param identity\n * @param preference\n * @param dataUuid\n * @returns\n */\n public async createUserPreference(\n identity: IdentityResponse,\n preference: UserPreference,\n dataUuid?: string\n ): Promise<DataCreateResponse> {\n const lockboxUuid = (await this.getGrants()).find(\n (lockbox) => lockbox.lockboxOwnerUuid === identity.id\n )?.lockboxUuid\n\n if (lockboxUuid) {\n return this.createJsonData<PreferenceMeta>(\n lockboxUuid,\n preference,\n {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n },\n {},\n undefined,\n dataUuid\n )\n } else {\n throw MissingLockbox\n }\n }\n\n /**\n * retrieves the user preference from a grant\n * @param grant The grant\n * @returns the user preference\n */\n public async getDataFromGrant<T = any>(grant: Grant, filter: Metadata): Promise<LocalizedData<T>> {\n const { lockboxUuid, lockboxOwnerUuid } = grant\n\n if (!lockboxUuid) throw MissingLockbox\n if (!lockboxOwnerUuid) throw MissingLockboxOwner\n const identificationDataUuid = (\n await this.getLockboxManifest(\n lockboxUuid,\n\n filter,\n false,\n grant.lockboxOwnerUuid,\n true\n )\n )[0].dataUuid\n\n return {\n lockboxOwnerUuid,\n lockboxUuid,\n dataUuid: identificationDataUuid,\n data: await this.getJsonData<T>(lockboxUuid, identificationDataUuid),\n }\n }\n\n /**\n * retrieves the user preference from a consultation id\n * @param consultationId The related consultationId\n * @returns the user preference\n */\n public async getUserPreferenceFromConsultId(consultationId: string): Promise<LocalizedData<UserPreference>> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<UserPreference>(grant, {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference stored in the first owned lockbox from identity\n * @param identity The identity to use\n * @returns the user preference\n */\n public async getUserPreference(identity: IdentityResponse): Promise<LocalizedData<UserPreference>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === identity.id)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<UserPreference>(grant, {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference from a consultation id\n * @param consultationId The related consultationId\n * @returns the user preference\n */\n public async getRecoveryDataFromConsultId(consultationId: string): Promise<LocalizedData<RecoveryData>> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<RecoveryData>(grant, {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference stored in the first owned lockbox from identity\n * @param identity The identity to use\n * @returns the user preference\n */\n public async getRecoveryData(identity: IdentityResponse): Promise<LocalizedData<RecoveryData>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === identity.id)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant(grant, {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n })\n }\n\n /**\n * @name getAssignedConsultations\n * @description finds all assigned or owned consultations for the logged user\n * Steps:\n * - Retrieves all granted lockboxes given to the logged user\n * - for each lockbox, find all consultation ids\n * - for each consultation id, retrieve the consult information\n * @param practiceUuid the uuid of the practice to look consult into\n * @returns the list of consults\n */\n public async getAssignedConsultations(practiceUuid: Uuid): Promise<Consult[]> {\n return Promise.all(\n (await this.getGrants()).map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n true,\n undefined\n ).then((manifest) =>\n Promise.all(\n manifest.map(\n async (entry) =>\n await this.consultClient.getConsultByUUID(entry.metadata.consultationId, practiceUuid)\n )\n ).then((promise) => promise.flat())\n )\n )\n ).then((consults) => consults.flat())\n }\n\n /**\n * Gets the past consultations of the patient as well as his relatives if any\n * @param consultationId any consultation uuid from which we will fetch all the other consultations of the same patient as the owner of this consultation id\n * @param practiceUuid\n */\n public async getPastConsultationsFromConsultId(\n consultationId: string,\n practiceUuid: string\n ): Promise<Consult[] | undefined> {\n const grant = await this.getGrantFromConsultId(consultationId)\n if (!grant) return undefined\n\n let consultationsInLockbox: string[] = (\n await this.vaultClient.lockboxMetadataGet(\n grant.lockboxUuid!,\n ['consultationId'],\n ['consultationId'],\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n grant.lockboxOwnerUuid\n )\n )\n .flat()\n .map((metadata: { consultationId: string }) => metadata.consultationId)\n\n if (consultationsInLockbox.length == 0) return []\n\n return await Promise.all(\n consultationsInLockbox.map(async (consultId: string) => {\n return await this.consultClient.getConsultByUUID(consultId, practiceUuid)\n })\n )\n }\n\n /**\n * @name getPatientConsultationData\n * @description retrieves the consultation data\n * @param consultationId\n * @returns\n */\n public async getPatientConsultationData(\n consultationId: Uuid,\n forceRefresh: boolean = false\n ): Promise<PopulatedWorkflowData[]> {\n //TODO: make use of getPatientDocumentsList instead of doing it manually here\n return Promise.all(\n (await this.getGrants({ consultationId }))\n .map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationId, //since we want to update the cached manifest (if another consult data exists)\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n ).then((manifest) =>\n Promise.all(\n manifest.map((e) =>\n this.getJsonData<PopulatedWorkflowData>(\n grant.lockboxUuid!,\n e.dataUuid,\n grant.lockboxOwnerUuid\n )\n )\n )\n )\n )\n .flat()\n ).then((data) => data.flat())\n }\n\n /**\n * This function returns the patient prescriptions\n * @param consultationId\n * @returns\n */\n public async getPatientPrescriptionsList(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Prescription,\n },\n true,\n consultationId\n )\n }\n\n /**\n * This function returns the patient results\n * @param consultationId\n * @returns\n */\n public async getPatientResultsList(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Result,\n },\n true,\n consultationId\n )\n }\n\n /**\n * returns the patient treatment plan options\n * @param consultationId\n * @returns Document[] corresponding to the patient treatment plan options\n */\n public async getPatientTreatmentPlans(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.TreatmentPlan,\n },\n true,\n consultationId\n )\n }\n\n /**\n * returns a specific patient treatment plan option\n * @param consultationId\n * @param treatmentPlanId\n * @returns\n */\n public async getPatientTreatmentPlanByUuid(consultationId: Uuid, treatmentPlanId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.TreatmentPlan,\n treatmentPlanId,\n },\n true,\n consultationId\n )\n }\n\n /**\n * @name getPatientDocumentsList\n * @description applies the provided filter to the vault to only find those documents\n * @param filters the applied filters (e.g. type of documents)\n * @param expandPrivateMetadata whether or not, the private metadata needs to be retrieved\n * (more computationally expensive)\n * @param consultationId\n * @returns the filtered document list\n */\n public async getPatientDocumentsList(\n filters: Object,\n expandPrivateMetadata: boolean,\n consultationId: Uuid\n ): Promise<Document[]> {\n return Promise.all(\n (await this.getGrants({ consultationId }))\n .map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n { ...filters, consultationId },\n expandPrivateMetadata,\n grant.lockboxOwnerUuid,\n true\n ).then((manifest) =>\n Promise.all(\n manifest.map(async (entry): Promise<Document> => {\n return {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid!,\n ...entry,\n }\n })\n )\n )\n )\n .flat()\n ).then((data) => data.flat())\n }\n\n /****************************************************************************************************************\n * RECOVERY *\n ****************************************************************************************************************/\n\n /**\n * @name recoverPrivateKeyFromSecurityQuestions\n * @description Recovers and sets the rsa private key from the answered security questions\n * @param id\n * @param recoverySecurityQuestions\n * @param recoverySecurityAnswers\n * @param threshold the number of answers needed to recover the key\n */\n public async recoverPrivateKeyFromSecurityQuestions(\n id: Uuid,\n recoverySecurityQuestions: string[],\n recoverySecurityAnswers: string[],\n threshold: number\n ) {\n let shards: SecretShard[] = (await this.guardClient.identityGet(id)).recoverySecurityQuestions!\n let answeredShards = shards\n .filter((shard: any) => {\n // filters all answered security questions\n let indexOfQuestion = recoverySecurityQuestions.indexOf(shard.securityQuestion)\n if (indexOfQuestion === -1) return false\n return recoverySecurityAnswers[indexOfQuestion] && recoverySecurityAnswers[indexOfQuestion] != ''\n })\n .map((item: any) => {\n // appends the security answer to the answered shards\n let index = recoverySecurityQuestions.indexOf(item.securityQuestion)\n item.securityAnswer = recoverySecurityAnswers[index]\n return item\n })\n try {\n // reconstructs the key from the answered security answers\n let privateKey = this.toolbox.reconstructSecret(answeredShards, threshold)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n } catch (e) {\n console.error(e)\n }\n }\n\n /**\n * @name recoverPrivateKeyFromPassword\n * @description Recovers and sets the rsa private key from the password\n * @param id\n * @param password\n */\n public async recoverPrivateKeyFromPassword(id: Uuid, password: string) {\n let identity = await this.guardClient.identityGet(id)\n\n let recoveryPayload = identity.recoveryPassword\n let symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(password)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n\n if (identity.recoveryLogin) {\n //Ensure we can recover from a page reload\n let symetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(identity.recoveryLogin)\n sessionStorage.setItem(\n sessionStorePrivateKeyName(id),\n symetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n )\n }\n\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * @name recoverPrivateKeyFromMasterKey\n * @description Recovers and sets the rsa private key from the master key\n * @param id\n * @param masterKey\n */\n public async recoverPrivateKeyFromMasterKey(id: Uuid, masterKey: string) {\n let recoveryPayload = (await this.guardClient.identityGet(id)).recoveryMasterKey!\n let symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(masterKey)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * @description Generates and updates the security questions and answers payload using new recovery questions and answers\n * Important: Since the security questions generate a payload for the private key, they will never be stored on the device as they must remain secret!!!\n * @param id\n * @param recoverySecurityQuestions\n * @param recoverySecurityAnswers\n * @param threshold the number of answers needed to rebuild the secret\n */\n public async updateSecurityQuestions(\n id: Uuid,\n recoverySecurityQuestions: string[],\n recoverySecurityAnswers: string[],\n threshold: number\n ) {\n if (!this.rsa) throw IncompleteAuthentication\n let securityQuestionPayload = this.toolbox.breakSecretIntoShards(\n recoverySecurityQuestions,\n recoverySecurityAnswers,\n this.rsa.private(),\n threshold\n )\n let updateRequest = {\n recoverySecurityQuestions: securityQuestionPayload,\n }\n\n return await this.guardClient.identityUpdate(id, updateRequest)\n }\n\n /**\n * @description Generates and stores the payload encrypted payload and updates the password itself (double hash)\n * @important\n * the recovery payload uses a singly hashed password and the password stored is doubly hashed so\n * the stored password cannot derive the decryption key in the payload\n * @note\n * the old password must be provided when not performing an account recovery\n * @param id\n * @param newPassword\n * @param oldPassword\n */\n public async updatePassword(id: Uuid, newPassword: string, oldPassword?: string) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(newPassword)\n let passwordPayload = symmetricEncryptor.bytesEncryptToBase64Payload(this.rsa.private())\n if (oldPassword) {\n oldPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(oldPassword))\n }\n\n newPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(newPassword))\n\n let updateRequest = {\n password: {\n oldPassword,\n newPassword,\n },\n recoveryPassword: passwordPayload,\n }\n\n return await this.guardClient.identityUpdate(id, updateRequest)\n }\n\n /**\n * @description Generates and stores the master key encrypted payload\n * Important\n * Since the master key is used to generate a payload for the private key, it will never be stored on the device as it must remain secret!\n * @param id\n * @param masterKey\n * @param lockboxUuid\n */\n async updateMasterKey(id: Uuid, masterKey: string, lockboxUuid: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(masterKey)\n let masterKeyPayload = symmetricEncryptor.bytesEncryptToBase64Payload(this.rsa.private())\n let updateRequest = { recoveryMasterKey: masterKeyPayload }\n const updatedIdentity = await this.guardClient.identityUpdate(id, updateRequest)\n\n await this.getOrInsertJsonData<RecoveryMeta>(\n lockboxUuid,\n { masterKey },\n {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n },\n {},\n true\n )\n\n return updatedIdentity\n }\n}\n","import { AxiosService, CliniaResponse, FacetFilter, PlaceData } from \"oro-sdk-apis\"\n\nexport class CliniaService {\n private api: AxiosService\n\n constructor(private url: string, apiKey: string, private locale?: string) {\n this.api = new AxiosService({ headers: { 'X-Clinia-API-Key': apiKey } })\n }\n\n public placeSearch(searchOptions: {\n locale?: string\n query?: string\n facetFilters?: FacetFilter[]\n location?: string\n aroundLatLng?: string\n page?: number\n }) {\n const { locale, ...data } = searchOptions\n\n return this.api.post<CliniaResponse<PlaceData>>(\n `${this.url}/search/v1/indexes/health_facility/query`,\n data,\n {\n params: { locale: locale ?? this.locale },\n }\n )\n }\n\n public placeMatch(\n searchOptions: {\n locale?: string\n name?: string\n address?: string\n postalCode?: string\n place?: string\n region?: string\n country?: string\n },\n type?: string\n ) {\n const { locale, ...data } = searchOptions\n\n let request = this.api.post<PlaceData[]>(\n `${this.url}/search/v1/matches`,\n data,\n {\n params: { locale: locale ?? this.locale },\n }\n )\n\n if (type) {\n request = request.then((places) =>\n places.filter((place) => place.type === type)\n )\n }\n\n return request\n }\n}\n","import initApis from 'oro-sdk-apis'\nimport { OroClient } from './client'\nimport * as OroToolboxNamespace from 'oro-toolbox'\n\nexport type OroToolbox = typeof OroToolboxNamespace\n\nexport let wasmPath = 'node_modules/oro-toolbox'\n\n/**\n * This function helps you to initialize and OroClient instance\n * @param toolbox the OroToolbox object\n * @param tellerBaseURL the teller service base URL \n * @param vaultBaseURL the vault service base URL \n * @param guardBaseURL the guard service base URL \n * @param searchbaseURL the search service base URL\n * @param practiceBaseURL the practice service base URL \n * @param consultBaseURL the consult service base URL \n * @param workflowBaseURL the workflow service base URL \n * @param diagnosisBaseURL the diagnosis service base URL \n * @param authenticationCallback (optional) authenticationCallback the authentification callback \n * @returns an instance of OroClient\n */\nconst init = (\n toolbox: OroToolbox,\n tellerBaseURL: string,\n vaultBaseURL: string,\n guardBaseURL: string,\n searchBaseURL: string,\n practiceBaseURL: string,\n consultBaseURL: string,\n workflowBaseURL: string,\n diagnosisBaseURL: string,\n authenticationCallback?: (err: Error) => void\n) => {\n const {\n tellerService,\n practiceService,\n consultService,\n vaultService,\n guardService,\n searchService,\n workflowService,\n diagnosisService,\n } = initApis(\n {\n tellerBaseURL,\n vaultBaseURL,\n guardBaseURL,\n searchBaseURL,\n practiceBaseURL,\n consultBaseURL,\n workflowBaseURL,\n diagnosisBaseURL,\n },\n authenticationCallback\n )\n\n const client = new OroClient(\n toolbox,\n tellerService!,\n vaultService!,\n guardService!,\n searchService!,\n practiceService!,\n consultService!,\n workflowService!,\n diagnosisService!,\n authenticationCallback\n )\n\n return client\n}\n\nexport { OroClient } from './client'\nexport * from 'oro-sdk-apis'\nexport * from './models'\nexport * from './helpers'\nexport * from './services'\nexport { OroToolboxNamespace }\nexport default init\n"],"names":["personalMetaToPrefix","MetadataCategory","Personal","ChildPersonal","OtherPersonal","identificationToPersonalInformations","data","category","prefix","birthday","firstname","gender","name","phone","zip","hid","pharmacy","address","toActualObject","ret","Object","entries","fields","forEach","field","displayedAnswer","answer","sessionStorePrivateKeyName","id","IncompleteAuthentication","_inheritsLoose","Error","MissingGrant","MissingGrantFilter","MissingLockbox","MissingLockboxOwner","AssociatedLockboxNotFound","WorkflowAnswersMissingError","filterTriggeredAnsweredWithKind","workflowData","kind","selectedAnswers","_context","flattenedAnswers","flattenSelectedAnswers","triggeredQuestionsWithKind","fromEntries","pages","map","a","questions","filter","question","isTriggered","triggers","flat","samePageAnswers","reduce","prev","cur","res","keys","questionFieldName","getWorkflowDataByCategory","_context2","triggeredQuestions","Promise","all","e","k","populateWorkflowField","then","populatedValue","workflowCreatedAt","createdAt","workflowId","locale","err","console","error","getImagesFromIndexDb","_context3","getMany","v","answerValue","undefined","_context4","answers","text","value","images","image","imageData","resolve","includes","Array","isArray","some","subSetTriggers","every","trigger","linearAnswers","push","values","getInitialisedSelectedAnswers","workflow","useDefault","page","defaultValue","getOrCreatePatientConsultationUuid","consult","oroClient","practiceClient","practiceGetPayment","uuidPractice","idStripeInvoiceOrPaymentIntent","payment","uuidConsult","consultClient","getConsultByUUID","consultCreate","registerPatient","patientUuid","consultRequest","masterKey","recoveryQA","indexSearch","onProgress","lockboxUuid","practitionerAdmin","retry","identity","errorsThrown","stepsTotalNum","currentStep","setTimeout","practiceGetFromUuid","uuidAdmin","practiceGetPractitioners","log","practitioners","getOrCreatePatientLockbox","guardClient","identityGet","grantLockbox","grantPromises","practitioner","uuid","IndexKey","ConsultationLockbox","grant","lockboxOwnerUuid","consultationId","consultIndex","consultIndexPromises","vaultIndexAdd","storeImageAliases","storePatientData","isoLanguageRequired","_identity","recoveryMasterKey","updateMasterKey","_identity2","recoverySecurityQuestions","updateSecurityQuestions","recoverySecurityAnswers","buildConsultSearchIndex","length","updateConsultByUUID","statusMedical","MedicalStatus","New","cleanIndex","_context5","getGrants","grants","vaultClient","lockboxCreate","lockboxResponse","authRefresh","tokens","setTokens","accessToken","refreshToken","whoAmI","isoLanguage","getOrInsertJsonData","Raw","contentType","Consultation","documentType","DocumentType","PopulatedWorkflowData","Medical","consultationIds","extractAndStorePersonalWorkflowData","Preference","dataUuids","progress","_context7","nonNullImages","img","storedImagesNum","totalImagesNum","promises","ImageAlias","idbId","progressStepValue","Math","round","extractPersonalInfoFromWorkflowData","personalInfoPopulatedWfData","childPersonalInfoPopulatedWfData","otherPersonalInfoPopulatedWfData","terms","shortId","_context10","_yield$extractPersona","personalInfo","childPersonalInfo","otherPersonalInfo","searchClient","index","decryptGrants","encryptedGrants","rsaKey","encryptedLockbox","uuidParse","base64DecryptToBytes","decryptConsultLockboxGrants","encryptedConsultLockboxes","base64DecryptToJson","encryptedIndexEntry","grantsTuple","grantTuples","createRefill","populatedRefillWorkflow","newConsult","Refill","filterGrantsWithLockboxMetadata","filteredGrants","_iterator","lockboxMetadataGet","OroClient","toolbox","tellerClient","workflowClient","diagnosisClient","authenticationCallback","this","_proto","cachedMetadataGrants","cachedManifest","signUp","email","password","practice","tosAndCpAcceptance","tokenData","subscription","skipEmailValidation","rsa","CryptoRSA","privateKey","symmetricEncryptor","CryptoChaCha","fromPassphrase","recoveryPassword","bytesEncryptToBase64Payload","hashedPassword","hashStringToBase64","emailConfirmed","signupRequest","practiceUuid","toLowerCase","publicKey","encodeToBase64","identityCreate","recoveryLogin","symetricEncryptor","sessionStorage","setItem","confirmEmail","identityUpdate","sub","signIn","otp","tokenRequest","authToken","userUuid","recoverPrivateKeyFromPassword","resumeSession","recoveryPayload","getItem","recoveryKey","symmetricDecryptor","base64PayloadDecryptToBytes","fromKey","localEncryptToJsonPayload","chaChaKey","encryptedData","jsonEncryptToBase64Payload","encryptedKey","encryptToBytes","key","localDecryptJsonPayload","base64PayloadDecryptToJson","signOut","secrets","_context6","authLogout","_context8","forceUpdateIndexEntries","_context9","_this","consults","alert","indexOwnerUuid","_context11","rsaPub","decodeFromBase64","encryptedIndex","_i","uniqueHash","timestamp","jsonWithPubEncryptToBase64","vaultIndexPut","granteeUuid","_context12","getCachedSecretCryptor","secret","granteePublicKey","granteeEncryptedSecret","bytesWithPubEncryptToBase64","request","encryptedSecret","lockboxGrant","createMessageData","message","previousDataUuid","_context13","author","encryptedPrivateMeta","lockboxDataStore","publicMetadata","Message","privateMetadata","createMessageAttachmentData","_context14","Uint8Array","arrayBuffer","lastModified","size","fileName","type","createConsultationAttachmentData","withNotification","_context15","createBytesData","createJsonData","meta","privateMeta","_context16","forceReplace","_context17","lockboxManifestGet","manifest","JSON","stringify","dataUuid","_context18","getJsonData","_context19","lockboxDataGet","_yield$Promise$all","getBytesData","_context20","_yield$Promise$all2","_context21","filterString","getAccountRole","currentAccountRole","OtherRoleType","User","Patient","requiredRole","grantsGet","decryptedGrants","info","vaultIndexGet","decryptedConsults","grantsByConsultLockbox","_context22","scope","split","_context23","findIndex","lockboxSecretGet","sharedSecret","cryptor","getPersonalInformationsFromConsultId","forceRefresh","getMetaCategoryFromConsultId","getMedicalDataFromConsultId","_context28","_loop","_context27","_this2","getLockboxManifest","entry","metadata","_context26","getPersonalInformations","userId","_context29","find","lockbox","identificationDataUuid","getGrantFromConsultId","_context30","getIdentityFromConsultId","_context31","expandPrivateMetadata","manifestKey","_context33","_context32","_this3","createPersonalInformations","_context34","_yield$this$getGrants","createUserPreference","preference","_context35","_yield$this$getGrants2","getDataFromGrant","_context36","getUserPreferenceFromConsultId","_context37","getUserPreference","_context38","getRecoveryDataFromConsultId","_context39","Recovery","getRecoveryData","_context40","getAssignedConsultations","_context42","_this4","_context41","promise","getPastConsultationsFromConsultId","_context44","consultationsInLockbox","consultId","_context43","_this5","getPatientConsultationData","_context45","_this6","getPatientPrescriptionsList","getPatientDocumentsList","Prescription","getPatientResultsList","Result","getPatientTreatmentPlans","TreatmentPlan","getPatientTreatmentPlanByUuid","treatmentPlanId","filters","_context51","_this7","recoverPrivateKeyFromSecurityQuestions","threshold","_context52","answeredShards","shard","indexOfQuestion","indexOf","securityQuestion","item","securityAnswer","reconstructSecret","_context53","recoverPrivateKeyFromMasterKey","_context54","_context55","securityQuestionPayload","breakSecretIntoShards","updateRequest","updatePassword","newPassword","oldPassword","_context56","passwordPayload","_context57","masterKeyPayload","updatedIdentity","CliniaService","url","apiKey","api","AxiosService","headers","X-Clinia-API-Key","placeSearch","searchOptions","post","params","placeMatch","places","place","tellerBaseURL","vaultBaseURL","guardBaseURL","searchBaseURL","practiceBaseURL","consultBaseURL","workflowBaseURL","diagnosisBaseURL","initApis","tellerService","vaultService","guardService","searchService","practiceService","consultService","workflowService","diagnosisService","arrSelectedLocality","flatMap","currentAnswerPage","arrCountryFields","workflowFieldName","arrProvinceFields","arrConsultLocalFields","currentFieldName","currentSelectedLocality","startsWith","allowedLocalityPatterns","indexPriority","isoValue","finalLocality","extractedSelected","exec","indexSelectedPriority","isoSelectedValue","extractedFinal","indexFinalPriority","populatedWorkflow","filledWorkflow","parse","pageIdx","isTreatmentWorking","hasSideEffects","deliveryAddress","culDeSacs","hidePlanRules","title","groups","fieldsAndGroups","label","inline","inlineLabel","metaCategory","73bec6eb-0310-4787-af3c-ac9c291737b2","e193951f-986f-4db3-bede-903045a1804a","1b87ad22-d316-4fac-9c7f-8f4ccb841aed","ab7f5a41-c351-4f5d-a568-e38f9f200e9a","youPharmacy","minorLabel","summaryLabel","youAddress","infos"],"mappings":"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"}
1
+ {"version":3,"file":"oro-sdk.cjs.production.min.js","sources":["../src/helpers/client.ts","../src/models/error.ts","../src/helpers/workflow.ts","../src/helpers/consult.ts","../src/helpers/patient-registration.ts","../src/helpers/vault-grants.ts","../src/helpers/prescription-refill.ts","../src/sdk-revision/client.ts","../src/client.ts","../src/services/external/clinia.ts","../src/index.ts"],"sourcesContent":["import {\n PopulatedWorkflowData,\n MetadataCategory,\n SelectedAnswersData,\n} from 'oro-sdk-apis'\nimport { PersonalInformations } from '../models/client'\n\nconst personalMetaToPrefix = {\n [MetadataCategory.Personal]: 'you',\n [MetadataCategory.ChildPersonal]: 'child',\n [MetadataCategory.OtherPersonal]: 'other',\n}\n\n/**\n * This function extract PersonalInformations from data input object coming from workflow\n * @param data extracted from WorkflowData\n * @returns PersonalInformations of a patient\n */\nexport function identificationToPersonalInformations(\n data: any,\n category:\n | MetadataCategory.Personal\n | MetadataCategory.ChildPersonal\n | MetadataCategory.OtherPersonal\n): PersonalInformations {\n const prefix = personalMetaToPrefix[category]\n\n return {\n birthday: data[`${prefix}Birthday`],\n firstname: data[`${prefix}Firstname`],\n gender: data[`${prefix}Gender`],\n name: data[`${prefix}Name`],\n phone: data[`${prefix}Phone`],\n zip: data[`${prefix}Zip`],\n hid: data[`${prefix}HID`] ?? data[`${prefix}ID`], // This is done for backward compatibility (historically youID was used)\n pharmacy: data[`${prefix}Pharmacy`],\n address: data[`${prefix}Address`],\n }\n}\n\nexport function toActualObject(data: PopulatedWorkflowData) {\n const ret: any = {}\n\n Object.entries(data.fields).forEach(([key, field]) => {\n ret[key] = field.displayedAnswer ? field.displayedAnswer : field.answer\n })\n\n return ret\n}\n\n/**\n * This function update a PopulatedWorkflowData with PersonalInformations\n * @param infos the personal informations\n * @param data the PopulatedWorkflowData\n * @returns an updated PopulatedWorkflowData\n */\nexport function updatePersonalIntoPopulatedWorkflowData(\n infos: PersonalInformations,\n data: PopulatedWorkflowData,\n category:\n | MetadataCategory.Personal\n | MetadataCategory.ChildPersonal\n | MetadataCategory.OtherPersonal\n) {\n const prefix = personalMetaToPrefix[category]\n\n const ret = JSON.parse(JSON.stringify(data)) // deep copy PopulatedWorkflowData\n\n if (infos.birthday && ret.fields[`${prefix}Birthday`])\n ret.fields[`${prefix}Birthday`].answer = infos.birthday\n if (infos.firstname && ret.fields[`${prefix}Firstname`])\n ret.fields[`${prefix}Firstname`].answer = infos.firstname\n if (infos.gender && ret.fields[`${prefix}Gender`])\n ret.fields[`${prefix}Gender`].answer = infos.gender\n if (infos.name && ret.fields[`${prefix}Name`])\n ret.fields[`${prefix}Name`].answer = infos.name\n if (infos.phone && ret.fields[`${prefix}Phone`])\n ret.fields[`${prefix}Phone`].answer = infos.phone\n if (infos.zip && ret.fields[`${prefix}Zip`])\n ret.fields[`${prefix}Zip`].answer = infos.zip\n if (infos.hid) {\n if (ret.fields[`${prefix}HID`]) {\n ret.fields[`${prefix}HID`].answer = infos.hid\n } else if (ret.fields[`${prefix}ID`]) {\n // This is done for backward compatibility (historically youID was used)\n ret.fields[`${prefix}ID`].answer = infos.hid\n } else {\n // If does not exist create it\n ret.fields[`${prefix}HID`] = { kind: 'text', answer: infos.hid }\n }\n }\n\n return ret\n}\n\n/**\n * This function extract an ISO 3166-1 alpha-2 country and subdivision code from data input object coming from workflow\n * @param answers answers from the WorkflowData\n * @returns an ISO 3166 alpha-2 code or undefined\n */\nexport function extractISOLocalityForConsult(\n answers?: SelectedAnswersData\n): string | undefined {\n if (!answers) {\n return undefined\n }\n\n const arrAnswersWithLocality = answers\n .flatMap((currentAnswerPage) => {\n const arrCountryFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Country') !== -1\n )\n .flat()\n const arrProvinceFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Province') !== -1\n )\n .flat()\n const arrConsultLocalFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Locality') !== -1\n )\n .flat()\n //returning the actual selected values, skipping if their IDs are more complex than a string\n return [\n ...arrCountryFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ...arrProvinceFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ...arrConsultLocalFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ]\n })\n .filter((item) => item !== undefined)\n\n const arrSelectedLocality = arrAnswersWithLocality.filter(\n (currentSelectedLocality) =>\n currentSelectedLocality.startsWith('isoLocalityConsult')\n )\n if (!arrSelectedLocality || arrSelectedLocality.length === 0) {\n console.log('no locality found in ' + arrSelectedLocality)\n return undefined\n }\n //to allow enforcing of an order, we will allow the following pattern in the isoLocalityConsult field name\n // isoLocalityConsult-QC-CA and isoLocalityConsult_1-QC-CA\n // or generally: isoLocalityConsult-<isoValue> or isoLocalityConsult_<priority>-<isoValue>\n const allowedLocalityPatterns = /isoLocalityConsult(?:_(?<indexPriority>\\d*))?-(?<isoValue>[a-zA-Z0-9]{2}-[a-zA-Z0-9]{1,3})/\n const finalLocality = arrSelectedLocality.reduce<string | undefined>(\n (finalLocality, currentSelectedLocality) => {\n const extractedSelected = allowedLocalityPatterns.exec(\n currentSelectedLocality\n )\n const [, indexSelectedPriority, isoSelectedValue] =\n extractedSelected ?? []\n if (!finalLocality) {\n return isoSelectedValue\n }\n\n const extractedFinal = allowedLocalityPatterns.exec(finalLocality)\n const [, indexFinalPriority, isoFinalValue] = extractedFinal ?? []\n //we only keep the old value if there's priority used\n // and the new value is of lower priority\n if (\n !indexSelectedPriority ||\n (indexFinalPriority &&\n indexFinalPriority > indexSelectedPriority)\n ) {\n return isoFinalValue\n }\n\n return isoSelectedValue\n },\n undefined\n )\n\n console.log('Picking locality ' + finalLocality)\n return finalLocality\n}\n\nconst sessionPrivateKeyPrefix = 'sess-pkey'\nexport function sessionStorePrivateKeyName(id: string): string {\n return sessionPrivateKeyPrefix + id\n}\n","export class IncompleteAuthentication extends Error { }\nexport class MissingGrant extends Error { }\nexport class MissingGrantFilter extends Error { }\nexport class MissingLockbox extends Error { }\nexport class MissingLockboxOwner extends Error { }\nexport class AssociatedLockboxNotFound extends Error { }\nexport class WorkflowAnswersMissingError extends Error { }\n","import { getMany } from 'idb-keyval'\nimport { WorkflowAnswersMissingError } from '../models'\nimport {\n MetadataCategory,\n PopulatedWorkflowData,\n PopulatedWorkflowField,\n QuestionData,\n SelectedAnswerData,\n SelectedAnswersData,\n WorkflowData,\n WorkflowPageData,\n WorkflowUploadedImage,\n} from 'oro-sdk-apis'\n\nexport async function filterTriggeredAnsweredWithKind(\n workflowData: WorkflowData,\n kind:\n | 'text'\n | 'text-area'\n | 'text-select-group'\n | 'date'\n | 'number'\n | 'images'\n | 'images-alias'\n | 'body-parts'\n | 'pharmacy-picker'\n | 'online-pharmacy-picker'\n | 'hair-selector-women'\n | 'hair-selector-men'\n | 'hair-loss-stage'\n | 'hair-loss-frontal'\n): Promise<SelectedAnswerData[]> {\n if (!workflowData.selectedAnswers) throw WorkflowAnswersMissingError\n // Flattens the list of answered questions\n let flattenedAnswers = flattenSelectedAnswers(workflowData.selectedAnswers)\n // Generates a list of applicable questions\n let triggeredQuestionsWithKind = Object.fromEntries(\n workflowData.pages\n .map((a) => {\n return Object.entries(a.questions).filter(\n ([_, question]) => isTriggered(question.triggers || [], flattenedAnswers) && question.kind === kind\n )\n })\n .flat()\n )\n\n const samePageAnswers = workflowData.selectedAnswers.reduce((prev, cur) => {\n return { ...prev, ...cur }\n }, {})\n\n const res = Object.keys(triggeredQuestionsWithKind).map((questionFieldName) => {\n return samePageAnswers[questionFieldName]\n })\n\n return res\n}\n\n/**\n * Filters and Populates the `selectedAnswers` from the workflow by\n * Cross-referencing the `MetaCategory` of the answer's respective question\n * Populates the fields labels and values that are of radio, dropdown and checkbox types\n *\n * @param workflowData\n * @param category\n * @returns An array of record key, value pairs\n */\nexport async function getWorkflowDataByCategory(\n workflowData: WorkflowData,\n category: MetadataCategory\n): Promise<PopulatedWorkflowData> {\n if (!workflowData.selectedAnswers) throw WorkflowAnswersMissingError\n\n // Flattens the list of answered questions\n let flattenedAnswers = flattenSelectedAnswers(workflowData.selectedAnswers)\n // Generates a list of applicable questions\n let triggeredQuestions = Object.fromEntries(\n workflowData.pages\n .map((a) => {\n return Object.entries(a.questions).filter(([_, question]) =>\n isTriggered(question.triggers || [], flattenedAnswers)\n )\n })\n .flat()\n )\n\n const fields: Record<string, PopulatedWorkflowField> = {}\n\n // Generates the answers of the specified category and adds the appropriate values if any are missing\n return Promise.all(\n workflowData.selectedAnswers\n .map((e) => Object.entries(e))\n .flat()\n .filter(([k, v]) => triggeredQuestions[k] && triggeredQuestions[k]['metaCategory'] === category)\n .map(([k, v]) => {\n return populateWorkflowField(triggeredQuestions[k], v).then((populatedValue) => {\n fields[k] = populatedValue\n })\n })\n )\n .then(() => {\n const ret: PopulatedWorkflowData = {\n workflowCreatedAt: workflowData.createdAt,\n workflowId: workflowData.id,\n locale: workflowData.locale,\n fields,\n }\n return ret\n })\n .catch((err) => {\n console.error(`Error while extracting ${category} data from workflow`, err)\n throw err\n })\n}\n\nexport async function getImagesFromIndexDb(answer: SelectedAnswerData): Promise<WorkflowUploadedImage[]> {\n return await getMany<WorkflowUploadedImage>((answer as any[]).map((v) => v.id ?? v) as string[])\n}\n\n/**\n * (If applicable) Based on the question kind, and the answer type this function will add and replace the appropriate fields to the\n * field values if they are radio, dropdown and checkbox fields\n *\n *\n * @param question\n * @param answerValue\n * @returns\n */\nasync function populateWorkflowField(\n question: QuestionData,\n answerValue: SelectedAnswerData\n): Promise<PopulatedWorkflowField> {\n let answer: any\n let displayedAnswer: string | string[] | undefined = undefined\n switch (question.kind) {\n case 'text-select-group':\n if (question.answers) {\n displayedAnswer = `${answerValue[0]} ${question.answers[answerValue[1] as string].text}`\n }\n answer = answerValue\n break\n case 'radio':\n case 'radio-card':\n case 'select':\n if (question.answers) {\n displayedAnswer = question.answers[answerValue as string].text\n }\n\n answer = answerValue\n break\n case 'multiple':\n case 'checkbox-group':\n displayedAnswer = (answerValue as string[]).map((value) => {\n if (question.answers) {\n return question.answers[value].text\n }\n\n throw new WorkflowAnswersMissingError()\n })\n\n answer = answerValue\n break\n case 'images':\n answer = await getImagesFromIndexDb(answerValue).then((images) =>\n images.map((image) => {\n const { name, imageData } = image\n\n return { name, imageData }\n })\n )\n break\n default:\n answer = answerValue\n }\n\n return Promise.resolve({\n answer,\n displayedAnswer,\n kind: question.kind,\n })\n}\n\n/**\n * Determine if a question is triggered by some answers\n *\n * We use the following logical combinations of rules:\n *\n * #### Single string\n *\n * ```\n * // Required: rule1\n * rules: rule1\n * ```\n *\n * #### Array of strings (AND is applied between statements):\n *\n * ```\n * // Required: rule1 AND rule2\n * rules: [ rule1, rule2 ]\n * ```\n *\n * #### Array of arrays of strings (OR is applied between inner arrays. AND is applied between inner arrays statements)\n *\n * ```\n * // Required: rule1 OR rule2\n * rules: [\n * [ rule1 ],\n * [ rule2 ]\n * ]\n *\n * // Required: rule1 OR (rule2 AND rule3)\n * rules: [\n * [ rule1 ],\n * [ rule2, rule3 ]\n * ]\n *\n * // THIS IS FORBIDDEN\n * rules: [\n * rule1, // <-- THIS IS FORBIDDEN. Instead use [ rule1 ]\n * [ rule2, rule3 ]\n * ]\n * ```\n *\n * @param triggers the triggering rules\n * @param answers the answers to check againts triggering rules\n * @returns `true` if triggers are verified against ansers. Otherwise, returns `false`.\n * @throws an Error if triggers typing is wrong\n */\nexport function isTriggered(triggers: string[][] | string[] | string, answers: string[]): boolean {\n // is triggers contained in answers\n if (typeof triggers === 'string') {\n return answers.includes(triggers)\n }\n\n if (Array.isArray(triggers)) {\n // rule combination kind: rule1 OR (rule2 AND rule3)\n if (Array.isArray(triggers[0])) {\n return (triggers as string[][]).some((subSetTriggers) =>\n subSetTriggers.every((trigger) => answers.includes(trigger))\n )\n } else {\n // rule combination kind: rule1 AND rule2\n return (triggers as string[]).every((trigger) => answers.includes(trigger))\n }\n }\n\n throw Error('[isTriggered] triggers is not typed well')\n}\n\nexport function flattenSelectedAnswers(answers: SelectedAnswersData) {\n const linearAnswers: SelectedAnswerData[] = []\n\n for (const answer of answers) {\n linearAnswers.push(...Object.values(answer))\n }\n\n return linearAnswers.flat(1)\n}\n\n/**\n * This function helps you to get a valid workflow selectedAnswers structure\n * @param workflow the workflow data to use to initialize selectedAnswers\n * @param useDefault use workflow default values or not (this is used to avoid having unset values to appear in summaries)\n * @returns a valid selectedAnswers structure\n */\nexport function getInitialisedSelectedAnswers(workflow: WorkflowData, useDefault: boolean = true) {\n return workflow.pages.map((page) => {\n const ret: any = {}\n for (const [id, question] of Object.entries(page.questions)) {\n if (question.kind === 'body-parts') {\n ret[id] = useDefault ? [] : undefined\n } else {\n ret[id] = useDefault && question.defaultValue ? question.defaultValue : undefined\n }\n }\n return ret\n })\n}\n\nexport function fillWorkflowFromPopulatedWorkflow(workflow: WorkflowData, populatedWorkflow: PopulatedWorkflowData) {\n const filledWorkflow = JSON.parse(JSON.stringify(workflow))\n\n if (!filledWorkflow.selectedAnswers) {\n filledWorkflow.selectedAnswers = getInitialisedSelectedAnswers(filledWorkflow, false)\n }\n\n filledWorkflow.pages.forEach((page: WorkflowPageData, pageIdx: number) => {\n const ret: any = {}\n for (const [id] of Object.entries(page.questions)) {\n if (populatedWorkflow.fields[id]) {\n if (filledWorkflow.selectedAnswers)\n filledWorkflow.selectedAnswers[pageIdx][id] = populatedWorkflow.fields[id].answer as\n | string\n | string[]\n }\n }\n })\n\n return filledWorkflow\n}\n","import { Consult, ConsultRequest } from 'oro-sdk-apis'\nimport { OroClient } from '..'\n\n/**\n * Creates a consultation if one has not been created and fails to be retrieved by the payment intent\n * @param consult\n * @param oroClient\n * @returns the consult Uuid\n */\nexport async function getOrCreatePatientConsultationUuid(\n consult: ConsultRequest,\n oroClient: OroClient\n): Promise<Consult> {\n let payment = await oroClient.practiceClient.practiceGetPayment(\n consult.uuidPractice,\n consult.idStripeInvoiceOrPaymentIntent\n )\n if (payment && payment.uuidConsult) {\n return oroClient.consultClient.getConsultByUUID(payment.uuidConsult).catch((err) => {\n console.error('Error while retrieving consult', err)\n throw err\n })\n } else {\n return await oroClient.consultClient.consultCreate(consult).catch((err) => {\n console.error('Error while creating consult', err)\n throw err\n })\n }\n}\n","import {\n Consult,\n ConsultationImageMeta,\n ConsultationMeta,\n ConsultRequest,\n DocumentType,\n IdentityResponse,\n IndexKey,\n MedicalMeta,\n MedicalStatus,\n MetadataCategory,\n PersonalMeta,\n PopulatedWorkflowData,\n Practitioner,\n PreferenceMeta,\n RawConsultationMeta,\n Term,\n Terms,\n Uuid,\n VaultIndex,\n WorkflowData,\n} from 'oro-sdk-apis'\nimport {\n filterTriggeredAnsweredWithKind,\n getImagesFromIndexDb,\n getWorkflowDataByCategory,\n identificationToPersonalInformations,\n OroClient,\n RegisterPatientOutput,\n toActualObject,\n} from '..'\nimport { getOrCreatePatientConsultationUuid } from './consult'\n\nconst MAX_RETRIES = 15\n\n/**\n * Completes a registration for a user retrying the complete flow a maximum of 15 times\n *\n * @description The order of importance when registering:\n * Creates a consultation if none exist\n * Retrieves or create's a lockbox if none exist\n * Grants the lockbox (if new) to all practitioners in the practice\n * Stores or fetches the patient data (without images)\n * Indexes the lockbox to the consult for all practitioners (done after inserting since index can be rebuilt from grants)\n * Stores the image data - done last since the majority of failure cases occur here\n * Creates the recovery payloads if they don't exist\n *\n * @param patientUuid\n * @param consultRequest\n * @param workflow\n * @param oroClient\n * @param masterKey\n * @param recoveryQA\n * @param indexSearch create search index for the consultation if true\n * @param onProgress callback that is called whenever a new step of patient registration is executed. Note: progress ranges from 0 to 1, and descriptionKey is a description of the progress as a key so the app would use it to translate the description\n * @returns the successful registration\n */\nexport async function registerPatient(\n patientUuid: Uuid,\n consultRequest: ConsultRequest,\n workflow: WorkflowData,\n oroClient: OroClient,\n masterKey?: Uuid,\n recoveryQA?: {\n recoverySecurityQuestions: string[]\n recoverySecurityAnswers: string[]\n },\n indexSearch: boolean = true,\n onProgress?: (\n progress: number,\n descriptionKey: string,\n extraInfo?: { storedImagesNum?: number; totalImagesNum?: number }\n ) => void\n): Promise<RegisterPatientOutput> {\n let consult: Consult | undefined = undefined\n let lockboxUuid: Uuid | undefined = undefined\n let practitionerAdmin: Uuid | undefined = undefined\n let retry = MAX_RETRIES\n let identity: IdentityResponse | undefined = undefined\n let errorsThrown: Error[] = []\n const stepsTotalNum = 9\n let currentStep: number\n\n for (; retry > 0; retry--) {\n try {\n currentStep = 0\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'retrieve_practitioners')\n\n // Wait a bit each retry (we also want the first one to wait)\n await new Promise((resolve) => setTimeout(resolve, 2000))\n\n // Retrieving practitioners\n if (!practitionerAdmin)\n practitionerAdmin = (await oroClient.practiceClient.practiceGetFromUuid(consultRequest.uuidPractice))\n .uuidAdmin\n\n let practitioners: Practitioner[] = await oroClient.practiceClient\n .practiceGetPractitioners(consultRequest.uuidPractice)\n .catch((err) => {\n console.log(`Error retrieving practitioners`, err)\n return []\n })\n\n // Creating consult\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'create_consult')\n\n if (!consult) {\n consult = await getOrCreatePatientConsultationUuid(consultRequest, oroClient)\n }\n\n // Creating lockbox\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'create_lockbox')\n\n if (!lockboxUuid) lockboxUuid = await getOrCreatePatientLockbox(oroClient)\n\n if (!identity) identity = await oroClient.guardClient.identityGet(patientUuid)\n\n await oroClient.grantLockbox(practitionerAdmin, lockboxUuid).catch((err) => {\n console.error(`Error while granting lockbox to practitioner admin ${practitionerAdmin}`, err)\n // if we cannot grant to the admin, then the registration will fail\n errorsThrown.push(err)\n })\n\n // Patient Grant to practice\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'grant_patient')\n\n let grantPromises = practitioners\n .filter((practitioner) => practitioner.uuid !== practitionerAdmin)\n .map(async (practitioner) => {\n return oroClient.grantLockbox(practitioner.uuid, lockboxUuid!).catch((err) => {\n console.error(`Error while granting lockbox to practitioner`, err)\n // Acceptable to continue as admin has already been granted, but we should still retry until the last retry remains\n if (retry <= 1) return\n errorsThrown.push(err)\n })\n })\n\n const consultIndex: VaultIndex = {\n [IndexKey.ConsultationLockbox]: [\n {\n grant: {\n lockboxUuid,\n lockboxOwnerUuid: patientUuid,\n },\n consultationId: consult.uuid,\n },\n ],\n }\n\n // the index will identify in which lockbox a consultation resides\n let consultIndexPromises = practitioners.map(async (practitioner) => {\n return oroClient.vaultIndexAdd(consultIndex, practitioner.uuid).catch((err) => {\n console.error(\n `[SDK: registration] Error while adding to the practitioner's index ${practitioner.uuid}`,\n err\n )\n // Acceptable to continue as the index can be rebuilt, but we should still retry until the last retry remains\n if (retry <= 1) return\n else errorsThrown.push(err)\n })\n })\n\n await storeImageAliases(\n consult.uuid,\n lockboxUuid,\n workflow,\n oroClient,\n onProgress\n ? {\n onProgress,\n currentStep,\n stepsTotalNum,\n }\n : undefined\n ).catch((err) => {\n console.error('[SDK: registration] Some errors happened during image upload', err)\n // Acceptable to continue as images can be requested during the consultation, but we should still retry until the last retry remains\n if (retry <= 1) return\n else errorsThrown.push(err)\n })\n ++currentStep\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'store_patient_data')\n\n await storePatientData(\n consult.uuid,\n consultRequest.isoLanguageRequired,\n lockboxUuid,\n workflow,\n oroClient\n ).catch((err) => {\n console.error('[SDK: registration] Some errors happened during patient data upload', err)\n errorsThrown.push(err)\n })\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'set_masterkey')\n\n if (masterKey && !identity?.recoveryMasterKey) {\n // generate and store recovery payload and updates the identity\n identity = await oroClient.updateMasterKey(patientUuid, masterKey, lockboxUuid).catch((err) => {\n console.error(`[SDK: registration] Error while updating master key`, err)\n /// it's acceptable to continue registration (return old identity)\n if (retry <= 1) return\n errorsThrown.push(err)\n return identity\n })\n } else {\n // we did not set the master key so we do not return it\n masterKey = undefined\n }\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'set_security_questions')\n\n if (recoveryQA && !identity?.recoverySecurityQuestions)\n // Patient security question recovery threshold is 2 answers and updates the identity\n identity = await oroClient\n .updateSecurityQuestions(\n patientUuid,\n recoveryQA.recoverySecurityQuestions,\n recoveryQA.recoverySecurityAnswers,\n 2\n )\n .catch((err) => {\n console.error(`[SDK: registration] Error while updating security questions`, err)\n /// it's acceptable to continue registration (return old identity)\n if (retry <= 1) return\n errorsThrown.push(err)\n return identity\n })\n\n await Promise.all([...grantPromises, ...consultIndexPromises])\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'search_indexing')\n\n if (indexSearch) {\n await buildConsultSearchIndex(consult, workflow, oroClient).catch((err) => {\n console.error(\n '[SDK: registration] personal information not found or another error occured during search indexing',\n err\n )\n if (retry <= 1) return // this statement is to avoid failing the registration due to the failure in search indexing the consult, this practically implements a soft retry\n errorsThrown.push(err)\n })\n }\n\n if (errorsThrown.length > 0) throw errorsThrown\n\n // Deem the consultation as ready\n await oroClient.consultClient.updateConsultByUUID(consult.uuid, {\n statusMedical: MedicalStatus.New,\n })\n\n // if we got through the complete flow, the registration succeeded\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'success')\n\n break\n } catch (err) {\n console.error(`[SDK] Error occured during registration: ${err}, retrying... Retries remaining: ${retry}`)\n errorsThrown = []\n continue\n }\n }\n\n if (retry <= 0) {\n console.error('[SDK] registration failed: MAX_RETRIES reached')\n throw 'RegistrationFailed'\n }\n\n console.log('Successfully Registered')\n await oroClient.cleanIndex()\n return {\n masterKey,\n consultationId: consult!.uuid,\n lockboxUuid: lockboxUuid!,\n }\n}\n\n/**\n * Creates a new lockbox for the patient if they do not have any, otherwise, use the first (and only one)\n * @param oroClient\n * @returns the lockbox Uuid\n */\nasync function getOrCreatePatientLockbox(oroClient: OroClient): Promise<Uuid> {\n let grants = await oroClient.getGrants()\n if (grants.length > 0) {\n console.log('The grant has already been created, skipping lockbox create step')\n return grants[0].lockboxUuid!\n } else {\n let lockboxResponse = await oroClient.vaultClient.lockboxCreate().catch((err) => {\n console.error('Error while creating lockbox', err)\n throw err\n })\n // Since the creation of a lockbox will change the scope of a user, we will force refresh the tokens\n let tokens = await oroClient.guardClient.authRefresh()\n await oroClient.guardClient.setTokens({ accessToken: tokens.accessToken, refreshToken: tokens.refreshToken })\n await oroClient.guardClient.whoAmI(true)\n\n return lockboxResponse.lockboxUuid\n }\n}\n\n/**\n * Store all patient related information into his/her lockbox\n * @param consultationId The consultation id\n * @param isoLanguage the prefered language of communication (ISO 639-3 https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes)\n * @param lockboxUuid the lockbox uuid to store data in\n * @param workflow the workflow used to extract informations\n * @param oroClient an oroClient instance\n * @returns\n */\nasync function storePatientData(\n consultationId: Uuid,\n isoLanguage: string,\n lockboxUuid: Uuid,\n workflow: WorkflowData,\n oroClient: OroClient\n): Promise<(Uuid | void)[]> {\n // Create and store registration data\n return Promise.all([\n // Storing Raw data first\n oroClient.getOrInsertJsonData<RawConsultationMeta>(\n lockboxUuid,\n workflow,\n {\n category: MetadataCategory.Raw,\n contentType: 'application/json',\n consultationId,\n },\n {}\n ),\n getWorkflowDataByCategory(workflow, MetadataCategory.Consultation).then((data) =>\n oroClient.getOrInsertJsonData<ConsultationMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationId, // TODO: deprecated. Will finally only be in privateMetadata\n },\n { consultationId },\n { withNotification: true },\n // the only data that needs to include an email notification\n )\n ),\n getWorkflowDataByCategory(workflow, MetadataCategory.Medical).then((data) =>\n oroClient.getOrInsertJsonData<MedicalMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Medical,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId!],\n },\n {}\n )\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.Personal,\n oroClient\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.ChildPersonal,\n oroClient\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.OtherPersonal,\n oroClient\n ),\n oroClient.getOrInsertJsonData<PreferenceMeta>(\n lockboxUuid,\n { isoLanguage },\n {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n },\n {}\n ),\n ]).then((dataUuids) => dataUuids.flat())\n}\n\nasync function storeImageAliases(\n consultationId: Uuid,\n lockboxUuid: Uuid,\n workflow: WorkflowData,\n oroClient: OroClient,\n progress?: {\n currentStep: number\n stepsTotalNum: number\n onProgress: (\n progress: number,\n descriptionKey: string,\n extraInfo?: { storedImagesNum?: number; totalImagesNum?: number }\n ) => void\n }\n): Promise<(Uuid | void)[]> {\n const images = await getImagesFromIndexDb((await filterTriggeredAnsweredWithKind(workflow, 'images-alias')).flat())\n\n const nonNullImages = images.filter((img) => !!img)\n\n if (images.length !== nonNullImages.length) {\n console.error('[SDK] Some images have not been found, they have been skipped.')\n }\n\n let storedImagesNum = 0\n let totalImagesNum = nonNullImages.length\n if (progress)\n progress.onProgress(progress.currentStep / progress.stepsTotalNum, 'store_images', {\n storedImagesNum,\n totalImagesNum,\n })\n\n let promises = nonNullImages.map((image) => {\n return oroClient\n .getOrInsertJsonData<ConsultationImageMeta>(\n lockboxUuid,\n image,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.ImageAlias,\n consultationId,\n idbId: image.idbId as string,\n },\n {}\n )\n .then(() => {\n if (progress) {\n ++storedImagesNum\n let progressStepValue =\n Math.round(\n ((progress.currentStep + 1) / progress.stepsTotalNum -\n progress.currentStep / progress.stepsTotalNum) *\n 100\n ) / 100\n progress.onProgress(\n progress.currentStep / progress.stepsTotalNum +\n progressStepValue * (storedImagesNum / totalImagesNum),\n 'store_images',\n {\n storedImagesNum,\n totalImagesNum,\n }\n )\n }\n })\n })\n return Promise.all(promises)\n}\n\n/**\n * Extracts the workflow MetadataCategory for Personal, ChildPersonal and OtherPersonal\n * then stores it in the vault\n *\n * @param workflow\n * @param lockboxUuid\n * @param category\n * @returns The data uuid\n */\nexport async function extractAndStorePersonalWorkflowData(\n workflow: WorkflowData,\n lockboxUuid: Uuid,\n consultationId: Uuid,\n category: MetadataCategory.Personal | MetadataCategory.ChildPersonal | MetadataCategory.OtherPersonal,\n oroClient: OroClient\n): Promise<Uuid | void> {\n return getWorkflowDataByCategory(workflow, category as unknown as MetadataCategory).then((data) => {\n if (Object.keys(data.fields).length === 0) return\n return oroClient.getOrInsertJsonData<PersonalMeta>(\n lockboxUuid,\n data,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId],\n },\n {}\n )\n })\n}\n\n/**\n * Given workflow data, it populates it with Personal, ChildPersonal, and OtherPersonal workflow data\n * @param workflow\n */\nexport async function extractPersonalInfoFromWorkflowData(workflow: WorkflowData): Promise<{\n personalInfoPopulatedWfData: PopulatedWorkflowData\n childPersonalInfoPopulatedWfData: PopulatedWorkflowData\n otherPersonalInfoPopulatedWfData: PopulatedWorkflowData\n}> {\n return Promise.all([\n getWorkflowDataByCategory(workflow, MetadataCategory.Personal),\n getWorkflowDataByCategory(workflow, MetadataCategory.ChildPersonal),\n getWorkflowDataByCategory(workflow, MetadataCategory.OtherPersonal),\n ]).then(([personalInfoPopulatedWfData, childPersonalInfoPopulatedWfData, otherPersonalInfoPopulatedWfData]) => {\n return {\n personalInfoPopulatedWfData,\n childPersonalInfoPopulatedWfData,\n otherPersonalInfoPopulatedWfData,\n }\n })\n}\n\n/**\n * Creates the search index for the first name, last name, and the short id of the given consultation\n * @param consult the consultation to be search indexed\n * @param workflow the workflow data\n * @param oroClient\n */\nexport async function buildConsultSearchIndex(consult: Consult, workflow: WorkflowData, oroClient: OroClient) {\n let terms: Terms = [\n <Term>{\n kind: 'consult-shortid',\n value: consult.shortId,\n },\n ]\n\n const { personalInfoPopulatedWfData, childPersonalInfoPopulatedWfData, otherPersonalInfoPopulatedWfData } =\n await extractPersonalInfoFromWorkflowData(workflow)\n\n const personalInfo = identificationToPersonalInformations(\n toActualObject(personalInfoPopulatedWfData),\n MetadataCategory.Personal\n )\n const childPersonalInfo = identificationToPersonalInformations(\n toActualObject(childPersonalInfoPopulatedWfData),\n MetadataCategory.ChildPersonal\n )\n const otherPersonalInfo = identificationToPersonalInformations(\n toActualObject(otherPersonalInfoPopulatedWfData),\n MetadataCategory.OtherPersonal\n )\n\n terms.push(\n <Term>{\n kind: 'first-name',\n value: personalInfo.firstname,\n },\n <Term>{\n kind: 'last-name',\n value: personalInfo.name,\n }\n )\n\n if (childPersonalInfo.firstname && childPersonalInfo.name) {\n terms.push(\n <Term>{\n kind: 'first-name',\n value: childPersonalInfo.firstname,\n },\n <Term>{\n kind: 'last-name',\n value: childPersonalInfo.name,\n }\n )\n }\n\n if (otherPersonalInfo.firstname && otherPersonalInfo.name) {\n terms.push(\n <Term>{\n kind: 'first-name',\n value: otherPersonalInfo.firstname,\n },\n <Term>{\n kind: 'last-name',\n value: otherPersonalInfo.name,\n }\n )\n }\n\n await oroClient.searchClient.index(consult.uuid, terms)\n}\n","import { CryptoRSA, uuidParse} from \"oro-toolbox\"\nimport { EncryptedIndexEntry, Grant, IndexConsultLockbox } from \"oro-sdk-apis\"\n\n/**\n * Decrypts and returns the encrypted grants\n * If something went wrong during decryption, that grant will be removed from the list\n *\n * @param encryptedGrants: an array of encrypted grants\n * @param rsaKey: the rsa key used to decrypt the encrypted grants\n * @returns an array of grants\n */\nexport function decryptGrants(encryptedGrants: Grant[], rsaKey: CryptoRSA): Grant[] {\n return encryptedGrants\n .map(grant => {\n if (grant.encryptedLockbox && !grant.lockboxUuid) {\n try {\n grant.lockboxUuid = uuidParse(\n rsaKey.base64DecryptToBytes(grant.encryptedLockbox)\n )\n } catch (e) {\n console.error('[sdk:index] The grant could not be decrypted or was not a valid UUID: ', e)\n }\n }\n return grant\n })\n .filter(grant => grant.lockboxUuid)\n}\n\n/**\n * Decrypts the encrypted consult lockboxes and returns their grants\n * If something went wrong during decryption, that grant will be removed from the list\n *\n * @param encryptedConsultLockboxes: an array of encrypted entries\n * @param rsaKey: the rsa key used to decrypt the encrypted entries\n * @returns an array of grants\n */\nexport function decryptConsultLockboxGrants(encryptedConsultLockboxes: EncryptedIndexEntry[], rsaKey: CryptoRSA): Grant[] {\n return encryptedConsultLockboxes\n .map(encryptedConsultLockboxes => {\n try {\n return [true, (rsaKey.base64DecryptToJson(\n encryptedConsultLockboxes.encryptedIndexEntry\n ) as IndexConsultLockbox).grant]\n } catch(e) {\n console.error('[sdk:index] The consult lockbox grant could not be decrypted: ', e)\n return [false, undefined] // if decryption fails, we want to ignore the grant but not fail the call\n }\n })\n .filter(grantsTuple => grantsTuple[0])\n .map(grantTuples => grantTuples[1] as Grant)\n}","import {\n Consult,\n ConsultRequest,\n DocumentType,\n MedicalStatus,\n MetadataCategory,\n PlaceData,\n SelectedAnswersData,\n Uuid,\n WorkflowData,\n} from 'oro-sdk-apis'\nimport { OroClient } from '..'\nimport { getOrCreatePatientConsultationUuid } from './consult'\n\nconst MAX_RETRIES = 15\n/**\n * Placeholder while the workflow interpreter for the refill flows is complete\n *\n * Creates a fake workflow in which the workflow data will reside\n *\n * @param isTreatmentWorking the value from the `is treatment working` question\n * @param hasSideEffects the value from the `does the treatment have side effects` question\n * @param deliveryAddress the provided delivery address\n * @param pharmacy\n * @returns a workflow\n */\nexport function getRefillAnswersAsWorkflow(\n isTreatmentWorking: string,\n hasSideEffects: string,\n deliveryAddress?: string,\n pharmacy?: PlaceData\n): WorkflowData {\n let selectedAnswers: SelectedAnswersData = [\n {\n ['isTreatmentWorking']: isTreatmentWorking,\n },\n {\n ['hasSideEffects']: hasSideEffects,\n },\n ]\n\n if (deliveryAddress) selectedAnswers.push({ ['deliveryAddress']: deliveryAddress })\n if (pharmacy) selectedAnswers.push({ ['pharmacy']: JSON.stringify(pharmacy) })\n\n return {\n id: '32573a20-6f1d-49be-9ad3-b87c58074979',\n createdAt: '2022-10-03T00:00:00.000Z',\n culDeSacs: [],\n hidePlanRules: [],\n pages: [\n {\n title: 'Prescription Refill',\n groups: [\n {\n type: 'field-group',\n fieldsAndGroups: [\n {\n type: 'field',\n id: 'isTreatmentWorking',\n },\n {\n type: 'field',\n id: 'hasSideEffects',\n },\n {\n type: 'field',\n id: 'youPharmacy',\n },\n {\n type: 'field',\n id: 'youAddress',\n },\n ],\n },\n ],\n questions: {\n isTreatmentWorking: {\n label: 'Is the treatment working for you?',\n kind: 'radio',\n inline: true,\n inlineLabel: false,\n metaCategory: MetadataCategory.Refill,\n answers: {\n '73bec6eb-0310-4787-af3c-ac9c291737b2': {\n text: 'Yes',\n },\n 'e193951f-986f-4db3-bede-903045a1804a': {\n text: 'No',\n },\n },\n },\n hasSideEffects: {\n label: 'Are there any side effects',\n kind: 'radio',\n inline: true,\n inlineLabel: false,\n metaCategory: MetadataCategory.Refill,\n answers: {\n '1b87ad22-d316-4fac-9c7f-8f4ccb841aed': {\n text: 'Yes',\n },\n 'ab7f5a41-c351-4f5d-a568-e38f9f200e9a': {\n text: 'No',\n },\n },\n },\n youPharmacy: {\n kind: 'online-pharmacy-picker',\n label: 'Which pharmacy do you want the prescription sent to?',\n metaCategory: MetadataCategory.Refill,\n minorLabel: ' (Optional)',\n summaryLabel: 'Your pharmacy',\n },\n youAddress: {\n kind: 'place-address',\n label: 'Address',\n metaCategory: MetadataCategory.Refill,\n },\n },\n },\n ],\n locale: 'en',\n selectedAnswers,\n }\n}\n\n/**\n * Complete refill flow, creates a consult, stores refill data and updates consultation status\n * @param consultRequest\n * @param populatedRefillWorkflow the refill workflow data\n * @param oroClient\n */\nexport async function createRefill(\n consultRequest: ConsultRequest,\n populatedRefillWorkflow: WorkflowData,\n oroClient: OroClient\n) {\n let retry = MAX_RETRIES\n let errorsThrown: Error[] = []\n\n let newConsult: Consult | undefined\n let lockboxUuid: Uuid | undefined\n\n for (; retry > 0; retry--) {\n try {\n if (!newConsult) newConsult = await getOrCreatePatientConsultationUuid(consultRequest, oroClient)\n\n if (!lockboxUuid) lockboxUuid = (await oroClient.getGrants())[0].lockboxUuid\n\n await oroClient\n .getOrInsertJsonData(\n lockboxUuid!,\n populatedRefillWorkflow,\n {\n category: MetadataCategory.Refill,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [newConsult.uuid],\n },\n {},\n { withNotification: true }\n )\n .catch((err) => {\n console.error('[SDK: prescription refill] Some errors happened during refill data upload', err)\n errorsThrown.push(err)\n })\n\n if (errorsThrown.length > 0) throw errorsThrown\n await oroClient.consultClient.updateConsultByUUID(newConsult.uuid, {\n statusMedical: MedicalStatus.New,\n })\n } catch (err) {\n console.error(`[SDK] Error occured during refill: ${err}, retrying... Retries remaining: ${retry}`)\n errorsThrown = []\n continue\n }\n }\n}\n","import { IndexKey, Grant, IndexConsultLockbox, MetadataCategory, VaultIndex } from 'oro-sdk-apis'\nimport { OroClient, Uuid } from '..'\n\n/**\n * @name filterGrantsWithLockboxMetadata\n * @description searches for the existance of a consult uuid in each granted lockbox\n * @param oroClient\n * @param filter: the consult uuid\n * @returns the grants containing the consult uuid\n */\nexport async function filterGrantsWithLockboxMetadata(\n oroClient: OroClient,\n filter: { consultationId: Uuid },\n): Promise<Grant[]> {\n let grants = await oroClient.getGrants()\n let filteredGrants = []\n for (let grant of grants) {\n // Fetches in each lockbox the existance of a given consult id\n let consultationIdExistsInMetadata = await oroClient.vaultClient.lockboxMetadataGet(grant.lockboxUuid!, ['consultationId'], [], {\n category: MetadataCategory.Consultation,\n consultationId: filter.consultationId\n })\n // If there are entries in the metadata, it means that the consult exists in the lockbox\n if (consultationIdExistsInMetadata[0].length >= 0)\n filteredGrants.push(grant)\n }\n\n return filteredGrants\n}\n","import {\n AllRoleType,\n AuthTokenRequest,\n Consult,\n ConsultRequest,\n ConsultService,\n DataCreateResponse,\n DiagnosisService,\n Document,\n DocumentType,\n EncryptedIndexEntry,\n EncryptedVaultIndex,\n Grant,\n GuardService,\n IdentityCreateRequest,\n IdentityResponse,\n IndexConsultLockbox,\n IndexKey,\n LocalizedData,\n LockboxDataRequest,\n LockboxGrantRequest,\n LockboxManifest,\n ManifestEntry,\n Meta,\n Metadata,\n MetadataCategory,\n OtherRoleType,\n PersonalMeta,\n PopulatedWorkflowData,\n Practice,\n PracticeService,\n PractitionnerRoleType,\n PreferenceMeta,\n RecoveryMeta,\n RoleBasedScopes,\n SearchService,\n SecretShard,\n TellerService,\n TokenData,\n TosAndCpAcceptanceRequest,\n Uuid,\n VaultIndex,\n VaultService,\n WorkflowData,\n WorkflowService,\n} from 'oro-sdk-apis'\nimport * as OroToolbox from 'oro-toolbox'\nimport { CryptoRSA } from 'oro-toolbox'\nimport {\n createRefill,\n decryptConsultLockboxGrants,\n decryptGrants,\n registerPatient,\n sessionStorePrivateKeyName,\n} from './helpers'\nimport {\n AssociatedLockboxNotFound,\n IncompleteAuthentication,\n LocalEncryptedData,\n MissingGrant,\n MissingGrantFilter,\n MissingLockbox,\n MissingLockboxOwner,\n RecoveryData,\n RegisterPatientOutput,\n UserPreference,\n} from './models'\nimport { filterGrantsWithLockboxMetadata } from './sdk-revision'\n\nexport class OroClient {\n private rsa?: CryptoRSA\n private secrets: {\n lockboxUuid: string\n cryptor: OroToolbox.CryptoChaCha\n }[] = []\n private cachedMetadataGrants: {\n [filter: string]: Grant[]\n } = {}\n\n private cachedManifest: {\n [filter: string]: ManifestEntry[]\n } = {}\n\n private vaultIndex?: VaultIndex\n\n constructor(\n private toolbox: typeof OroToolbox,\n public tellerClient: TellerService,\n public vaultClient: VaultService,\n public guardClient: GuardService,\n public searchClient: SearchService,\n public practiceClient: PracticeService,\n public consultClient: ConsultService,\n public workflowClient: WorkflowService,\n public diagnosisClient: DiagnosisService,\n private authenticationCallback?: (err: Error) => void\n ) { }\n\n /**\n * clears the vaultIndex and cached metadata grants\n */\n public async cleanIndex() {\n this.cachedMetadataGrants = {}\n this.cachedManifest = {}\n }\n\n /**\n * Generates an RSA key pair and password payload (rsa private key encrypted with the password)\n * Calls Guard to sign up with the email address, password, practice, legal and token data\n *\n * @param email\n * @param password\n * @param practice\n * @param legal\n * @param tokenData\n * @returns\n */\n public async signUp(\n email: string,\n password: string,\n practice: Practice,\n tosAndCpAcceptance: TosAndCpAcceptanceRequest,\n tokenData?: TokenData,\n subscription?: boolean,\n skipEmailValidation?: boolean\n ): Promise<IdentityResponse> {\n this.rsa = new CryptoRSA()\n const privateKey = this.rsa.private()\n\n const symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(password)\n const recoveryPassword = symmetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n\n const hashedPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(password))\n\n const emailConfirmed = !!skipEmailValidation\n\n const signupRequest: IdentityCreateRequest = {\n practiceUuid: practice.uuid,\n email: email.toLowerCase(),\n emailConfirmed,\n password: hashedPassword,\n publicKey: this.toolbox.encodeToBase64(this.rsa.public()),\n recoveryPassword,\n tosAndCpAcceptance,\n tokenData,\n subscription,\n }\n\n const identity = await this.guardClient.identityCreate(signupRequest)\n\n if (identity.recoveryLogin) {\n //Ensure we can recover from a page reload\n let symetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(identity.recoveryLogin)\n sessionStorage.setItem(\n sessionStorePrivateKeyName(identity.id),\n symetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n )\n }\n\n return identity\n }\n\n /**\n * Parse the given accessToken claims by calling guard whoami and update theidentity to set it's emailConfirmed flag\n * @param accessToken\n * @returns The identity related to confirmedEmail\n */\n public async confirmEmail(accessToken: string): Promise<IdentityResponse> {\n this.guardClient.setTokens({ accessToken })\n const claims = await this.guardClient.whoAmI()\n return this.guardClient.identityUpdate(claims.sub, {\n emailConfirmed: true,\n })\n }\n\n /**\n * Calls Guard to sign in with the email address, password and one time password (if MFA is enabled)\n * Then recover's the rsa private key from the recovery payload\n *\n * @param practiceUuid\n * @param email\n * @param password\n * @param otp\n * @returns the user identity\n */\n public async signIn(practiceUuid: Uuid, email: string, password: string, otp?: string): Promise<IdentityResponse> {\n const hashedPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(password))\n const tokenRequest: AuthTokenRequest = {\n practiceUuid,\n email: email.toLowerCase(),\n password: hashedPassword,\n otp,\n }\n\n await this.guardClient.authToken(tokenRequest)\n const userUuid = (await this.guardClient.whoAmI()).sub\n\n // Updates the rsa key to the one generated on the backend\n await this.recoverPrivateKeyFromPassword(userUuid, password)\n return await this.guardClient.identityGet(userUuid)\n }\n\n /**\n * Will attempt to recover an existing login session and set back\n * the private key in scope\n */\n public async resumeSession() {\n const id = (await this.guardClient.whoAmI()).sub\n const recoveryPayload = sessionStorage.getItem(sessionStorePrivateKeyName(id))\n const recoveryKey = (await this.guardClient.identityGet(id)).recoveryLogin\n\n if (!recoveryKey || !recoveryPayload) throw IncompleteAuthentication\n\n const symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(recoveryKey)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * This function let's you encrypt locally an Object\n * @param value the Object to encrypt\n * @returns a LocalEncryptedData Object\n * @throws IncompleteAuthentication if rsa is not set\n * @calls authenticationCallback if rsa is not set\n */\n public localEncryptToJsonPayload(value: any): LocalEncryptedData {\n if (!this.rsa) {\n if (this.authenticationCallback) {\n this.authenticationCallback(new IncompleteAuthentication())\n }\n\n throw new IncompleteAuthentication()\n }\n\n const chaChaKey = new this.toolbox.CryptoChaCha()\n\n const encryptedData = chaChaKey.jsonEncryptToBase64Payload(value)\n const encryptedKey = this.toolbox.encodeToBase64(this.rsa.encryptToBytes(chaChaKey.key()))\n\n return { encryptedData, encryptedKey }\n }\n\n /**\n * This function let's you decrypt a LocalEncryptedData object\n * @param value a LocalEncryptedData object\n * @returns a decrypted Object\n * @throws IncompleteAuthentication if rsa is not set\n * @calls authenticationCallback if rsa is not set\n */\n public localDecryptJsonPayload({ encryptedKey, encryptedData }: LocalEncryptedData): any {\n if (!this.rsa) {\n if (this.authenticationCallback) {\n this.authenticationCallback(new IncompleteAuthentication())\n }\n\n throw new IncompleteAuthentication()\n }\n\n const chaChaKey = this.rsa.base64DecryptToBytes(encryptedKey)\n const decryptedData = this.toolbox.CryptoChaCha.fromKey(chaChaKey).base64PayloadDecryptToJson(encryptedData)\n\n return decryptedData\n }\n\n /**\n * Effectively kills your \"session\"\n */\n public async signOut() {\n this.rsa = undefined\n this.secrets = []\n this.guardClient.setTokens({\n accessToken: undefined,\n refreshToken: undefined,\n })\n await this.guardClient.authLogout()\n }\n\n /**\n * @name registerPatient\n * @description The complete flow to register a patient\n *\n * Steps:\n * 1. Create a consult (checks if payment has been done)\n * 2. Creates a lockbox\n * 3. Grants lockbox access to all practice personnel\n * 4. Creates secure identification, medical, onboarding data\n * 5. Generates and stores the rsa key pair and recovery payloads\n *\n * @param patientUuid\n * @param consult\n * @param workflow\n * @param recoveryQA\n * @param indexSearch create search index for the consultation if true\n * @param onProgress callback that is called whenever a new step of patient registration is executed. Note: progress ranges from 0 to 1, and descriptionKey is a description of the progress as a key so the app would use it to translate the description\n * @returns\n */\n public async registerPatient(\n patientUuid: Uuid,\n consult: ConsultRequest,\n workflow: WorkflowData,\n recoveryQA?: {\n recoverySecurityQuestions: string[]\n recoverySecurityAnswers: string[]\n },\n indexSearch: boolean = true,\n onProgress?: (progress: number, descriptionKey: string) => void\n ): Promise<RegisterPatientOutput> {\n if (!this.rsa) throw IncompleteAuthentication\n return registerPatient(\n patientUuid,\n consult,\n workflow,\n this,\n this.toolbox.uuid(),\n recoveryQA,\n indexSearch,\n onProgress\n )\n }\n\n /**\n * Creates and stores all relevant refill data\n * - New consultation is created\n * - Stores refill workflow data in the lockbox\n * - Updates the consult to new\n *\n * @param consult\n * @param populatedRefillWorkflow\n * @returns\n */\n public async createRefill(consult: ConsultRequest, populatedRefillWorkflow: WorkflowData): Promise<void> {\n if (!this.rsa) throw IncompleteAuthentication\n return createRefill(consult, populatedRefillWorkflow, this)\n }\n\n /**\n * Fetches all grants, and consultations that exist in each lockbox\n * Then updates the index for the current user with the lockbox consult relationship\n */\n public async forceUpdateIndexEntries() {\n let grants = await this.getGrants()\n\n let indexConsultLockbox: IndexConsultLockbox[] = await Promise.all(\n grants.map(\n async (grant: Grant) =>\n await this.vaultClient\n .lockboxMetadataGet(\n grant.lockboxUuid!,\n ['consultationId'],\n [],\n { category: MetadataCategory.Consultation },\n grant.lockboxOwnerUuid\n )\n .then((consults) => {\n try {\n return consults[0].map((consult: any) => {\n return {\n ...consult,\n grant: {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid,\n },\n }\n })\n } catch (e) {\n // No consultations in lockbox or index could not be created\n return []\n }\n })\n .catch(() => [])\n )\n ).then((consults) => consults.flat())\n this.vaultIndexAdd({\n [IndexKey.Consultation]: indexConsultLockbox,\n })\n .then(() => alert('The Index was successfully updated!'))\n .catch(() => console.error('The index failed to update!'))\n }\n\n /**\n * Generates, encrypts and adds entries to vault index for a given index owner\n *\n * @param entries\n * @param indexOwnerUuid\n */\n public async vaultIndexAdd(entries: VaultIndex, indexOwnerUuid?: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let rsaPub: Uint8Array\n if (indexOwnerUuid) {\n let base64IndexOwnerPubKey = (await this.guardClient.identityGet(indexOwnerUuid)).publicKey\n rsaPub = this.toolbox.decodeFromBase64(base64IndexOwnerPubKey)\n } else {\n rsaPub = this.rsa.public()\n }\n\n let encryptedIndex: EncryptedVaultIndex = {}\n\n for (let keyString of Object.keys(entries)) {\n let key = keyString as keyof VaultIndex\n switch (key) {\n case IndexKey.ConsultationLockbox:\n encryptedIndex[key] = (entries[key] as IndexConsultLockbox[])\n .map((e) => ({\n ...e,\n uniqueHash: e.consultationId,\n }))\n .map(\n (e: IndexConsultLockbox) =>\n ({\n uuid: e.uuid,\n timestamp: e.timestamp,\n uniqueHash: e.uniqueHash,\n encryptedIndexEntry: CryptoRSA.jsonWithPubEncryptToBase64(\n {\n consultationId: e.consultationId,\n grant: e.grant,\n },\n rsaPub\n ),\n } as EncryptedIndexEntry)\n )\n break\n }\n }\n await this.vaultClient.vaultIndexPut(encryptedIndex, indexOwnerUuid)\n }\n\n /**\n * @name grantLockbox\n * @description Grants a lockbox by retrieving the shared secret of the lockbox and encrypting it with the grantees public key\n * @param granteeUuid\n * @param lockboxUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n */\n public async grantLockbox(granteeUuid: Uuid, lockboxUuid: Uuid, lockboxOwnerUuid?: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let secret = (await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)).key()\n let base64GranteePublicKey = (await this.guardClient.identityGet(granteeUuid)).publicKey\n let granteePublicKey = this.toolbox.decodeFromBase64(base64GranteePublicKey)\n\n let granteeEncryptedSecret = CryptoRSA.bytesWithPubEncryptToBase64(secret, granteePublicKey)\n let request: LockboxGrantRequest = {\n encryptedSecret: granteeEncryptedSecret,\n granteeUuid: granteeUuid,\n }\n await this.vaultClient.lockboxGrant(lockboxUuid, request, lockboxOwnerUuid)\n }\n\n /**\n * @name createMessageData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a message string\n * @param lockboxUuid\n * @param message\n * @param consultationId the consultation for which this message is sent\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @returns the data uuid\n */\n public async createMessageData(\n lockboxUuid: Uuid,\n message: string,\n consultationId: string,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n\n let encryptedData = symmetricEncryptor.jsonEncryptToBase64Payload(message)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload({\n author: (await this.guardClient.whoAmI()).sub,\n })\n\n let meta = {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Message,\n contentType: 'text/plain',\n }\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name createMessageAttachmentData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a file\n * @param lockboxUuid\n * @param data the file stored\n * @param consultationId the consultation for which this message is sent\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @returns the data uuid\n */\n public async createMessageAttachmentData(\n lockboxUuid: Uuid,\n data: File,\n consultationId: string,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.bytesEncryptToBase64Payload(new Uint8Array(await data.arrayBuffer()))\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload({\n author: (await this.guardClient.whoAmI()).sub,\n fileName: data.name,\n lastModified: data.lastModified,\n size: data.size,\n })\n\n let meta = {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Message,\n contentType: data.type,\n }\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name createAttachmentData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a file\n * @param lockboxUuid\n * @param data the file stored\n * @param consultationId the consultation for which this message is sent\n * @param category the category for the attachment data\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @param withNotification if the insertion of data requires notification\n * @returns the data uuid\n */\n public async createConsultationAttachmentData(\n lockboxUuid: Uuid,\n data: File,\n consultationId: string,\n documentType: DocumentType,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid,\n options: { withNotification?: boolean } = { withNotification: false }\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n return this.createBytesData<Meta | any>(\n lockboxUuid,\n new Uint8Array(await data.arrayBuffer()),\n {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType,\n contentType: data.type,\n },\n {\n author: (await this.guardClient.whoAmI()).sub,\n fileName: data.name,\n },\n lockboxOwnerUuid,\n previousDataUuid,\n options\n )\n }\n\n /**\n * @name createJsonData\n * @description Creates a Base64 encrypted Payload to send and store in the vault. With the data input as a JSON\n * @param lockboxUuid\n * @param data\n * @param meta\n * @param privateMeta the metadata that will be secured in the vault\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing data, specify the previous data uuid\n * @param options if the insertion of data requires email notification\n * @returns the data uuid\n */\n public async createJsonData<T extends Metadata>(\n lockboxUuid: Uuid,\n data: any,\n meta?: T,\n privateMeta?: { [val: string]: any },\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid,\n options: { withNotification?: boolean } = { withNotification: false }\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.jsonEncryptToBase64Payload(data)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload(privateMeta)\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n if (options.withNotification)\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n else return this.vaultClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * Get or upsert a data in lockbox\n * @param lockboxUuid the lockbox uuid\n * @param data the data to insert\n * @param publicMetadata the public Metadata\n * @param privateMetadata the private Metadata\n * @param forceReplace set true when the insertion of data requires to replace the data when it exists already\n * @param options if the insertion of data requires email notification\n * @returns the data uuid\n */\n public async getOrInsertJsonData<M extends Metadata>(\n lockboxUuid: Uuid,\n data: any,\n publicMetadata: M,\n privateMetadata: Metadata,\n options: { withNotification?: boolean, forceReplace?: boolean } = { withNotification: false, forceReplace: false }\n ): Promise<Uuid> {\n let manifest = await this.vaultClient.lockboxManifestGet(lockboxUuid, publicMetadata)\n if (!options.forceReplace && manifest.length > 0) {\n console.log(`The data for ${JSON.stringify(publicMetadata)} already exist`)\n return manifest[0].dataUuid\n } else\n return (\n await this.createJsonData<M>(\n lockboxUuid,\n data,\n publicMetadata,\n privateMetadata,\n undefined,\n // if forceReplace and data already exist, then replace data. Otherwise insert it\n options.forceReplace && manifest.length > 0 ? manifest[0].dataUuid : undefined,\n { withNotification: options.withNotification }\n ).catch((err) => {\n console.error(`Error while upserting data ${JSON.stringify(publicMetadata)} data`, err)\n throw err\n })\n ).dataUuid\n }\n\n /**\n * @name createBytesData\n * @description Creates a Base64 encrypted Payload to send and store in the vault. With the data input as a Bytes\n * @param lockboxUuid\n * @param data\n * @param meta\n * @param privateMeta the metadata that will be secured in the vault\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing data, specify the previous data uuid\n * @param withNotification if the insertion of data requires notification\n * @returns the data uuid\n */\n public async createBytesData<T extends Metadata>(\n lockboxUuid: Uuid,\n data: Uint8Array,\n meta: T,\n privateMeta: { [val: string]: any },\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid,\n options: { withNotification?: boolean } = { withNotification: false }\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.bytesEncryptToBase64Payload(data)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload(privateMeta)\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n if (options.withNotification)\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n else return this.vaultClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name getJsonData\n * @description Fetches and decrypts the lockbox data with the cached shared secret.\n * Decrypts the data to a valid JSON object. If this is impossible, the call to the WASM binary will fail\n *\n * @type T is the generic type specifying the return type object of the function\n * @param lockboxUuid\n * @param dataUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns the data specified by the generic type <T>\n */\n public async getJsonData<T = any>(lockboxUuid: Uuid, dataUuid: Uuid, lockboxOwnerUuid?: Uuid): Promise<T> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let [encryptedPayload, symmetricDecryptor] = await Promise.all([\n this.vaultClient.lockboxDataGet(lockboxUuid, dataUuid, lockboxOwnerUuid),\n this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid),\n ])\n\n return symmetricDecryptor.base64PayloadDecryptToJson(encryptedPayload.data)\n }\n /**\n * @description Fetches and decrypts the lockbox data with the cached shared secret.\n * @param lockboxUuid\n * @param dataUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns the bytes data\n */\n public async getBytesData(lockboxUuid: Uuid, dataUuid: Uuid, lockboxOwnerUuid?: Uuid): Promise<Uint8Array> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let [encryptedPayload, symmetricDecryptor] = await Promise.all([\n this.vaultClient.lockboxDataGet(lockboxUuid, dataUuid, lockboxOwnerUuid),\n this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid),\n ])\n\n return symmetricDecryptor.base64PayloadDecryptToBytes(encryptedPayload.data)\n }\n\n /**\n * @name getGrants\n * @description Get all lockboxes granted to user with the applied filter\n * @note this function returns cached grants and will not update unless the page is refreshed\n * @todo some versions of lockboxes do not make use of lockbox metadata\n * in this case, all lockboxes need to be filtered one-by-one to find the correct one\n * Remove if this is no longer the case\n * @param filter: the consultationId in which the grant exists\n * @returns decrypted lockboxes granted to user\n */\n public async getGrants(filter?: { consultationId: Uuid }): Promise<Grant[]> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let filterString = JSON.stringify(filter)\n // retrieves cached grants\n if (this.cachedMetadataGrants[filterString]) return this.cachedMetadataGrants[filterString]\n\n // We're using the account role to determine the way a grant is accessed\n let currentAccountRole = await this.getAccountRole()\n if (currentAccountRole.length === 1 && currentAccountRole[0] === OtherRoleType.User) return []\n\n if (\n [OtherRoleType.Patient, OtherRoleType.User].every((requiredRole) =>\n currentAccountRole.includes(requiredRole)\n )\n ) {\n let encryptedGrants\n // if there are no grants with the applied filter from index, attempt for naive filter with backwards compatibility\n if (filter) {\n encryptedGrants = await filterGrantsWithLockboxMetadata(this, filter)\n } else {\n encryptedGrants = (await this.vaultClient.grantsGet()).grants\n }\n const decryptedGrants = await decryptGrants(encryptedGrants, this.rsa)\n // sets the cached grant\n this.cachedMetadataGrants[filterString] = decryptedGrants\n console.info('[sdk:grant] Found grant for patient')\n return decryptedGrants\n }\n // if not a patient, then a practitioner is trying to retrieve a grant, it **Must** contain a filter, otherwise too many grants are possible\n if (!filter) throw MissingGrantFilter\n // Note: will work only if the filter being applied is exclusively a consult id\n const grantsByConsultLockbox = await this.vaultClient\n .vaultIndexGet([IndexKey.ConsultationLockbox], [filter.consultationId])\n .then((res) => res[IndexKey.ConsultationLockbox])\n .catch((e) => {\n console.error(e)\n return []\n })\n\n const decryptedConsults = decryptConsultLockboxGrants(grantsByConsultLockbox ?? [], this.rsa)\n if (decryptedConsults.length > 0) {\n console.info('[sdk:index] Grants found in user`s constant time secure index')\n this.cachedMetadataGrants[filterString] = decryptedConsults\n return this.cachedMetadataGrants[filterString]\n }\n\n // if we have no valid grants, then return nothing\n return []\n }\n\n /**\n * Fetches the role of the account that is logged in\n *\n * @returns the role based scopes defined by the whoami\n */\n async getAccountRole(): Promise<RoleBasedScopes[]> {\n return (await this.guardClient.whoAmI()).scope.split(' ') as RoleBasedScopes[]\n }\n\n /**\n * @name getCachedSecretCryptor\n * @description Retrieves the cached lockbox secret or fetches the secret from vault, then creates the symmetric cryptor and stores it in memory\n * @param lockboxUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns\n */\n async getCachedSecretCryptor(lockboxUuid: string, lockboxOwnerUuid?: string): Promise<OroToolbox.CryptoChaCha> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let index = this.secrets.findIndex((secret) => secret.lockboxUuid === lockboxUuid)\n if (index === -1) {\n let encryptedSecret = (await this.vaultClient.lockboxSecretGet(lockboxUuid, lockboxOwnerUuid)).sharedSecret\n\n let secret = this.rsa.base64DecryptToBytes(encryptedSecret)\n let cryptor = this.toolbox.CryptoChaCha.fromKey(secret)\n this.secrets.push({ lockboxUuid, cryptor })\n return cryptor\n } else {\n return this.secrets[index].cryptor\n }\n }\n\n /**\n * Retrieves the patient personal information associated to the `consultationId`\n * The `consultationId` only helps to retrieve the patient lockboxes\n * Note: it is possible to have several personal informations data\n * @param consultationId The consultation Id\n * @param category The personal MetadataCategory to fetch\n * @param forceRefresh force data refresh (default to false)\n * @returns the personal data\n */\n public async getPersonalInformationsFromConsultId(\n consultationId: Uuid,\n category: MetadataCategory.Personal | MetadataCategory.ChildPersonal | MetadataCategory.OtherPersonal,\n options: { forceRefresh: boolean } = { forceRefresh: false }\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n return this.getMetaCategoryFromConsultId(consultationId, category, options)\n }\n\n /**\n * Retrieves the patient medical data associated to the `consultationId`\n * The `consultationId` only helps to retrieve the patient lockboxes\n * Note: it is possible to have several medical data\n * @param consultationId The consultation Id\n * @param forceRefresh force data refresh (default to false)\n * @returns the medical data\n */\n public async getMedicalDataFromConsultId(\n consultationId: Uuid,\n options: { forceRefresh: boolean } = { forceRefresh: false }\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n return this.getMetaCategoryFromConsultId(consultationId, MetadataCategory.Medical, options)\n }\n\n private async getMetaCategoryFromConsultId(\n consultationId: Uuid,\n category: MetadataCategory,\n options: { forceRefresh: boolean } = { forceRefresh: false }\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n let grants = await this.getGrants({ consultationId })\n let workflowData: LocalizedData<PopulatedWorkflowData>[] = []\n for (let grant of grants) {\n let manifest = await this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId],\n },\n true,\n grant.lockboxOwnerUuid,\n options\n )\n\n // TODO: find another solution for backwards compatibility (those without the metadata consultationIds)\n if (manifest.length === 0) {\n manifest = (\n await this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n // backward compatiblility with TonTest\n },\n true,\n grant.lockboxOwnerUuid,\n options\n )\n ).filter((entry) => !entry.metadata.consultationIds) // Keep only entries without associated consultationIds\n }\n let data = await Promise.all(\n manifest.map(async (entry) => {\n return {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid!,\n dataUuid: entry.dataUuid,\n data: await this.getJsonData<PopulatedWorkflowData>(grant.lockboxUuid!, entry.dataUuid),\n }\n })\n )\n workflowData = { ...workflowData, ...data }\n }\n return workflowData\n }\n\n /**\n * @description retrieves the personal information stored in the first owned lockbox\n * @param userId The user Id\n * @returns the personal data\n */\n public async getPersonalInformations(userId: Uuid): Promise<LocalizedData<PopulatedWorkflowData>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === userId)\n\n if (!grant) {\n throw MissingGrant\n }\n\n const { lockboxUuid, lockboxOwnerUuid } = grant\n\n if (!lockboxUuid) throw MissingLockbox\n\n if (!lockboxOwnerUuid) throw MissingLockboxOwner\n\n const identificationDataUuid = (\n await this.getLockboxManifest(\n lockboxUuid,\n {\n category: MetadataCategory.Personal,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n false,\n userId\n )\n )[0].dataUuid\n\n return {\n lockboxOwnerUuid,\n lockboxUuid,\n dataUuid: identificationDataUuid,\n data: await this.getJsonData<PopulatedWorkflowData>(lockboxUuid, identificationDataUuid),\n }\n }\n\n /**\n * Retrieves the grant associated to a consultationId\n * @note returns the first grant only\n * @param consultationId The consultationId\n * @returns the grant\n */\n public async getGrantFromConsultId(consultationId: Uuid): Promise<Grant | undefined> {\n let grants = await this.getGrants({ consultationId })\n\n if (grants.length === 0) {\n throw AssociatedLockboxNotFound\n }\n\n return grants[0]\n }\n\n /**\n * retrieves the identity associated to the `consultationId`\n * @param consultationId The consultation Id\n * @returns the identity\n */\n public async getIdentityFromConsultId(consultationId: Uuid): Promise<IdentityResponse | undefined> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (grant && grant.lockboxOwnerUuid) {\n return await this.guardClient.identityGet(grant.lockboxOwnerUuid)\n } else {\n return undefined\n }\n }\n\n /**\n * retrieves the lockbox manifest for a given lockbox and add's its private metadata\n * @note the lockbox manifest will retrieved the cached manifest first unless force refresh is enabled\n * @param lockboxUuid\n * @param filter\n * @param expandPrivateMetadata\n * @param lockboxOwnerUuid\n * @param forceRefresh\n * @returns the lockbox manifest\n */\n public async getLockboxManifest(\n lockboxUuid: Uuid,\n filter: Metadata,\n expandPrivateMetadata: boolean,\n lockboxOwnerUuid?: Uuid,\n options: { forceRefresh: boolean } = { forceRefresh: false }\n ): Promise<LockboxManifest> {\n let manifestKey = JSON.stringify({\n lockboxUuid,\n filter,\n expandPrivateMetadata,\n lockboxOwnerUuid,\n })\n if (!options.forceRefresh && this.cachedManifest[manifestKey]) return this.cachedManifest[manifestKey]\n\n return this.vaultClient.lockboxManifestGet(lockboxUuid, filter, lockboxOwnerUuid).then((manifest) => {\n return Promise.all(\n manifest.map(async (entry) => {\n if (expandPrivateMetadata && entry.metadata.privateMetadata) {\n let privateMeta = await this.getJsonData<Metadata>(\n lockboxUuid!,\n entry.metadata.privateMetadata,\n lockboxOwnerUuid\n )\n entry.metadata = {\n ...entry.metadata,\n ...privateMeta,\n }\n }\n return entry\n })\n ).then((manifest) => (this.cachedManifest[manifestKey] = manifest))\n })\n }\n\n /**\n * @description Create or update the personal information and store it in the first owned lockbox\n * @param identity The identity to use\n * @param data The personal data to store\n * @param dataUuid (optional) The dataUuid to update\n * @returns\n */\n public async createPersonalInformations(\n identity: IdentityResponse,\n data: PopulatedWorkflowData,\n dataUuid?: string\n ): Promise<DataCreateResponse> {\n const lockboxUuid = (await this.getGrants()).find(\n (lockbox) => lockbox.lockboxOwnerUuid === identity.id\n )?.lockboxUuid\n\n if (lockboxUuid) {\n return this.createJsonData<PersonalMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Personal,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n {},\n undefined,\n dataUuid\n )\n } else {\n throw MissingLockbox\n }\n }\n\n /**\n * Create or update user Preference\n * @param identity\n * @param preference\n * @param dataUuid\n * @returns\n */\n public async createUserPreference(\n identity: IdentityResponse,\n preference: UserPreference,\n dataUuid?: string\n ): Promise<DataCreateResponse> {\n const lockboxUuid = (await this.getGrants()).find(\n (lockbox) => lockbox.lockboxOwnerUuid === identity.id\n )?.lockboxUuid\n\n if (lockboxUuid) {\n return this.createJsonData<PreferenceMeta>(\n lockboxUuid,\n preference,\n {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n },\n {},\n undefined,\n dataUuid\n )\n } else {\n throw MissingLockbox\n }\n }\n\n /**\n * retrieves the user preference from a grant\n * @param grant The grant\n * @returns the user preference\n */\n public async getDataFromGrant<T = any>(grant: Grant, filter: Metadata): Promise<LocalizedData<T>> {\n const { lockboxUuid, lockboxOwnerUuid } = grant\n\n if (!lockboxUuid) throw MissingLockbox\n if (!lockboxOwnerUuid) throw MissingLockboxOwner\n const identificationDataUuid = (\n await this.getLockboxManifest(\n lockboxUuid,\n filter,\n false,\n grant.lockboxOwnerUuid,\n { forceRefresh: true }\n )\n )[0].dataUuid\n\n return {\n lockboxOwnerUuid,\n lockboxUuid,\n dataUuid: identificationDataUuid,\n data: await this.getJsonData<T>(lockboxUuid, identificationDataUuid),\n }\n }\n\n /**\n * retrieves the user preference from a consultation id\n * @param consultationId The related consultationId\n * @returns the user preference\n */\n public async getUserPreferenceFromConsultId(consultationId: string): Promise<LocalizedData<UserPreference>> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<UserPreference>(grant, {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference stored in the first owned lockbox from identity\n * @param identity The identity to use\n * @returns the user preference\n */\n public async getUserPreference(identity: IdentityResponse): Promise<LocalizedData<UserPreference>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === identity.id)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<UserPreference>(grant, {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference from a consultation id\n * @param consultationId The related consultationId\n * @returns the user preference\n */\n public async getRecoveryDataFromConsultId(consultationId: string): Promise<LocalizedData<RecoveryData>> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<RecoveryData>(grant, {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference stored in the first owned lockbox from identity\n * @param identity The identity to use\n * @returns the user preference\n */\n public async getRecoveryData(identity: IdentityResponse): Promise<LocalizedData<RecoveryData>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === identity.id)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant(grant, {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n })\n }\n\n /**\n * @name getAssignedConsultations\n * @description finds all assigned or owned consultations for the logged user\n * Steps:\n * - Retrieves all granted lockboxes given to the logged user\n * - for each lockbox, find all consultation ids\n * - for each consultation id, retrieve the consult information\n * @param practiceUuid the uuid of the practice to look consult into\n * @returns the list of consults\n */\n public async getAssignedConsultations(practiceUuid: Uuid): Promise<Consult[]> {\n return Promise.all(\n (await this.getGrants()).map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n true,\n undefined\n ).then((manifest) =>\n Promise.all(\n manifest.map(\n async (entry) =>\n await this.consultClient.getConsultByUUID(entry.metadata.consultationId, practiceUuid)\n )\n ).then((promise) => promise.flat())\n )\n )\n ).then((consults) => consults.flat())\n }\n\n /**\n * Gets the past consultations of the patient as well as his relatives if any\n * @param consultationId any consultation uuid from which we will fetch all the other consultations of the same patient as the owner of this consultation id\n * @param practiceUuid\n */\n public async getPastConsultationsFromConsultId(\n consultationId: string,\n practiceUuid: string\n ): Promise<Consult[] | undefined> {\n const grant = await this.getGrantFromConsultId(consultationId)\n if (!grant) return undefined\n\n let consultationsInLockbox: string[] = (\n await this.vaultClient.lockboxMetadataGet(\n grant.lockboxUuid!,\n ['consultationId'],\n ['consultationId'],\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n grant.lockboxOwnerUuid\n )\n )\n .flat()\n .map((metadata: { consultationId: string }) => metadata.consultationId)\n\n if (consultationsInLockbox.length == 0) return []\n\n return await Promise.all(\n consultationsInLockbox.map(async (consultId: string) => {\n return await this.consultClient.getConsultByUUID(consultId, practiceUuid)\n })\n )\n }\n\n /**\n * @name getPatientConsultationData\n * @description retrieves the consultation data\n * @param consultationId\n * @returns\n */\n public async getPatientConsultationData(\n consultationId: Uuid,\n options: { forceRefresh: boolean } = { forceRefresh: false }\n ): Promise<PopulatedWorkflowData[]> {\n //TODO: make use of getPatientDocumentsList instead of doing it manually here\n return Promise.all(\n (await this.getGrants({ consultationId }))\n .map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationId, //since we want to update the cached manifest (if another consult data exists)\n },\n true,\n grant.lockboxOwnerUuid,\n options\n ).then((manifest) =>\n Promise.all(\n manifest.map((e) =>\n this.getJsonData<PopulatedWorkflowData>(\n grant.lockboxUuid!,\n e.dataUuid,\n grant.lockboxOwnerUuid\n )\n )\n )\n )\n )\n .flat()\n ).then((data) => data.flat())\n }\n\n /**\n * This function returns the patient prescriptions\n * @param consultationId\n * @returns\n */\n public async getPatientPrescriptionsList(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Prescription,\n },\n true,\n consultationId\n )\n }\n\n /**\n * This function returns the patient results\n * @param consultationId\n * @returns\n */\n public async getPatientResultsList(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Result,\n },\n true,\n consultationId\n )\n }\n\n /**\n * returns the patient treatment plan options\n * @param consultationId\n * @returns Document[] corresponding to the patient treatment plan options\n */\n public async getPatientTreatmentPlans(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.TreatmentPlan,\n },\n true,\n consultationId\n )\n }\n\n /**\n * returns a specific patient treatment plan option\n * @param consultationId\n * @param treatmentPlanId\n * @returns\n */\n public async getPatientTreatmentPlanByUuid(consultationId: Uuid, treatmentPlanId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.TreatmentPlan,\n treatmentPlanId,\n },\n true,\n consultationId\n )\n }\n\n /**\n * @name getPatientDocumentsList\n * @description applies the provided filter to the vault to only find those documents\n * @param filters the applied filters (e.g. type of documents)\n * @param expandPrivateMetadata whether or not, the private metadata needs to be retrieved\n * (more computationally expensive)\n * @param consultationId\n * @returns the filtered document list\n */\n public async getPatientDocumentsList(\n filters: Object,\n expandPrivateMetadata: boolean,\n consultationId: Uuid\n ): Promise<Document[]> {\n return Promise.all(\n (await this.getGrants({ consultationId }))\n .map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n { ...filters, consultationId },\n expandPrivateMetadata,\n grant.lockboxOwnerUuid,\n { forceRefresh: true }\n ).then((manifest) =>\n Promise.all(\n manifest.map(async (entry): Promise<Document> => {\n return {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid!,\n ...entry,\n }\n })\n )\n )\n )\n .flat()\n ).then((data) => data.flat())\n }\n\n /****************************************************************************************************************\n * RECOVERY *\n ****************************************************************************************************************/\n\n /**\n * @name recoverPrivateKeyFromSecurityQuestions\n * @description Recovers and sets the rsa private key from the answered security questions\n * @param id\n * @param recoverySecurityQuestions\n * @param recoverySecurityAnswers\n * @param threshold the number of answers needed to recover the key\n */\n public async recoverPrivateKeyFromSecurityQuestions(\n id: Uuid,\n recoverySecurityQuestions: string[],\n recoverySecurityAnswers: string[],\n threshold: number\n ) {\n let shards: SecretShard[] = (await this.guardClient.identityGet(id)).recoverySecurityQuestions!\n let answeredShards = shards\n .filter((shard: any) => {\n // filters all answered security questions\n let indexOfQuestion = recoverySecurityQuestions.indexOf(shard.securityQuestion)\n if (indexOfQuestion === -1) return false\n return recoverySecurityAnswers[indexOfQuestion] && recoverySecurityAnswers[indexOfQuestion] != ''\n })\n .map((item: any) => {\n // appends the security answer to the answered shards\n let index = recoverySecurityQuestions.indexOf(item.securityQuestion)\n item.securityAnswer = recoverySecurityAnswers[index]\n return item\n })\n try {\n // reconstructs the key from the answered security answers\n let privateKey = this.toolbox.reconstructSecret(answeredShards, threshold)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n } catch (e) {\n console.error(e)\n }\n }\n\n /**\n * @name recoverPrivateKeyFromPassword\n * @description Recovers and sets the rsa private key from the password\n * @param id\n * @param password\n */\n public async recoverPrivateKeyFromPassword(id: Uuid, password: string) {\n let identity = await this.guardClient.identityGet(id)\n\n let recoveryPayload = identity.recoveryPassword\n let symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(password)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n\n if (identity.recoveryLogin) {\n //Ensure we can recover from a page reload\n let symetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(identity.recoveryLogin)\n sessionStorage.setItem(\n sessionStorePrivateKeyName(id),\n symetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n )\n }\n\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * @name recoverPrivateKeyFromMasterKey\n * @description Recovers and sets the rsa private key from the master key\n * @param id\n * @param masterKey\n */\n public async recoverPrivateKeyFromMasterKey(id: Uuid, masterKey: string) {\n let recoveryPayload = (await this.guardClient.identityGet(id)).recoveryMasterKey!\n let symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(masterKey)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * @description Generates and updates the security questions and answers payload using new recovery questions and answers\n * Important: Since the security questions generate a payload for the private key, they will never be stored on the device as they must remain secret!!!\n * @param id\n * @param recoverySecurityQuestions\n * @param recoverySecurityAnswers\n * @param threshold the number of answers needed to rebuild the secret\n */\n public async updateSecurityQuestions(\n id: Uuid,\n recoverySecurityQuestions: string[],\n recoverySecurityAnswers: string[],\n threshold: number\n ) {\n if (!this.rsa) throw IncompleteAuthentication\n let securityQuestionPayload = this.toolbox.breakSecretIntoShards(\n recoverySecurityQuestions,\n recoverySecurityAnswers,\n this.rsa.private(),\n threshold\n )\n let updateRequest = {\n recoverySecurityQuestions: securityQuestionPayload,\n }\n\n return await this.guardClient.identityUpdate(id, updateRequest)\n }\n\n /**\n * @description Generates and stores the payload encrypted payload and updates the password itself (double hash)\n * @important\n * the recovery payload uses a singly hashed password and the password stored is doubly hashed so\n * the stored password cannot derive the decryption key in the payload\n * @note\n * the old password must be provided when not performing an account recovery\n * @param id\n * @param newPassword\n * @param oldPassword\n */\n public async updatePassword(id: Uuid, newPassword: string, oldPassword?: string) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(newPassword)\n let passwordPayload = symmetricEncryptor.bytesEncryptToBase64Payload(this.rsa.private())\n if (oldPassword) {\n oldPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(oldPassword))\n }\n\n newPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(newPassword))\n\n let updateRequest = {\n password: {\n oldPassword,\n newPassword,\n },\n recoveryPassword: passwordPayload,\n }\n\n return await this.guardClient.identityUpdate(id, updateRequest)\n }\n\n /**\n * @description Generates and stores the master key encrypted payload\n * Important\n * Since the master key is used to generate a payload for the private key, it will never be stored on the device as it must remain secret!\n * @param id\n * @param masterKey\n * @param lockboxUuid\n */\n async updateMasterKey(id: Uuid, masterKey: string, lockboxUuid: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(masterKey)\n let masterKeyPayload = symmetricEncryptor.bytesEncryptToBase64Payload(this.rsa.private())\n let updateRequest = { recoveryMasterKey: masterKeyPayload }\n const updatedIdentity = await this.guardClient.identityUpdate(id, updateRequest)\n\n await this.getOrInsertJsonData<RecoveryMeta>(\n lockboxUuid,\n { masterKey },\n {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n },\n {},\n { forceReplace: true }\n )\n\n return updatedIdentity\n }\n}\n","import { AxiosService, CliniaResponse, FacetFilter, PlaceData } from \"oro-sdk-apis\"\n\nexport class CliniaService {\n private api: AxiosService\n\n constructor(private url: string, apiKey: string, private locale?: string) {\n this.api = new AxiosService({ headers: { 'X-Clinia-API-Key': apiKey } })\n }\n\n public placeSearch(searchOptions: {\n locale?: string\n query?: string\n facetFilters?: FacetFilter[]\n location?: string\n aroundLatLng?: string\n page?: number\n }) {\n const { locale, ...data } = searchOptions\n\n return this.api.post<CliniaResponse<PlaceData>>(\n `${this.url}/search/v1/indexes/health_facility/query`,\n data,\n {\n params: { locale: locale ?? this.locale },\n }\n )\n }\n\n public placeMatch(\n searchOptions: {\n locale?: string\n name?: string\n address?: string\n postalCode?: string\n place?: string\n region?: string\n country?: string\n },\n type?: string\n ) {\n const { locale, ...data } = searchOptions\n\n let request = this.api.post<PlaceData[]>(\n `${this.url}/search/v1/matches`,\n data,\n {\n params: { locale: locale ?? this.locale },\n }\n )\n\n if (type) {\n request = request.then((places) =>\n places.filter((place) => place.type === type)\n )\n }\n\n return request\n }\n}\n","import initApis from 'oro-sdk-apis'\nimport { OroClient } from './client'\nimport * as OroToolboxNamespace from 'oro-toolbox'\n\nexport type OroToolbox = typeof OroToolboxNamespace\n\nexport let wasmPath = 'node_modules/oro-toolbox'\n\n/**\n * This function helps you to initialize and OroClient instance\n * @param toolbox the OroToolbox object\n * @param tellerBaseURL the teller service base URL \n * @param vaultBaseURL the vault service base URL \n * @param guardBaseURL the guard service base URL \n * @param searchbaseURL the search service base URL\n * @param practiceBaseURL the practice service base URL \n * @param consultBaseURL the consult service base URL \n * @param workflowBaseURL the workflow service base URL \n * @param diagnosisBaseURL the diagnosis service base URL \n * @param authenticationCallback (optional) authenticationCallback the authentification callback \n * @returns an instance of OroClient\n */\nconst init = (\n toolbox: OroToolbox,\n tellerBaseURL: string,\n vaultBaseURL: string,\n guardBaseURL: string,\n searchBaseURL: string,\n practiceBaseURL: string,\n consultBaseURL: string,\n workflowBaseURL: string,\n diagnosisBaseURL: string,\n authenticationCallback?: (err: Error) => void\n) => {\n const {\n tellerService,\n practiceService,\n consultService,\n vaultService,\n guardService,\n searchService,\n workflowService,\n diagnosisService,\n } = initApis(\n {\n tellerBaseURL,\n vaultBaseURL,\n guardBaseURL,\n searchBaseURL,\n practiceBaseURL,\n consultBaseURL,\n workflowBaseURL,\n diagnosisBaseURL,\n },\n authenticationCallback\n )\n\n const client = new OroClient(\n toolbox,\n tellerService!,\n vaultService!,\n guardService!,\n searchService!,\n practiceService!,\n consultService!,\n workflowService!,\n diagnosisService!,\n authenticationCallback\n )\n\n return client\n}\n\nexport { OroClient } from './client'\nexport * from 'oro-sdk-apis'\nexport * from './models'\nexport * from './helpers'\nexport * from './services'\nexport { OroToolboxNamespace }\nexport default init\n"],"names":["personalMetaToPrefix","MetadataCategory","Personal","ChildPersonal","OtherPersonal","identificationToPersonalInformations","data","category","prefix","birthday","firstname","gender","name","phone","zip","hid","pharmacy","address","toActualObject","ret","Object","entries","fields","forEach","field","displayedAnswer","answer","sessionStorePrivateKeyName","id","IncompleteAuthentication","_inheritsLoose","Error","MissingGrant","MissingGrantFilter","MissingLockbox","MissingLockboxOwner","AssociatedLockboxNotFound","WorkflowAnswersMissingError","filterTriggeredAnsweredWithKind","_filterTriggeredAnsweredWithKind","workflowData","kind","selectedAnswers","_context","flattenedAnswers","flattenSelectedAnswers","triggeredQuestionsWithKind","fromEntries","pages","map","a","questions","filter","question","isTriggered","triggers","flat","samePageAnswers","reduce","prev","cur","res","keys","questionFieldName","getWorkflowDataByCategory","_getWorkflowDataByCategory","_context2","triggeredQuestions","Promise","all","e","k","populateWorkflowField","then","populatedValue","workflowCreatedAt","createdAt","workflowId","locale","err","console","error","getImagesFromIndexDb","_getImagesFromIndexDb","_context3","getMany","v","_populateWorkflowField","answerValue","undefined","_context4","answers","text","value","images","image","imageData","resolve","includes","Array","isArray","some","subSetTriggers","every","trigger","linearAnswers","push","values","getInitialisedSelectedAnswers","workflow","useDefault","page","defaultValue","getOrCreatePatientConsultationUuid","_getOrCreatePatientConsultationUuid","consult","oroClient","practiceClient","practiceGetPayment","uuidPractice","idStripeInvoiceOrPaymentIntent","payment","uuidConsult","consultClient","getConsultByUUID","consultCreate","registerPatient","_registerPatient","patientUuid","consultRequest","masterKey","recoveryQA","indexSearch","onProgress","lockboxUuid","practitionerAdmin","retry","identity","errorsThrown","stepsTotalNum","currentStep","setTimeout","practiceGetFromUuid","uuidAdmin","practiceGetPractitioners","log","practitioners","getOrCreatePatientLockbox","guardClient","identityGet","grantLockbox","grantPromises","practitioner","uuid","IndexKey","ConsultationLockbox","grant","lockboxOwnerUuid","consultationId","consultIndex","consultIndexPromises","vaultIndexAdd","storeImageAliases","storePatientData","isoLanguageRequired","_identity","recoveryMasterKey","updateMasterKey","_identity2","recoverySecurityQuestions","updateSecurityQuestions","recoverySecurityAnswers","buildConsultSearchIndex","length","updateConsultByUUID","statusMedical","MedicalStatus","New","cleanIndex","_getOrCreatePatientLockbox","_context5","getGrants","grants","vaultClient","lockboxCreate","lockboxResponse","authRefresh","tokens","setTokens","accessToken","refreshToken","whoAmI","_storePatientData","isoLanguage","getOrInsertJsonData","Raw","contentType","Consultation","documentType","DocumentType","PopulatedWorkflowData","withNotification","Medical","consultationIds","extractAndStorePersonalWorkflowData","Preference","dataUuids","_storeImageAliases","progress","_context7","nonNullImages","img","storedImagesNum","totalImagesNum","promises","ImageAlias","idbId","progressStepValue","Math","round","_extractAndStorePersonalWorkflowData","extractPersonalInfoFromWorkflowData","_extractPersonalInfoFromWorkflowData","personalInfoPopulatedWfData","childPersonalInfoPopulatedWfData","otherPersonalInfoPopulatedWfData","_buildConsultSearchIndex","terms","shortId","_context10","_yield$extractPersona","personalInfo","childPersonalInfo","otherPersonalInfo","searchClient","index","decryptGrants","encryptedGrants","rsaKey","encryptedLockbox","uuidParse","base64DecryptToBytes","decryptConsultLockboxGrants","encryptedConsultLockboxes","base64DecryptToJson","encryptedIndexEntry","grantsTuple","grantTuples","createRefill","_createRefill","populatedRefillWorkflow","newConsult","Refill","filterGrantsWithLockboxMetadata","_filterGrantsWithLockboxMetadata","filteredGrants","_iterator","lockboxMetadataGet","OroClient","toolbox","tellerClient","workflowClient","diagnosisClient","authenticationCallback","this","_proto","cachedMetadataGrants","cachedManifest","signUp","email","password","practice","tosAndCpAcceptance","tokenData","subscription","skipEmailValidation","rsa","CryptoRSA","privateKey","symmetricEncryptor","CryptoChaCha","fromPassphrase","recoveryPassword","bytesEncryptToBase64Payload","hashedPassword","hashStringToBase64","emailConfirmed","signupRequest","practiceUuid","toLowerCase","publicKey","encodeToBase64","identityCreate","recoveryLogin","symetricEncryptor","sessionStorage","setItem","confirmEmail","identityUpdate","sub","signIn","otp","tokenRequest","authToken","userUuid","recoverPrivateKeyFromPassword","resumeSession","recoveryPayload","getItem","recoveryKey","symmetricDecryptor","base64PayloadDecryptToBytes","fromKey","localEncryptToJsonPayload","chaChaKey","encryptedData","jsonEncryptToBase64Payload","encryptedKey","encryptToBytes","key","localDecryptJsonPayload","base64PayloadDecryptToJson","signOut","secrets","_context6","authLogout","_context8","forceUpdateIndexEntries","_this$vaultIndexAdd","_context9","_this","consults","alert","indexOwnerUuid","_context11","rsaPub","decodeFromBase64","encryptedIndex","_i","uniqueHash","timestamp","jsonWithPubEncryptToBase64","vaultIndexPut","granteeUuid","_context12","getCachedSecretCryptor","secret","granteePublicKey","granteeEncryptedSecret","bytesWithPubEncryptToBase64","request","encryptedSecret","lockboxGrant","createMessageData","message","previousDataUuid","_context13","author","encryptedPrivateMeta","lockboxDataStore","publicMetadata","Message","privateMetadata","createMessageAttachmentData","_context14","Uint8Array","arrayBuffer","lastModified","size","fileName","type","createConsultationAttachmentData","options","_context15","createBytesData","createJsonData","meta","privateMeta","_context16","forceReplace","_context17","lockboxManifestGet","manifest","JSON","stringify","dataUuid","_context18","getJsonData","_context19","lockboxDataGet","_yield$Promise$all","getBytesData","_context20","_yield$Promise$all2","_context21","filterString","getAccountRole","currentAccountRole","OtherRoleType","User","Patient","requiredRole","grantsGet","decryptedGrants","info","vaultIndexGet","decryptedConsults","grantsByConsultLockbox","_context22","scope","split","_context23","findIndex","lockboxSecretGet","sharedSecret","cryptor","getPersonalInformationsFromConsultId","forceRefresh","getMetaCategoryFromConsultId","getMedicalDataFromConsultId","_context28","_loop","_context27","_this2","getLockboxManifest","entry","metadata","_context26","getPersonalInformations","userId","_context29","find","lockbox","identificationDataUuid","getGrantFromConsultId","_context30","getIdentityFromConsultId","_context31","expandPrivateMetadata","manifestKey","_context33","_context32","_this3","createPersonalInformations","_context34","_yield$this$getGrants","createUserPreference","preference","_context35","_yield$this$getGrants2","getDataFromGrant","_context36","getUserPreferenceFromConsultId","_context37","getUserPreference","_context38","getRecoveryDataFromConsultId","_context39","Recovery","getRecoveryData","_context40","getAssignedConsultations","_context42","_this4","_context41","promise","getPastConsultationsFromConsultId","_context44","consultationsInLockbox","consultId","_context43","_this5","getPatientConsultationData","_context45","_this6","getPatientPrescriptionsList","getPatientDocumentsList","Prescription","getPatientResultsList","Result","getPatientTreatmentPlans","TreatmentPlan","getPatientTreatmentPlanByUuid","treatmentPlanId","filters","_context51","_this7","recoverPrivateKeyFromSecurityQuestions","threshold","_context52","answeredShards","shard","indexOfQuestion","indexOf","securityQuestion","item","securityAnswer","reconstructSecret","_context53","recoverPrivateKeyFromMasterKey","_context54","_context55","securityQuestionPayload","breakSecretIntoShards","updateRequest","updatePassword","newPassword","oldPassword","_context56","passwordPayload","_context57","masterKeyPayload","updatedIdentity","CliniaService","url","apiKey","api","AxiosService","headers","X-Clinia-API-Key","placeSearch","searchOptions","post","params","placeMatch","places","place","tellerBaseURL","vaultBaseURL","guardBaseURL","searchBaseURL","practiceBaseURL","consultBaseURL","workflowBaseURL","diagnosisBaseURL","initApis","tellerService","vaultService","guardService","searchService","practiceService","consultService","workflowService","diagnosisService","arrSelectedLocality","flatMap","currentAnswerPage","arrCountryFields","workflowFieldName","arrProvinceFields","arrConsultLocalFields","currentFieldName","currentSelectedLocality","startsWith","allowedLocalityPatterns","indexPriority","isoValue","finalLocality","extractedSelected","exec","indexSelectedPriority","isoSelectedValue","extractedFinal","indexFinalPriority","populatedWorkflow","filledWorkflow","parse","pageIdx","isTreatmentWorking","hasSideEffects","deliveryAddress","culDeSacs","hidePlanRules","title","groups","fieldsAndGroups","label","inline","inlineLabel","metaCategory","73bec6eb-0310-4787-af3c-ac9c291737b2","e193951f-986f-4db3-bede-903045a1804a","1b87ad22-d316-4fac-9c7f-8f4ccb841aed","ab7f5a41-c351-4f5d-a568-e38f9f200e9a","youPharmacy","minorLabel","summaryLabel","youAddress","infos"],"mappings":"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"}