oro-sdk 2.10.1 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.10.1",
2
+ "version": "2.12.0",
3
3
  "main": "dist/index.js",
4
4
  "typings": "dist/index.d.ts",
5
5
  "files": [
@@ -59,7 +59,7 @@
59
59
  "form-data": "^4.0.0",
60
60
  "formdata-node": "^4.3.1",
61
61
  "idb-keyval": "^5.0.6",
62
- "oro-sdk-apis": "^1.7.0",
62
+ "oro-sdk-apis": "1.8.1",
63
63
  "oro-toolbox": "0.0.6",
64
64
  "uuid": "^8.3.2"
65
65
  }
@@ -4,6 +4,7 @@ import {
4
4
  ConsultationMeta,
5
5
  ConsultRequest,
6
6
  DocumentType,
7
+ IdentityResponse,
7
8
  IndexKey,
8
9
  MedicalMeta,
9
10
  MedicalStatus,
@@ -26,6 +27,26 @@ import {
26
27
 
27
28
  const MAX_RETRIES = 15
28
29
 
30
+ /**
31
+ * Completes a registration for a user retrying the complete flow a maximum of 15 times
32
+ *
33
+ * @description The order of importance when registering:
34
+ * Creates a consultation if none exist
35
+ * Retrieves or create's a lockbox if none exist
36
+ * Grants the lockbox (if new) to all practitioners in the practice
37
+ * Stores or fetches the patient data (without images)
38
+ * Indexes the lockbox to the consult for all practitioners (done after inserting since index can be rebuilt from grants)
39
+ * Stores the image data - done last since the majority of failure cases occur here
40
+ * Creates the recovery payloads if they don't exist
41
+ *
42
+ * @param patientUuid
43
+ * @param consultRequest
44
+ * @param workflow
45
+ * @param oroClient
46
+ * @param masterKey
47
+ * @param recoveryQA
48
+ * @returns the successful registration
49
+ */
29
50
  export async function registerPatient(
30
51
  patientUuid: Uuid,
31
52
  consultRequest: ConsultRequest,
@@ -41,7 +62,8 @@ export async function registerPatient(
41
62
  let lockboxUuid: Uuid | undefined = undefined
42
63
  let practitionerAdmin: Uuid | undefined = undefined
43
64
  let retry = MAX_RETRIES
44
- let isExistingPatient = false
65
+ let identity: IdentityResponse | undefined = undefined
66
+ let errorsThrown: Error[] = []
45
67
 
46
68
  for (; retry > 0; retry--) {
47
69
  try {
@@ -68,14 +90,13 @@ export async function registerPatient(
68
90
  // Creating lockbox
69
91
  if (!lockboxUuid) lockboxUuid = await getOrCreatePatientLockbox(oroClient)
70
92
 
71
- isExistingPatient = await patientConsultExists(consult, lockboxUuid, oroClient).catch((err) => {
72
- console.error(`Error when retrieving existing consults ${err}`)
73
- return false
74
- })
93
+ if (!identity)
94
+ identity = await oroClient.guardClient.identityGet(patientUuid)
95
+
75
96
  await oroClient.grantLockbox(practitionerAdmin, lockboxUuid).catch((err) => {
76
97
  console.error(`Error while granting lockbox to practitioner admin ${practitionerAdmin}`, err)
77
98
  // if we cannot grant to the admin, then the registration will fail
78
- throw err
99
+ errorsThrown.push(err)
79
100
  })
80
101
 
81
102
  // Patient Grant to practice
@@ -84,16 +105,13 @@ export async function registerPatient(
84
105
  .map(async (practitioner) => {
85
106
  return oroClient.grantLockbox(practitioner.uuid, lockboxUuid!).catch((err) => {
86
107
  console.error(`Error while granting lockbox to practitioner`, err)
87
- // Acceptable to continue as admin has already been granted, but we should still try to retry
108
+ // Acceptable to continue as admin has already been granted, but we should still retry until the last retry remains
88
109
  if (retry <= 1) return
89
- else throw err
110
+ errorsThrown.push(err)
90
111
  })
91
112
  })
92
113
 
93
- await storePatientData(consult.uuid, consultRequest.isoLanguageRequired, lockboxUuid, workflow, oroClient)
94
-
95
- // the index will identify in which lockbox a consultation live
96
- let consultIndex: VaultIndex = {
114
+ const consultIndex: VaultIndex = {
97
115
  [IndexKey.ConsultationLockbox]: [
98
116
  {
99
117
  grant: {
@@ -105,53 +123,46 @@ export async function registerPatient(
105
123
  ],
106
124
  }
107
125
 
126
+ // the index will identify in which lockbox a consultation resides
108
127
  let consultIndexPromises = practitioners.map(async (practitioner) => {
109
128
  return oroClient.vaultIndexAdd(consultIndex, practitioner.uuid).catch((err) => {
110
- console.error(`Error while adding to the practitioner's index ${practitioner.uuid}`, err)
111
- /// it's acceptable to continue registration
112
- return
129
+ console.error(`[SDK: registration] Error while adding to the practitioner's index ${practitioner.uuid}`, err)
130
+ // Acceptable to continue as the index can be rebuilt, but we should still retry until the last retry remains
131
+ if (retry <= 1) return
132
+ else errorsThrown.push(err)
113
133
  })
114
134
  })
115
135
 
116
- //DEPRECATED: REMOVE ME : BEGIN /////////////////////////////////////////
117
136
 
118
- let deprecatedConsultIndex: VaultIndex = {
119
- [IndexKey.Consultation]: [
120
- {
121
- grant: {
122
- lockboxUuid,
123
- lockboxOwnerUuid: patientUuid,
124
- },
125
- consultationId: consult.uuid,
126
- },
127
- ],
128
- }
129
-
130
- let deprecatedConsultIndexPromises = practitioners.map(async (practitioner) => {
131
- return oroClient.vaultIndexAdd(deprecatedConsultIndex, practitioner.uuid).catch((err) => {
132
- console.error(`Error while adding to the practitioner's index ${practitioner.uuid}`, err)
133
- /// it's acceptable to continue registration
134
- return
135
- })
137
+ await storeImageAliases(consult.uuid, lockboxUuid, workflow, oroClient).catch((err) => {
138
+ console.error('[SDK: registration] Some errors happened during image upload', err)
139
+ // Acceptable to continue as images can be requested during the consultation, but we should still retry until the last retry remains
140
+ if (retry <= 1) return
141
+ else errorsThrown.push(err)
136
142
  })
137
143
 
138
- //DEPRECATED: REMOVE ME : END /////////////////////////////////////////
144
+ await storePatientData(consult.uuid, consultRequest.isoLanguageRequired, lockboxUuid, workflow, oroClient).catch((err) => {
145
+ console.error('[SDK: registration] Some errors happened during patient data upload', err)
146
+ errorsThrown.push(err)
147
+ })
139
148
 
140
- if (masterKey && !isExistingPatient) {
141
- // generate and store recovery payload
142
- await oroClient.updateMasterKey(patientUuid, masterKey, lockboxUuid).catch((err) => {
143
- console.error(`Error while updating master key`, err)
144
- /// it's acceptable to continue registration
145
- return
149
+ if (masterKey && !identity?.recoveryMasterKey) {
150
+ // generate and store recovery payload and updates the identity
151
+ identity = await oroClient.updateMasterKey(patientUuid, masterKey, lockboxUuid).catch((err) => {
152
+ console.error(`[SDK: registration] Error while updating master key`, err)
153
+ /// it's acceptable to continue registration (return old identity)
154
+ if (retry <= 1) return
155
+ errorsThrown.push(err)
156
+ return identity
146
157
  })
147
158
  } else {
148
159
  // we did not set the master key so we do not return it
149
160
  masterKey = undefined
150
161
  }
151
162
 
152
- if (recoveryQA && !isExistingPatient)
153
- // Patient security question recovery threshold is 2 answers
154
- await oroClient
163
+ if (recoveryQA && !identity?.recoverySecurityQuestions)
164
+ // Patient security question recovery threshold is 2 answers and updates the identity
165
+ identity = await oroClient
155
166
  .updateSecurityQuestions(
156
167
  patientUuid,
157
168
  recoveryQA.recoverySecurityQuestions,
@@ -159,12 +170,17 @@ export async function registerPatient(
159
170
  2
160
171
  )
161
172
  .catch((err) => {
162
- console.error(`Error while updating security questions`, err)
163
- /// it's acceptable to continue registration
164
- return
173
+ console.error(`[SDK: registration] Error while updating security questions`, err)
174
+ /// it's acceptable to continue registration (return old identity)
175
+ if (retry <= 1) return
176
+ errorsThrown.push(err)
177
+ return identity
165
178
  })
166
179
 
167
- await Promise.all([...grantPromises, ...consultIndexPromises, ...deprecatedConsultIndexPromises])
180
+ await Promise.all([...grantPromises, ...consultIndexPromises])
181
+
182
+ if (errorsThrown.length > 0)
183
+ throw errorsThrown
168
184
 
169
185
  // Deem the consultation as ready
170
186
  await oroClient.consultClient.updateConsultByUUID(consult.uuid, {
@@ -174,13 +190,14 @@ export async function registerPatient(
174
190
  // if we got through the complete flow, the registration succeeded
175
191
  break
176
192
  } catch (err) {
177
- console.error(`Error occured during registration, retrying... Retries remaining: ${retry}`)
193
+ console.error(`[SDK] Error occured during registration: ${err}, retrying... Retries remaining: ${retry}`)
194
+ errorsThrown = []
178
195
  continue
179
196
  }
180
197
  }
181
198
 
182
199
  if (retry <= 0) {
183
- console.error('registration failed: MAX_RETRIES reached')
200
+ console.error('[SDK] registration failed: MAX_RETRIES reached')
184
201
  throw 'RegistrationFailed'
185
202
  }
186
203
 
@@ -193,28 +210,6 @@ export async function registerPatient(
193
210
  }
194
211
  }
195
212
 
196
- /**
197
- * Returns whether the consultation creation is for an existing patient (ignores data from the current consultation)
198
- *
199
- * @param currentConsultation
200
- */
201
- async function patientConsultExists(
202
- currentConsultation: Consult,
203
- lockboxUuid: Uuid,
204
- oroClient: OroClient
205
- ): Promise<boolean> {
206
- let publicMetadata: ConsultationMeta = {
207
- category: MetadataCategory.Consultation,
208
- documentType: DocumentType.PopulatedWorkflowData,
209
- }
210
- let manifest = await oroClient.vaultClient.lockboxMetadataGet(lockboxUuid, ['consultationId'], [], publicMetadata)
211
- return (
212
- manifest[0].findIndex(
213
- (v: { consultationId: Uuid }) => v.consultationId != null && v.consultationId !== currentConsultation.uuid
214
- ) !== -1
215
- )
216
- }
217
-
218
213
  /**
219
214
  * Creates a consultation if one has not been created and fails to be retrieved by the payment intent
220
215
  * @param consult
@@ -276,9 +271,6 @@ async function storePatientData(
276
271
  ): Promise<(Uuid | void)[]> {
277
272
  // Create and store registration data
278
273
  return Promise.all([
279
- storeImageAliases(consultationId, lockboxUuid, workflow, oroClient).catch((err) => {
280
- console.error('[SDK] Some errors happened during image upload', err)
281
- }),
282
274
  // Storing Raw data first
283
275
  oroClient.getOrInsertJsonData<RawConsultationMeta>(
284
276
  lockboxUuid,