oro-sdk 5.0.2 → 5.2.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/dist/client.d.ts +11 -7
- package/dist/oro-sdk.cjs.development.js +1134 -672
- package/dist/oro-sdk.cjs.development.js.map +1 -1
- package/dist/oro-sdk.cjs.production.min.js +1 -1
- package/dist/oro-sdk.cjs.production.min.js.map +1 -1
- package/dist/oro-sdk.esm.js +1134 -672
- package/dist/oro-sdk.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/client.ts +57 -34
- package/src/helpers/patient-registration.ts +72 -52
package/package.json
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
"version": "5.0
|
2
|
+
"version": "5.2.0",
|
3
3
|
"main": "dist/index.js",
|
4
4
|
"typings": "dist/index.d.ts",
|
5
5
|
"files": [
|
@@ -55,7 +55,7 @@
|
|
55
55
|
"form-data": "^4.0.0",
|
56
56
|
"formdata-node": "^4.3.1",
|
57
57
|
"idb-keyval": "^5.0.6",
|
58
|
-
"oro-sdk-apis": "3.0
|
58
|
+
"oro-sdk-apis": "3.1.0",
|
59
59
|
"oro-toolbox": "0.0.6",
|
60
60
|
"uuid": "^8.3.2"
|
61
61
|
}
|
package/src/client.ts
CHANGED
@@ -88,7 +88,7 @@ export class OroClient {
|
|
88
88
|
public workflowClient: WorkflowService,
|
89
89
|
public diagnosisClient: DiagnosisService,
|
90
90
|
private authenticationCallback?: (err: Error) => void
|
91
|
-
) {
|
91
|
+
) {}
|
92
92
|
|
93
93
|
/**
|
94
94
|
* clears the vaultIndex and cached metadata grants
|
@@ -300,7 +300,16 @@ export class OroClient {
|
|
300
300
|
onProgress?: (progress: number, descriptionKey: string) => void
|
301
301
|
): Promise<RegisterPatientOutput> {
|
302
302
|
if (!this.rsa) throw IncompleteAuthentication
|
303
|
-
return registerPatient(
|
303
|
+
return registerPatient(
|
304
|
+
patientUuid,
|
305
|
+
consult,
|
306
|
+
workflow,
|
307
|
+
this,
|
308
|
+
this.toolbox.uuid(),
|
309
|
+
recoveryQA,
|
310
|
+
indexSearch,
|
311
|
+
onProgress
|
312
|
+
)
|
304
313
|
}
|
305
314
|
|
306
315
|
/**
|
@@ -377,18 +386,18 @@ export class OroClient {
|
|
377
386
|
}))
|
378
387
|
.map(
|
379
388
|
(e: IndexConsultLockbox) =>
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
389
|
+
({
|
390
|
+
uuid: e.uuid,
|
391
|
+
timestamp: e.timestamp,
|
392
|
+
uniqueHash: e.uniqueHash,
|
393
|
+
encryptedIndexEntry: CryptoRSA.jsonWithPubEncryptToBase64(
|
394
|
+
{
|
395
|
+
consultationId: e.consultationId,
|
396
|
+
grant: e.grant,
|
397
|
+
},
|
398
|
+
rsaPub
|
399
|
+
),
|
400
|
+
} as EncryptedIndexEntry)
|
392
401
|
)
|
393
402
|
break
|
394
403
|
}
|
@@ -513,6 +522,7 @@ export class OroClient {
|
|
513
522
|
* @param category the category for the attachment data
|
514
523
|
* @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)
|
515
524
|
* @param previousDataUuid if it's a revision of existing file, specify the previous data uuid
|
525
|
+
* @param withNotification if the insertion of data requires notification
|
516
526
|
* @returns the data uuid
|
517
527
|
*/
|
518
528
|
public async createConsultationAttachmentData(
|
@@ -521,7 +531,8 @@ export class OroClient {
|
|
521
531
|
consultationId: string,
|
522
532
|
documentType: DocumentType,
|
523
533
|
lockboxOwnerUuid?: Uuid,
|
524
|
-
previousDataUuid?: Uuid
|
534
|
+
previousDataUuid?: Uuid,
|
535
|
+
withNotification: boolean = false
|
525
536
|
): Promise<DataCreateResponse> {
|
526
537
|
if (!this.rsa) throw IncompleteAuthentication
|
527
538
|
|
@@ -539,7 +550,8 @@ export class OroClient {
|
|
539
550
|
fileName: data.name,
|
540
551
|
},
|
541
552
|
lockboxOwnerUuid,
|
542
|
-
previousDataUuid
|
553
|
+
previousDataUuid,
|
554
|
+
withNotification
|
543
555
|
)
|
544
556
|
}
|
545
557
|
|
@@ -552,15 +564,17 @@ export class OroClient {
|
|
552
564
|
* @param privateMeta the metadata that will be secured in the vault
|
553
565
|
* @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)
|
554
566
|
* @param previousDataUuid if it's a revision of existing data, specify the previous data uuid
|
567
|
+
* @param withNotification if the insertion of data requires notification
|
555
568
|
* @returns the data uuid
|
556
569
|
*/
|
557
|
-
public async createJsonData<T
|
570
|
+
public async createJsonData<T extends Metadata>(
|
558
571
|
lockboxUuid: Uuid,
|
559
572
|
data: any,
|
560
573
|
meta?: T,
|
561
574
|
privateMeta?: { [val: string]: any },
|
562
575
|
lockboxOwnerUuid?: Uuid,
|
563
|
-
previousDataUuid?: Uuid
|
576
|
+
previousDataUuid?: Uuid,
|
577
|
+
withNotification: boolean = false
|
564
578
|
): Promise<DataCreateResponse> {
|
565
579
|
if (!this.rsa) throw IncompleteAuthentication
|
566
580
|
|
@@ -573,8 +587,9 @@ export class OroClient {
|
|
573
587
|
publicMetadata: meta,
|
574
588
|
privateMetadata: encryptedPrivateMeta,
|
575
589
|
}
|
576
|
-
|
577
|
-
|
590
|
+
if (withNotification)
|
591
|
+
return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)
|
592
|
+
else return this.vaultClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)
|
578
593
|
}
|
579
594
|
|
580
595
|
/**
|
@@ -584,14 +599,16 @@ export class OroClient {
|
|
584
599
|
* @param publicMetadata the public Metadata
|
585
600
|
* @param privateMetadata the private Metadata
|
586
601
|
* @param forceReplace set true when the insertion of data requires to replace the data when it exists already
|
602
|
+
* @param withNotification if the insertion of data requires notification
|
587
603
|
* @returns the data uuid
|
588
604
|
*/
|
589
|
-
public async getOrInsertJsonData<M
|
605
|
+
public async getOrInsertJsonData<M extends Metadata>(
|
590
606
|
lockboxUuid: Uuid,
|
591
607
|
data: any,
|
592
608
|
publicMetadata: M,
|
593
609
|
privateMetadata: Metadata,
|
594
|
-
forceReplace: boolean = false
|
610
|
+
forceReplace: boolean = false,
|
611
|
+
withNotification: boolean = false
|
595
612
|
): Promise<Uuid> {
|
596
613
|
let manifest = await this.vaultClient.lockboxManifestGet(lockboxUuid, publicMetadata)
|
597
614
|
if (!forceReplace && manifest.length > 0) {
|
@@ -605,7 +622,8 @@ export class OroClient {
|
|
605
622
|
publicMetadata,
|
606
623
|
privateMetadata,
|
607
624
|
undefined,
|
608
|
-
forceReplace && manifest.length > 0 ? manifest[0].dataUuid : undefined // if forceReplace and data already exist, then replace data. Otherwise insert it
|
625
|
+
forceReplace && manifest.length > 0 ? manifest[0].dataUuid : undefined, // if forceReplace and data already exist, then replace data. Otherwise insert it
|
626
|
+
withNotification
|
609
627
|
).catch((err) => {
|
610
628
|
console.error(`Error while upserting data ${JSON.stringify(publicMetadata)} data`, err)
|
611
629
|
throw err
|
@@ -622,15 +640,17 @@ export class OroClient {
|
|
622
640
|
* @param privateMeta the metadata that will be secured in the vault
|
623
641
|
* @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)
|
624
642
|
* @param previousDataUuid if it's a revision of existing data, specify the previous data uuid
|
643
|
+
* @param withNotification if the insertion of data requires notification
|
625
644
|
* @returns the data uuid
|
626
645
|
*/
|
627
|
-
public async createBytesData<T
|
646
|
+
public async createBytesData<T extends Metadata>(
|
628
647
|
lockboxUuid: Uuid,
|
629
648
|
data: Uint8Array,
|
630
649
|
meta: T,
|
631
650
|
privateMeta: { [val: string]: any },
|
632
651
|
lockboxOwnerUuid?: Uuid,
|
633
|
-
previousDataUuid?: Uuid
|
652
|
+
previousDataUuid?: Uuid,
|
653
|
+
withNotification: boolean = false
|
634
654
|
): Promise<DataCreateResponse> {
|
635
655
|
if (!this.rsa) throw IncompleteAuthentication
|
636
656
|
let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)
|
@@ -642,8 +662,9 @@ export class OroClient {
|
|
642
662
|
publicMetadata: meta,
|
643
663
|
privateMetadata: encryptedPrivateMeta,
|
644
664
|
}
|
645
|
-
|
646
|
-
|
665
|
+
if (withNotification)
|
666
|
+
return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)
|
667
|
+
else return this.vaultClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)
|
647
668
|
}
|
648
669
|
|
649
670
|
/**
|
@@ -704,10 +725,13 @@ export class OroClient {
|
|
704
725
|
|
705
726
|
// We're using the account role to determine the way a grant is accessed
|
706
727
|
let currentAccountRole = await this.getAccountRole()
|
707
|
-
if (currentAccountRole.length === 1 && currentAccountRole[0] === OtherRoleType.User)
|
708
|
-
return []
|
728
|
+
if (currentAccountRole.length === 1 && currentAccountRole[0] === OtherRoleType.User) return []
|
709
729
|
|
710
|
-
if (
|
730
|
+
if (
|
731
|
+
[OtherRoleType.Patient, OtherRoleType.User].every((requiredRole) =>
|
732
|
+
currentAccountRole.includes(requiredRole)
|
733
|
+
)
|
734
|
+
) {
|
711
735
|
let encryptedGrants
|
712
736
|
// if there are no grants with the applied filter from index, attempt for naive filter with backwards compatibility
|
713
737
|
if (filter) {
|
@@ -722,8 +746,7 @@ export class OroClient {
|
|
722
746
|
return decryptedGrants
|
723
747
|
}
|
724
748
|
// if not a patient, then a practitioner is trying to retrieve a grant, it **Must** contain a filter, otherwise too many grants are possible
|
725
|
-
if (!filter)
|
726
|
-
throw MissingGrantFilter
|
749
|
+
if (!filter) throw MissingGrantFilter
|
727
750
|
// Note: will work only if the filter being applied is exclusively a consult id
|
728
751
|
const grantsByConsultLockbox = await this.vaultClient
|
729
752
|
.vaultIndexGet([IndexKey.ConsultationLockbox], [filter.consultationId])
|
@@ -746,7 +769,7 @@ export class OroClient {
|
|
746
769
|
|
747
770
|
/**
|
748
771
|
* Fetches the role of the account that is logged in
|
749
|
-
*
|
772
|
+
*
|
750
773
|
* @returns the role based scopes defined by the whoami
|
751
774
|
*/
|
752
775
|
async getAccountRole(): Promise<RoleBasedScopes[]> {
|
@@ -1515,4 +1538,4 @@ export class OroClient {
|
|
1515
1538
|
|
1516
1539
|
return updatedIdentity
|
1517
1540
|
}
|
1518
|
-
}
|
1541
|
+
}
|
@@ -65,7 +65,11 @@ export async function registerPatient(
|
|
65
65
|
recoverySecurityAnswers: string[]
|
66
66
|
},
|
67
67
|
indexSearch: boolean = true,
|
68
|
-
onProgress?: (
|
68
|
+
onProgress?: (
|
69
|
+
progress: number,
|
70
|
+
descriptionKey: string,
|
71
|
+
extraInfo?: { storedImagesNum?: number; totalImagesNum?: number }
|
72
|
+
) => void
|
69
73
|
): Promise<RegisterPatientOutput> {
|
70
74
|
let consult: Consult | undefined = undefined
|
71
75
|
let lockboxUuid: Uuid | undefined = undefined
|
@@ -80,8 +84,7 @@ export async function registerPatient(
|
|
80
84
|
try {
|
81
85
|
currentStep = 0
|
82
86
|
|
83
|
-
if (onProgress) onProgress(
|
84
|
-
|
87
|
+
if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'retrieve_practitioners')
|
85
88
|
|
86
89
|
// Wait a bit each retry (we also want the first one to wait)
|
87
90
|
await new Promise((resolve) => setTimeout(resolve, 2000))
|
@@ -99,14 +102,14 @@ export async function registerPatient(
|
|
99
102
|
})
|
100
103
|
|
101
104
|
// Creating consult
|
102
|
-
if (onProgress) onProgress(
|
105
|
+
if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'create_consult')
|
103
106
|
|
104
107
|
if (!consult) {
|
105
108
|
consult = await getOrCreatePatientConsultationUuid(consultRequest, oroClient)
|
106
109
|
}
|
107
110
|
|
108
111
|
// Creating lockbox
|
109
|
-
if (onProgress) onProgress(
|
112
|
+
if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'create_lockbox')
|
110
113
|
|
111
114
|
if (!lockboxUuid) lockboxUuid = await getOrCreatePatientLockbox(oroClient)
|
112
115
|
|
@@ -119,7 +122,7 @@ export async function registerPatient(
|
|
119
122
|
})
|
120
123
|
|
121
124
|
// Patient Grant to practice
|
122
|
-
if (onProgress) onProgress(
|
125
|
+
if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'grant_patient')
|
123
126
|
|
124
127
|
let grantPromises = practitioners
|
125
128
|
.filter((practitioner) => practitioner.uuid !== practitionerAdmin)
|
@@ -162,11 +165,13 @@ export async function registerPatient(
|
|
162
165
|
lockboxUuid,
|
163
166
|
workflow,
|
164
167
|
oroClient,
|
165
|
-
onProgress
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
168
|
+
onProgress
|
169
|
+
? {
|
170
|
+
onProgress,
|
171
|
+
currentStep,
|
172
|
+
stepsTotalNum,
|
173
|
+
}
|
174
|
+
: undefined
|
170
175
|
).catch((err) => {
|
171
176
|
console.error('[SDK: registration] Some errors happened during image upload', err)
|
172
177
|
// Acceptable to continue as images can be requested during the consultation, but we should still retry until the last retry remains
|
@@ -175,7 +180,7 @@ export async function registerPatient(
|
|
175
180
|
})
|
176
181
|
++currentStep
|
177
182
|
|
178
|
-
if (onProgress) onProgress(
|
183
|
+
if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'store_patient_data')
|
179
184
|
|
180
185
|
await storePatientData(
|
181
186
|
consult.uuid,
|
@@ -188,7 +193,7 @@ export async function registerPatient(
|
|
188
193
|
errorsThrown.push(err)
|
189
194
|
})
|
190
195
|
|
191
|
-
if (onProgress) onProgress(
|
196
|
+
if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'set_masterkey')
|
192
197
|
|
193
198
|
if (masterKey && !identity?.recoveryMasterKey) {
|
194
199
|
// generate and store recovery payload and updates the identity
|
@@ -204,7 +209,7 @@ export async function registerPatient(
|
|
204
209
|
masterKey = undefined
|
205
210
|
}
|
206
211
|
|
207
|
-
if (onProgress) onProgress(
|
212
|
+
if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'set_security_questions')
|
208
213
|
|
209
214
|
if (recoveryQA && !identity?.recoverySecurityQuestions)
|
210
215
|
// Patient security question recovery threshold is 2 answers and updates the identity
|
@@ -225,8 +230,7 @@ export async function registerPatient(
|
|
225
230
|
|
226
231
|
await Promise.all([...grantPromises, ...consultIndexPromises])
|
227
232
|
|
228
|
-
|
229
|
-
if (onProgress) onProgress((currentStep++)/stepsTotalNum, 'search_indexing')
|
233
|
+
if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'search_indexing')
|
230
234
|
|
231
235
|
if (indexSearch) {
|
232
236
|
await buildConsultSearchIndex(consult, workflow, oroClient).catch((err) => {
|
@@ -247,7 +251,7 @@ export async function registerPatient(
|
|
247
251
|
})
|
248
252
|
|
249
253
|
// if we got through the complete flow, the registration succeeded
|
250
|
-
if (onProgress) onProgress(
|
254
|
+
if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'success')
|
251
255
|
|
252
256
|
break
|
253
257
|
} catch (err) {
|
@@ -306,11 +310,10 @@ async function getOrCreatePatientLockbox(oroClient: OroClient): Promise<Uuid> {
|
|
306
310
|
console.log('The grant has already been created, skipping lockbox create step')
|
307
311
|
return grants[0].lockboxUuid!
|
308
312
|
} else {
|
309
|
-
let lockboxResponse =
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
})
|
313
|
+
let lockboxResponse = await oroClient.vaultClient.lockboxCreate().catch((err) => {
|
314
|
+
console.error('Error while creating lockbox', err)
|
315
|
+
throw err
|
316
|
+
})
|
314
317
|
// Since the creation of a lockbox will change the scope of a user, we will force refresh the tokens
|
315
318
|
let tokens = await oroClient.guardClient.authRefresh()
|
316
319
|
await oroClient.guardClient.setTokens({ accessToken: tokens.accessToken, refreshToken: tokens.refreshToken })
|
@@ -358,7 +361,9 @@ async function storePatientData(
|
|
358
361
|
documentType: DocumentType.PopulatedWorkflowData,
|
359
362
|
consultationId, // TODO: deprecated. Will finally only be in privateMetadata
|
360
363
|
},
|
361
|
-
{ consultationId }
|
364
|
+
{ consultationId },
|
365
|
+
false,
|
366
|
+
true // the only data that needs to include an email notification
|
362
367
|
)
|
363
368
|
),
|
364
369
|
getWorkflowDataByCategory(workflow, MetadataCategory.Medical).then((data) =>
|
@@ -412,9 +417,13 @@ async function storeImageAliases(
|
|
412
417
|
workflow: WorkflowData,
|
413
418
|
oroClient: OroClient,
|
414
419
|
progress?: {
|
415
|
-
currentStep: number
|
416
|
-
stepsTotalNum: number
|
417
|
-
onProgress: (
|
420
|
+
currentStep: number
|
421
|
+
stepsTotalNum: number
|
422
|
+
onProgress: (
|
423
|
+
progress: number,
|
424
|
+
descriptionKey: string,
|
425
|
+
extraInfo?: { storedImagesNum?: number; totalImagesNum?: number }
|
426
|
+
) => void
|
418
427
|
}
|
419
428
|
): Promise<(Uuid | void)[]> {
|
420
429
|
const images = await getImagesFromIndexDb((await filterTriggeredAnsweredWithKind(workflow, 'images-alias')).flat())
|
@@ -428,33 +437,44 @@ async function storeImageAliases(
|
|
428
437
|
let storedImagesNum = 0
|
429
438
|
let totalImagesNum = nonNullImages.length
|
430
439
|
if (progress)
|
431
|
-
progress.onProgress(progress.currentStep/progress.stepsTotalNum, 'store_images', {
|
440
|
+
progress.onProgress(progress.currentStep / progress.stepsTotalNum, 'store_images', {
|
441
|
+
storedImagesNum,
|
442
|
+
totalImagesNum,
|
443
|
+
})
|
432
444
|
|
433
445
|
let promises = nonNullImages.map((image) => {
|
434
|
-
return oroClient
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
446
|
+
return oroClient
|
447
|
+
.getOrInsertJsonData<ConsultationImageMeta>(
|
448
|
+
lockboxUuid,
|
449
|
+
image,
|
450
|
+
{
|
451
|
+
category: MetadataCategory.Consultation,
|
452
|
+
documentType: DocumentType.ImageAlias,
|
453
|
+
consultationId,
|
454
|
+
idbId: image.idbId as string,
|
455
|
+
},
|
456
|
+
{}
|
457
|
+
)
|
458
|
+
.then(() => {
|
459
|
+
if (progress) {
|
460
|
+
++storedImagesNum
|
461
|
+
let progressStepValue =
|
462
|
+
Math.round(
|
463
|
+
((progress.currentStep + 1) / progress.stepsTotalNum -
|
464
|
+
progress.currentStep / progress.stepsTotalNum) *
|
465
|
+
100
|
466
|
+
) / 100
|
467
|
+
progress.onProgress(
|
468
|
+
progress.currentStep / progress.stepsTotalNum +
|
469
|
+
progressStepValue * (storedImagesNum / totalImagesNum),
|
470
|
+
'store_images',
|
471
|
+
{
|
472
|
+
storedImagesNum,
|
473
|
+
totalImagesNum,
|
474
|
+
}
|
475
|
+
)
|
476
|
+
}
|
477
|
+
})
|
458
478
|
})
|
459
479
|
return Promise.all(promises)
|
460
480
|
}
|
@@ -580,4 +600,4 @@ export async function buildConsultSearchIndex(consult: Consult, workflow: Workfl
|
|
580
600
|
}
|
581
601
|
|
582
602
|
await oroClient.searchClient.index(consult.uuid, terms)
|
583
|
-
}
|
603
|
+
}
|