oro-sdk 2.1.4-dev1

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.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +72 -0
  3. package/dist/client.d.ts +464 -0
  4. package/dist/helpers/client.d.ts +23 -0
  5. package/dist/helpers/index.d.ts +4 -0
  6. package/dist/helpers/patient-registration.d.ts +16 -0
  7. package/dist/helpers/vault-grants.d.ts +20 -0
  8. package/dist/helpers/workflow.d.ts +23 -0
  9. package/dist/index.d.ts +11 -0
  10. package/dist/index.js +8 -0
  11. package/dist/models/client.d.ts +28 -0
  12. package/dist/models/consult.d.ts +102 -0
  13. package/dist/models/diagnosis.d.ts +122 -0
  14. package/dist/models/error.d.ts +26 -0
  15. package/dist/models/guard.d.ts +119 -0
  16. package/dist/models/index.d.ts +9 -0
  17. package/dist/models/practice.d.ts +353 -0
  18. package/dist/models/shared.d.ts +8 -0
  19. package/dist/models/vault.d.ts +124 -0
  20. package/dist/models/workflow.d.ts +106 -0
  21. package/dist/oro-sdk.cjs.development.js +7685 -0
  22. package/dist/oro-sdk.cjs.development.js.map +1 -0
  23. package/dist/oro-sdk.cjs.production.min.js +2 -0
  24. package/dist/oro-sdk.cjs.production.min.js.map +1 -0
  25. package/dist/oro-sdk.esm.js +7692 -0
  26. package/dist/oro-sdk.esm.js.map +1 -0
  27. package/dist/sdk-revision/client.d.ts +21 -0
  28. package/dist/sdk-revision/index.d.ts +1 -0
  29. package/dist/services/api.d.ts +11 -0
  30. package/dist/services/axios.d.ts +14 -0
  31. package/dist/services/consult.d.ts +54 -0
  32. package/dist/services/diagnosis.d.ts +44 -0
  33. package/dist/services/external/clinia.d.ts +82 -0
  34. package/dist/services/external/index.d.ts +1 -0
  35. package/dist/services/guard.d.ts +92 -0
  36. package/dist/services/index.d.ts +10 -0
  37. package/dist/services/practice.d.ts +100 -0
  38. package/dist/services/teller.d.ts +9 -0
  39. package/dist/services/vault.d.ts +54 -0
  40. package/dist/services/workflow.d.ts +21 -0
  41. package/package.json +63 -0
  42. package/src/client.ts +1843 -0
  43. package/src/helpers/client.ts +199 -0
  44. package/src/helpers/index.ts +4 -0
  45. package/src/helpers/patient-registration.ts +490 -0
  46. package/src/helpers/vault-grants.ts +51 -0
  47. package/src/helpers/workflow.ts +261 -0
  48. package/src/index.ts +61 -0
  49. package/src/models/client.ts +33 -0
  50. package/src/models/consult.ts +110 -0
  51. package/src/models/diagnosis.ts +141 -0
  52. package/src/models/error.ts +13 -0
  53. package/src/models/guard.ts +136 -0
  54. package/src/models/index.ts +9 -0
  55. package/src/models/practice.ts +411 -0
  56. package/src/models/shared.ts +6 -0
  57. package/src/models/vault.ts +158 -0
  58. package/src/models/workflow.ts +142 -0
  59. package/src/sdk-revision/client.ts +62 -0
  60. package/src/sdk-revision/index.ts +1 -0
  61. package/src/services/api.ts +77 -0
  62. package/src/services/axios.ts +91 -0
  63. package/src/services/consult.ts +265 -0
  64. package/src/services/diagnosis.ts +144 -0
  65. package/src/services/external/clinia.ts +133 -0
  66. package/src/services/external/index.ts +1 -0
  67. package/src/services/guard.ts +228 -0
  68. package/src/services/index.ts +10 -0
  69. package/src/services/practice.ts +537 -0
  70. package/src/services/teller.ts +39 -0
  71. package/src/services/vault.ts +178 -0
  72. package/src/services/workflow.ts +36 -0
