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/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.0.2",
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.1",
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(patientUuid, consult, workflow, this, this.toolbox.uuid(), recoveryQA, indexSearch, onProgress)
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
- uuid: e.uuid,
382
- timestamp: e.timestamp,
383
- uniqueHash: e.uniqueHash,
384
- encryptedIndexEntry: CryptoRSA.jsonWithPubEncryptToBase64(
385
- {
386
- consultationId: e.consultationId,
387
- grant: e.grant,
388
- },
389
- rsaPub
390
- ),
391
- } as EncryptedIndexEntry)
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 = Meta>(
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
- return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)
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 = Metadata>(
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 = Meta>(
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
- return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)
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 ([OtherRoleType.Patient, OtherRoleType.User].every(requiredRole => currentAccountRole.includes(requiredRole))) {
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?: (progress: number, descriptionKey: string, extraInfo?: { storedImagesNum?: number, totalImagesNum?: number }) => void
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((currentStep++)/stepsTotalNum, 'retrieve_practitioners')
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((currentStep++)/stepsTotalNum, 'create_consult')
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((currentStep++)/stepsTotalNum, 'create_lockbox')
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((currentStep++)/stepsTotalNum, 'grant_patient')
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
- onProgress,
167
- currentStep,
168
- stepsTotalNum
169
- } : undefined
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((currentStep++)/stepsTotalNum, 'store_patient_data')
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((currentStep++)/stepsTotalNum, 'set_masterkey')
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((currentStep++)/stepsTotalNum, 'set_security_questions')
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((currentStep++)/stepsTotalNum, 'success')
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
- await oroClient.vaultClient.lockboxCreate().catch((err) => {
311
- console.error('Error while creating lockbox', err)
312
- throw err
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: (progress: number, descriptionKey: string, extraInfo?: { storedImagesNum?: number; totalImagesNum?: number }) => void;
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', {storedImagesNum, totalImagesNum})
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.getOrInsertJsonData<ConsultationImageMeta>(
435
- lockboxUuid,
436
- image,
437
- {
438
- category: MetadataCategory.Consultation,
439
- documentType: DocumentType.ImageAlias,
440
- consultationId,
441
- idbId: image.idbId as string,
442
- },
443
- {}
444
- ).then(() => {
445
- if (progress) {
446
- ++storedImagesNum
447
- let progressStepValue = Math.round((((progress.currentStep + 1)/progress.stepsTotalNum) - (progress.currentStep/progress.stepsTotalNum)) * 100) / 100
448
- progress.onProgress(
449
- (progress.currentStep/progress.stepsTotalNum) + (progressStepValue * (storedImagesNum/totalImagesNum)),
450
- 'store_images',
451
- {
452
- storedImagesNum,
453
- totalImagesNum
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
+ }