@@ -0,0 +1,199 @@
1
+ import {
2
+ PopulatedWorkflowData,
3
+ MetadataCategory,
4
+ SelectedAnswersData,
5
+ } from '../models'
6
+ import { PersonalInformations } from '../models/client'
7
+
8
+ const personalMetaToPrefix = {
9
+ [MetadataCategory.Personal]: 'you',
10
+ [MetadataCategory.ChildPersonal]: 'child',
11
+ [MetadataCategory.OtherPersonal]: 'other',
12
+ }
13
+
14
+ /**
15
+ * This function extract PersonalInformations from data input object coming from workflow
16
+ * @param data extracted from WorkflowData
17
+ * @returns PersonalInformations of a patient
18
+ */
19
+ export function identificationToPersonalInformations(
20
+ data: any,
21
+ category:
22
+ | MetadataCategory.Personal
23
+ | MetadataCategory.ChildPersonal
24
+ | MetadataCategory.OtherPersonal
25
+ ): PersonalInformations {
26
+ const prefix = personalMetaToPrefix[category]
27
+
28
+ return {
29
+ birthday: data[`${prefix}Birthday`],
30
+ firstname: data[`${prefix}Firstname`],
31
+ gender: data[`${prefix}Gender`],
32
+ name: data[`${prefix}Name`],
33
+ phone: data[`${prefix}Phone`],
34
+ zip: data[`${prefix}Zip`],
35
+ hid: data[`${prefix}HID`] ?? data[`${prefix}ID`], // This is done for backward compatibility (historically youID was used)
36
+ pharmacy: data[`${prefix}Pharmacy`],
37
+ address: data[`${prefix}Address`],
38
+ }
39
+ }
40
+
41
+ export function toActualObject(data: PopulatedWorkflowData) {
42
+ const ret: any = {}
43
+
44
+ Object.entries(data.fields).forEach(([key, field]) => {
45
+ ret[key] = field.displayedAnswer ? field.displayedAnswer : field.answer
46
+ })
47
+
48
+ return ret
49
+ }
50
+
51
+ /**
52
+ * This function update a PopulatedWorkflowData with PersonalInformations
53
+ * @param infos the personal informations
54
+ * @param data the PopulatedWorkflowData
55
+ * @returns an updated PopulatedWorkflowData
56
+ */
57
+ export function updatePersonalIntoPopulatedWorkflowData(
58
+ infos: PersonalInformations,
59
+ data: PopulatedWorkflowData,
60
+ category:
61
+ | MetadataCategory.Personal
62
+ | MetadataCategory.ChildPersonal
63
+ | MetadataCategory.OtherPersonal
64
+ ) {
65
+ const prefix = personalMetaToPrefix[category]
66
+
67
+ const ret = JSON.parse(JSON.stringify(data)) // deep copy PopulatedWorkflowData
68
+
69
+ if (infos.birthday && ret.fields[`${prefix}Birthday`])
70
+ ret.fields[`${prefix}Birthday`].answer = infos.birthday
71
+ if (infos.firstname && ret.fields[`${prefix}Firstname`])
72
+ ret.fields[`${prefix}Firstname`].answer = infos.firstname
73
+ if (infos.gender && ret.fields[`${prefix}Gender`])
74
+ ret.fields[`${prefix}Gender`].answer = infos.gender
75
+ if (infos.name && ret.fields[`${prefix}Name`])
76
+ ret.fields[`${prefix}Name`].answer = infos.name
77
+ if (infos.phone && ret.fields[`${prefix}Phone`])
78
+ ret.fields[`${prefix}Phone`].answer = infos.phone
79
+ if (infos.zip && ret.fields[`${prefix}Zip`])
80
+ ret.fields[`${prefix}Zip`].answer = infos.zip
81
+ if (infos.hid) {
82
+ if (ret.fields[`${prefix}HID`]) {
83
+ ret.fields[`${prefix}HID`].answer = infos.hid
84
+ } else if (ret.fields[`${prefix}ID`]) {
85
+ // This is done for backward compatibility (historically youID was used)
86
+ ret.fields[`${prefix}ID`].answer = infos.hid
87
+ } else {
88
+ // If does not exist create it
89
+ ret.fields[`${prefix}HID`] = { kind: 'text', answer: infos.hid }
90
+ }
91
+ }
92
+
93
+ return ret
94
+ }
95
+
96
+ /**
97
+ * This function extract an ISO 3166-1 alpha-2 country and subdivision code from data input object coming from workflow
98
+ * @param answers answers from the WorkflowData
99
+ * @returns an ISO 3166 alpha-2 code or undefined
100
+ */
101
+ export function extractISOLocalityForConsult(
102
+ answers?: SelectedAnswersData
103
+ ): string | undefined {
104
+ if (!answers) {
105
+ return undefined
106
+ }
107
+
108
+ const arrAnswersWithLocality = answers
109
+ .flatMap((currentAnswerPage) => {
110
+ const arrCountryFields = Object.keys(currentAnswerPage)
111
+ .filter(
112
+ (workflowFieldName) =>
113
+ workflowFieldName.indexOf('Country') !== -1
114
+ )
115
+ .flat()
116
+ const arrProvinceFields = Object.keys(currentAnswerPage)
117
+ .filter(
118
+ (workflowFieldName) =>
119
+ workflowFieldName.indexOf('Province') !== -1
120
+ )
121
+ .flat()
122
+ const arrConsultLocalFields = Object.keys(currentAnswerPage)
123
+ .filter(
124
+ (workflowFieldName) =>
125
+ workflowFieldName.indexOf('Locality') !== -1
126
+ )
127
+ .flat()
128
+ //returning the actual selected values, skipping if their IDs are more complex than a string
129
+ return [
130
+ ...arrCountryFields.map(
131
+ (currentFieldName) =>
132
+ (typeof currentAnswerPage[currentFieldName] === 'string'
133
+ ? currentAnswerPage[currentFieldName]
134
+ : undefined) as string
135
+ ),
136
+ ...arrProvinceFields.map(
137
+ (currentFieldName) =>
138
+ (typeof currentAnswerPage[currentFieldName] === 'string'
139
+ ? currentAnswerPage[currentFieldName]
140
+ : undefined) as string
141
+ ),
142
+ ...arrConsultLocalFields.map(
143
+ (currentFieldName) =>
144
+ (typeof currentAnswerPage[currentFieldName] === 'string'
145
+ ? currentAnswerPage[currentFieldName]
146
+ : undefined) as string
147
+ ),
148
+ ]
149
+ })
150
+ .filter((item) => item !== undefined)
151
+
152
+ const arrSelectedLocality = arrAnswersWithLocality.filter(
153
+ (currentSelectedLocality) =>
154
+ currentSelectedLocality.startsWith('isoLocalityConsult')
155
+ )
156
+ if (!arrSelectedLocality || arrSelectedLocality.length === 0) {
157
+ console.log('no locality found in ' + arrSelectedLocality)
158
+ return undefined
159
+ }
160
+ //to allow enforcing of an order, we will allow the following pattern in the isoLocalityConsult field name
161
+ // isoLocalityConsult-QC-CA and isoLocalityConsult_1-QC-CA
162
+ // or generally: isoLocalityConsult-<isoValue> or isoLocalityConsult_<priority>-<isoValue>
163
+ const allowedLocalityPatterns = /isoLocalityConsult(?:_(?<indexPriority>\d*))?-(?<isoValue>[a-zA-Z0-9]{2}-[a-zA-Z0-9]{1,3})/
164
+ const finalLocality = arrSelectedLocality.reduce<string | undefined>(
165
+ (finalLocality, currentSelectedLocality) => {
166
+ const extractedSelected = allowedLocalityPatterns.exec(
167
+ currentSelectedLocality
168
+ )
169
+ const [, indexSelectedPriority, isoSelectedValue] =
170
+ extractedSelected ?? []
171
+ if (!finalLocality) {
172
+ return isoSelectedValue
173
+ }
174
+
175
+ const extractedFinal = allowedLocalityPatterns.exec(finalLocality)
176
+ const [, indexFinalPriority, isoFinalValue] = extractedFinal ?? []
177
+ //we only keep the old value if there's priority used
178
+ // and the new value is of lower priority
179
+ if (
180
+ !indexSelectedPriority ||
181
+ (indexFinalPriority &&
182
+ indexFinalPriority > indexSelectedPriority)
183
+ ) {
184
+ return isoFinalValue
185
+ }
186
+
187
+ return isoSelectedValue
188
+ },
189
+ undefined
190
+ )
191
+
192
+ console.log('Picking locality ' + finalLocality)
193
+ return finalLocality
194
+ }
195
+
196
+ const sessionPrivateKeyPrefix = 'sess-pkey'
197
+ export function sessionStorePrivateKeyName(id: string): string {
198
+ return sessionPrivateKeyPrefix + id
199
+ }
@@ -0,0 +1,4 @@
1
+ export * from './client'
2
+ export * from './workflow'
3
+ export * from './patient-registration'
4
+ export * from './vault-grants'
@@ -0,0 +1,490 @@
1
+ import {
2
+ Consult,
3
+ ConsultationImageMeta,
4
+ getImagesFromIndexDb,
5
+ getWorkflowDataByCategory,
6
+ filterTriggeredAnsweredWithKind,
7
+ MedicalStatus,
8
+ OroClient,
9
+ PersonalMeta,
10
+ Practitioner,
11
+ RegisterPatientOutput,
12
+ } from '..'
13
+ import {
14
+ ConsultationMeta,
15
+ ConsultRequest,
16
+ DocumentType,
17
+ IndexKey,
18
+ MedicalMeta,
19
+ MetadataCategory,
20
+ PreferenceMeta,
21
+ RawConsultationMeta,
22
+ Uuid,
23
+ VaultIndex,
24
+ WorkflowData,
25
+ } from '../models'
26
+
27
+ const MAX_RETRIES = 15
28
+
29
+ export async function registerPatient(
30
+ patientUuid: Uuid,
31
+ consultRequest: ConsultRequest,
32
+ workflow: WorkflowData,
33
+ oroClient: OroClient,
34
+ masterKey?: Uuid,
35
+ recoveryQA?: {
36
+ recoverySecurityQuestions: string[]
37
+ recoverySecurityAnswers: string[]
38
+ }
39
+ ): Promise<RegisterPatientOutput> {
40
+ let consult: Consult | undefined = undefined
41
+ let lockboxUuid: Uuid | undefined = undefined
42
+ let practitionerAdmin: Uuid | undefined = undefined
43
+ let retry = MAX_RETRIES
44
+ let isExistingPatient = false
45
+
46
+ for (; retry > 0; retry--) {
47
+ try {
48
+ // Wait a bit each retry (we also want the first one to wait)
49
+ await new Promise((resolve) => setTimeout(resolve, 2000))
50
+
51
+ // Retrieving practitioners
52
+ if (!practitionerAdmin)
53
+ practitionerAdmin = (
54
+ await oroClient.practiceClient.practiceGetFromUuid(
55
+ consultRequest.uuidPractice
56
+ )
57
+ ).uuidAdmin
58
+
59
+ let practitioners: Practitioner[] = await oroClient.practiceClient
60
+ .practiceGetPractitioners(consultRequest.uuidPractice)
61
+ .catch((err) => {
62
+ console.log(`Error retrieving practitioners`, err)
63
+ return []
64
+ })
65
+
66
+ // Creating consult
67
+ if (!consult) {
68
+ consult = await getOrCreatePatientConsultationUuid(
69
+ consultRequest,
70
+ oroClient
71
+ )
72
+ }
73
+
74
+ // Creating lockbox
75
+ if (!lockboxUuid)
76
+ lockboxUuid = await getOrCreatePatientLockbox(oroClient)
77
+
78
+ isExistingPatient = await patientConsultExists(
79
+ consult,
80
+ lockboxUuid,
81
+ oroClient
82
+ ).catch((err) => {
83
+ console.error(`Error when retrieving existing consults ${err}`)
84
+ return false
85
+ })
86
+ await oroClient
87
+ .grantLockbox(practitionerAdmin, lockboxUuid)
88
+ .catch((err) => {
89
+ console.error(
90
+ `Error while granting lockbox to practitioner admin ${practitionerAdmin}`,
91
+ err
92
+ )
93
+ // if we cannot grant to the admin, then the registration will fail
94
+ throw err
95
+ })
96
+
97
+ // Patient Grant to practice
98
+ let grantPromises = practitioners
99
+ .filter(
100
+ (practitioner) => practitioner.uuid !== practitionerAdmin
101
+ )
102
+ .map(async (practitioner) => {
103
+ return oroClient
104
+ .grantLockbox(practitioner.uuid, lockboxUuid!)
105
+ .catch((err) => {
106
+ console.error(
107
+ `Error while granting lockbox to practitioner`,
108
+ err
109
+ )
110
+ // Acceptable to continue as admin has already been granted, but we should still try to retry
111
+ if (retry <= 1) return
112
+ else throw err
113
+ })
114
+ })
115
+
116
+ await storePatientData(
117
+ consult.uuid,
118
+ consultRequest.isoLanguageRequired,
119
+ lockboxUuid,
120
+ workflow,
121
+ oroClient
122
+ )
123
+
124
+ // the index will identify in which lockbox a consultation live
125
+ let consultIndex: VaultIndex = {
126
+ [IndexKey.ConsultationLockbox]: [
127
+ {
128
+ grant: {
129
+ lockboxUuid,
130
+ lockboxOwnerUuid: patientUuid,
131
+ },
132
+ consultationId: consult.uuid,
133
+ },
134
+ ],
135
+ }
136
+
137
+ let consultIndexPromises = practitioners.map(async (practitioner) => {
138
+ return oroClient
139
+ .vaultIndexAdd(consultIndex, practitioner.uuid)
140
+ .catch((err) => {
141
+ console.error(
142
+ `Error while adding to the practitioner's index ${practitioner.uuid}`,
143
+ err
144
+ )
145
+ /// it's acceptable to continue registration
146
+ return
147
+ })
148
+ })
149
+
150
+
151
+ //DEPRECATED: REMOVE ME : BEGIN /////////////////////////////////////////
152
+
153
+ let deprecatedConsultIndex: VaultIndex = {
154
+ [IndexKey.Consultation]: [
155
+ {
156
+ grant: {
157
+ lockboxUuid,
158
+ lockboxOwnerUuid: patientUuid,
159
+ },
160
+ consultationId: consult.uuid,
161
+ },
162
+ ],
163
+ }
164
+
165
+ let deprecatedConsultIndexPromises = practitioners.map(async (practitioner) => {
166
+ return oroClient
167
+ .vaultIndexAdd(deprecatedConsultIndex, practitioner.uuid)
168
+ .catch((err) => {
169
+ console.error(
170
+ `Error while adding to the practitioner's index ${practitioner.uuid}`,
171
+ err
172
+ )
173
+ /// it's acceptable to continue registration
174
+ return
175
+ })
176
+ })
177
+
178
+ //DEPRECATED: REMOVE ME : END /////////////////////////////////////////
179
+
180
+
181
+ if (masterKey && !isExistingPatient) {
182
+ // generate and store recovery payload
183
+ await oroClient
184
+ .updateMasterKey(patientUuid, masterKey, lockboxUuid)
185
+ .catch((err) => {
186
+ console.error(`Error while updating master key`, err)
187
+ /// it's acceptable to continue registration
188
+ return
189
+ })
190
+ } else {
191
+ // we did not set the master key so we do not return it
192
+ masterKey = undefined
193
+ }
194
+
195
+ if (recoveryQA && !isExistingPatient)
196
+ // Patient security question recovery threshold is 2 answers
197
+ await oroClient
198
+ .updateSecurityQuestions(
199
+ patientUuid,
200
+ recoveryQA.recoverySecurityQuestions,
201
+ recoveryQA.recoverySecurityAnswers,
202
+ 2
203
+ )
204
+ .catch((err) => {
205
+ console.error(
206
+ `Error while updating security questions`,
207
+ err
208
+ )
209
+ /// it's acceptable to continue registration
210
+ return
211
+ })
212
+
213
+ await Promise.all([...grantPromises, ...consultIndexPromises, ...deprecatedConsultIndexPromises])
214
+
215
+ // Deem the consultation as ready
216
+ await oroClient.consultClient.updateConsultByUUID(consult.uuid, {
217
+ statusMedical: MedicalStatus.New,
218
+ })
219
+
220
+ // if we got through the complete flow, the registration succeeded
221
+ break
222
+ } catch (err) {
223
+ console.error(
224
+ `Error occured during registration, retrying... Retries remaining: ${retry}`
225
+ )
226
+ continue
227
+ }
228
+ }
229
+
230
+ if (retry <= 0) {
231
+ console.error('registration failed: MAX_RETRIES reached')
232
+ throw 'RegistrationFailed'
233
+ }
234
+
235
+ console.log('Successfully Registered')
236
+ await oroClient.cleanIndex()
237
+ return {
238
+ masterKey,
239
+ consultationId: consult!.uuid,
240
+ lockboxUuid: lockboxUuid!,
241
+ }
242
+ }
243
+
244
+ /**
245
+ * Returns whether the consultation creation is for an existing patient (ignores data from the current consultation)
246
+ *
247
+ * @param currentConsultation
248
+ */
249
+ async function patientConsultExists(
250
+ currentConsultation: Consult,
251
+ lockboxUuid: Uuid,
252
+ oroClient: OroClient
253
+ ): Promise<boolean> {
254
+ let publicMetadata: ConsultationMeta = {
255
+ category: MetadataCategory.Consultation,
256
+ documentType: DocumentType.PopulatedWorkflowData,
257
+ }
258
+ let manifest = await oroClient.vaultClient.lockboxMetadataGet(
259
+ lockboxUuid,
260
+ ['consultationId'],
261
+ [],
262
+ publicMetadata
263
+ )
264
+ return (
265
+ manifest[0].findIndex(
266
+ (v: { consultationId: Uuid }) =>
267
+ v.consultationId != null &&
268
+ v.consultationId !== currentConsultation.uuid
269
+ ) !== -1
270
+ )
271
+ }
272
+
273
+ /**
274
+ * Creates a consultation if one has not been created and fails to be retrieved by the payment intent
275
+ * @param consult
276
+ * @param oroClient
277
+ * @returns the consult Uuid
278
+ */
279
+ async function getOrCreatePatientConsultationUuid(
280
+ consult: ConsultRequest,
281
+ oroClient: OroClient
282
+ ): Promise<Consult> {
283
+ let payment = await oroClient.practiceClient.practiceGetPayment(
284
+ consult.uuidPractice,
285
+ consult.idStripeInvoiceOrPaymentIntent
286
+ )
287
+ if (payment && payment.uuidConsult) {
288
+ return oroClient.consultClient
289
+ .getConsultByUUID(payment.uuidConsult)
290
+ .catch((err) => {
291
+ console.error('Error while retrieving consult', err)
292
+ throw err
293
+ })
294
+ } else {
295
+ return await oroClient.consultClient
296
+ .consultCreate(consult)
297
+ .catch((err) => {
298
+ console.error('Error while creating consult', err)
299
+ throw err
300
+ })
301
+ }
302
+ }
303
+
304
+ /**
305
+ * Creates a new lockbox for the patient if they do not have any, otherwise, use the first (and only one)
306
+ * @param oroClient
307
+ * @returns the lockbox Uuid
308
+ */
309
+ async function getOrCreatePatientLockbox(oroClient: OroClient): Promise<Uuid> {
310
+ let grants = await oroClient.getGrants(undefined, true)
311
+ if (grants.length > 0) {
312
+ console.log(
313
+ 'The grant has already been created, skipping lockbox create step'
314
+ )
315
+ return grants[0].lockboxUuid!
316
+ } else
317
+ return (
318
+ await oroClient.vaultClient.lockboxCreate().catch((err) => {
319
+ console.error('Error while creating lockbox', err)
320
+ throw err
321
+ })
322
+ ).lockboxUuid
323
+ }
324
+
325
+ /**
326
+ * Store all patient related information into his/her lockbox
327
+ * @param consultationId The consultation id
328
+ * @param isoLanguage the prefered language of communication (ISO 639-3 https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes)
329
+ * @param lockboxUuid the lockbox uuid to store data in
330
+ * @param workflow the workflow used to extract informations
331
+ * @param oroClient an oroClient instance
332
+ * @returns
333
+ */
334
+ async function storePatientData(
335
+ consultationId: Uuid,
336
+ isoLanguage: string,
337
+ lockboxUuid: Uuid,
338
+ workflow: WorkflowData,
339
+ oroClient: OroClient
340
+ ): Promise<(Uuid | void)[]> {
341
+ // Create and store registration data
342
+ return Promise.all([
343
+ storeImageAliases(
344
+ consultationId,
345
+ lockboxUuid,
346
+ workflow,
347
+ oroClient
348
+ ).catch((err) => {
349
+ console.error('[SDK] Some errors happened during image upload', err)
350
+ }),
351
+ // Storing Raw data first
352
+ oroClient.getOrInsertJsonData<RawConsultationMeta>(
353
+ lockboxUuid,
354
+ workflow,
355
+ {
356
+ category: MetadataCategory.Raw,
357
+ contentType: 'application/json',
358
+ consultationId,
359
+ },
360
+ {}
361
+ ),
362
+ getWorkflowDataByCategory(workflow, MetadataCategory.Consultation).then(
363
+ (data) =>
364
+ oroClient.getOrInsertJsonData<ConsultationMeta>(
365
+ lockboxUuid,
366
+ data,
367
+ {
368
+ category: MetadataCategory.Consultation,
369
+ documentType: DocumentType.PopulatedWorkflowData,
370
+ consultationId, // TODO: deprecated. Will finally only be in privateMetadata
371
+ },
372
+ { consultationId }
373
+ )
374
+ ),
375
+ getWorkflowDataByCategory(workflow, MetadataCategory.Medical).then(
376
+ (data) =>
377
+ oroClient.getOrInsertJsonData<MedicalMeta>(
378
+ lockboxUuid,
379
+ data,
380
+ {
381
+ category: MetadataCategory.Medical,
382
+ documentType: DocumentType.PopulatedWorkflowData,
383
+ consultationIds: [consultationId!],
384
+ },
385
+ {}
386
+ )
387
+ ),
388
+ extractAndStorePersonalWorkflowData(
389
+ workflow,
390
+ lockboxUuid,
391
+ consultationId,
392
+ MetadataCategory.Personal,
393
+ oroClient
394
+ ),
395
+ extractAndStorePersonalWorkflowData(
396
+ workflow,
397
+ lockboxUuid,
398
+ consultationId,
399
+ MetadataCategory.ChildPersonal,
400
+ oroClient
401
+ ),
402
+ extractAndStorePersonalWorkflowData(
403
+ workflow,
404
+ lockboxUuid,
405
+ consultationId,
406
+ MetadataCategory.OtherPersonal,
407
+ oroClient
408
+ ),
409
+ oroClient.getOrInsertJsonData<PreferenceMeta>(
410
+ lockboxUuid,
411
+ { isoLanguage },
412
+ {
413
+ category: MetadataCategory.Preference,
414
+ contentType: 'application/json',
415
+ },
416
+ {}
417
+ ),
418
+ ]).then((dataUuids) => dataUuids.flat())
419
+ }
420
+
421
+ async function storeImageAliases(
422
+ consultationId: Uuid,
423
+ lockboxUuid: Uuid,
424
+ workflow: WorkflowData,
425
+ oroClient: OroClient
426
+ ): Promise<(Uuid | void)[]> {
427
+ const images = await getImagesFromIndexDb(
428
+ (await filterTriggeredAnsweredWithKind(workflow, 'images-alias')).flat()
429
+ )
430
+
431
+ const nonNullImages = images.filter((img) => !!img)
432
+
433
+ if (images.length !== nonNullImages.length) {
434
+ console.error(
435
+ '[SDK] Some images have not been found, they have been skipped.'
436
+ )
437
+ }
438
+
439
+ let promises = nonNullImages.map((image) => {
440
+ return oroClient.getOrInsertJsonData<ConsultationImageMeta>(
441
+ lockboxUuid,
442
+ image,
443
+ {
444
+ category: MetadataCategory.Consultation,
445
+ documentType: DocumentType.ImageAlias,
446
+ consultationId,
447
+ idbId: image.idbId as string,
448
+ },
449
+ {}
450
+ )
451
+ })
452
+ return Promise.all(promises)
453
+ }
454
+
455
+ /**
456
+ * Extracts the workflow MetadataCategory for Personal, ChildPersonal and OtherPersonal
457
+ * then stores it in the vault
458
+ *
459
+ * @param workflow
460
+ * @param lockboxUuid
461
+ * @param category
462
+ * @returns The data uuid
463
+ */
464
+ export async function extractAndStorePersonalWorkflowData(
465
+ workflow: WorkflowData,
466
+ lockboxUuid: Uuid,
467
+ consultationId: Uuid,
468
+ category:
469
+ | MetadataCategory.Personal
470
+ | MetadataCategory.ChildPersonal
471
+ | MetadataCategory.OtherPersonal,
472
+ oroClient: OroClient
473
+ ): Promise<Uuid | void> {
474
+ return getWorkflowDataByCategory(
475
+ workflow,
476
+ (category as unknown) as MetadataCategory
477
+ ).then((data) => {
478
+ if (Object.keys(data.fields).length === 0) return
479
+ return oroClient.getOrInsertJsonData<PersonalMeta>(
480
+ lockboxUuid,
481
+ data,
482
+ {
483
+ category,
484
+ documentType: DocumentType.PopulatedWorkflowData,
485
+ consultationIds: [consultationId],
486
+ },
487
+ {}
488
+ )
489
+ })
490
+ }