oro-sdk 3.4.0 → 3.6.1

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,61 +1,61 @@
1
1
  {
2
- "version": "3.4.0",
3
- "main": "dist/index.js",
4
- "typings": "dist/index.d.ts",
5
- "files": [
6
- "dist",
7
- "src"
8
- ],
9
- "engines": {
10
- "node": ">=10",
11
- "npm": ">=6.14.13"
12
- },
13
- "scripts": {
14
- "link:watch": "npm link && tsdx watch",
15
- "link:watch:apis": "npm link oro-sdk-apis && npm link && tsdx watch",
16
- "start": "tsdx watch",
17
- "build": "tsdx build",
18
- "test": "tsdx test",
19
- "lint": "tsdx lint",
20
- "prepare": "tsdx build",
21
- "size": "size-limit",
22
- "analyze": "size-limit --why",
23
- "package": "tsdx build && npm publish",
24
- "pretty": "prettier --config ../../.prettierrc.yaml --write './src/**/*.{ts,js,json,md}' && prettier --write './*.md'"
25
- },
26
- "name": "oro-sdk",
27
- "author": "Antoine Jaouën <antoine@orohealth.me>",
28
- "module": "dist/oro-sdk.esm.js",
29
- "description": "This package is intended to be run in browser only. It contains everything needed to interact with backend services, especially the vault",
30
- "size-limit": [
31
- {
32
- "path": "dist/oro-sdk.cjs.production.min.js",
33
- "limit": "10 KB"
2
+ "version": "3.6.1",
3
+ "main": "dist/index.js",
4
+ "typings": "dist/index.d.ts",
5
+ "files": [
6
+ "dist",
7
+ "src"
8
+ ],
9
+ "engines": {
10
+ "node": ">=10",
11
+ "npm": ">=6.14.13"
34
12
  },
35
- {
36
- "path": "dist/oro-sdk.esm.js",
37
- "limit": "10 KB"
13
+ "scripts": {
14
+ "link:watch": "npm link && tsdx watch",
15
+ "link:watch:apis": "npm link oro-sdk-apis && npm link && tsdx watch",
16
+ "start": "tsdx watch",
17
+ "build": "tsdx build",
18
+ "test": "tsdx test",
19
+ "lint": "tsdx lint",
20
+ "prepare": "tsdx build",
21
+ "size": "size-limit",
22
+ "analyze": "size-limit --why",
23
+ "package": "tsdx build && npm publish",
24
+ "pretty": "prettier --config ../../.prettierrc.yaml --write './src/**/*.{ts,js,json,md}' && prettier --write './*.md'"
25
+ },
26
+ "name": "oro-sdk",
27
+ "author": "Antoine Jaouën <antoine@orohealth.me>",
28
+ "module": "dist/oro-sdk.esm.js",
29
+ "description": "This package is intended to be run in browser only. It contains everything needed to interact with backend services, especially the vault",
30
+ "size-limit": [
31
+ {
32
+ "path": "dist/oro-sdk.cjs.production.min.js",
33
+ "limit": "10 KB"
34
+ },
35
+ {
36
+ "path": "dist/oro-sdk.esm.js",
37
+ "limit": "10 KB"
38
+ }
39
+ ],
40
+ "devDependencies": {
41
+ "@size-limit/preset-small-lib": "^4.10.2",
42
+ "@types/jest": "^27.4.1",
43
+ "@types/uuid": "^8.3.0",
44
+ "prettier": "^2.5.1",
45
+ "prettier-plugin-svelte": "^2.3.0",
46
+ "size-limit": "^4.10.2",
47
+ "tsdx": "^0.14.1",
48
+ "tslib": "^2.2.0",
49
+ "typescript": "^4.2.4"
50
+ },
51
+ "dependencies": {
52
+ "axios": "^0.21.4",
53
+ "axios-auth-refresh": "^3.2.1",
54
+ "form-data": "^4.0.0",
55
+ "formdata-node": "^4.3.1",
56
+ "idb-keyval": "^5.0.6",
57
+ "oro-sdk-apis": "1.41.0",
58
+ "oro-toolbox": "0.0.6",
59
+ "uuid": "^8.3.2"
38
60
  }
39
- ],
40
- "devDependencies": {
41
- "@size-limit/preset-small-lib": "^4.10.2",
42
- "@types/jest": "^27.4.1",
43
- "@types/uuid": "^8.3.0",
44
- "prettier": "^2.5.1",
45
- "prettier-plugin-svelte": "^2.3.0",
46
- "size-limit": "^4.10.2",
47
- "tsdx": "^0.14.1",
48
- "tslib": "^2.2.0",
49
- "typescript": "^4.2.4"
50
- },
51
- "dependencies": {
52
- "axios": "^0.21.4",
53
- "axios-auth-refresh": "^3.2.1",
54
- "form-data": "^4.0.0",
55
- "formdata-node": "^4.3.1",
56
- "idb-keyval": "^5.0.6",
57
- "oro-sdk-apis": "1.40.0",
58
- "oro-toolbox": "0.0.6",
59
- "uuid": "^8.3.2"
60
- }
61
- }
61
+ }
package/src/client.ts CHANGED
@@ -83,7 +83,7 @@ export class OroClient {
83
83
  public workflowClient: WorkflowService,
84
84
  public diagnosisClient: DiagnosisService,
85
85
  private authenticationCallback?: (err: Error) => void
86
- ) { }
86
+ ) {}
87
87
 
88
88
  /**
89
89
  * clears the vaultIndex and cached metadata grants
@@ -280,6 +280,7 @@ export class OroClient {
280
280
  * @param consult
281
281
  * @param workflow
282
282
  * @param recoveryQA
283
+ * @param indexSearch create search index for the consultation if true
283
284
  * @returns
284
285
  */
285
286
  public async registerPatient(
@@ -289,10 +290,11 @@ export class OroClient {
289
290
  recoveryQA?: {
290
291
  recoverySecurityQuestions: string[]
291
292
  recoverySecurityAnswers: string[]
292
- }
293
+ },
294
+ indexSearch: boolean = true
293
295
  ): Promise<RegisterPatientOutput> {
294
296
  if (!this.rsa) throw IncompleteAuthentication
295
- return registerPatient(patientUuid, consult, workflow, this, this.toolbox.uuid(), recoveryQA)
297
+ return registerPatient(patientUuid, consult, workflow, this, this.toolbox.uuid(), recoveryQA, indexSearch)
296
298
  }
297
299
 
298
300
  /**
@@ -391,18 +393,18 @@ export class OroClient {
391
393
  }))
392
394
  .map(
393
395
  (e: IndexConsultLockbox) =>
394
- ({
395
- uuid: e.uuid,
396
- timestamp: e.timestamp,
397
- uniqueHash: e.uniqueHash,
398
- encryptedIndexEntry: CryptoRSA.jsonWithPubEncryptToBase64(
399
- {
400
- consultationId: e.consultationId,
401
- grant: e.grant,
402
- },
403
- rsaPub
404
- ),
405
- } as EncryptedIndexEntry)
396
+ ({
397
+ uuid: e.uuid,
398
+ timestamp: e.timestamp,
399
+ uniqueHash: e.uniqueHash,
400
+ encryptedIndexEntry: CryptoRSA.jsonWithPubEncryptToBase64(
401
+ {
402
+ consultationId: e.consultationId,
403
+ grant: e.grant,
404
+ },
405
+ rsaPub
406
+ ),
407
+ } as EncryptedIndexEntry)
406
408
  )
407
409
  break
408
410
  //// DEPRECATED : REMOVE ME : BEGIN ///////////////////////////////////////////
@@ -424,18 +426,18 @@ export class OroClient {
424
426
  )
425
427
  .map(
426
428
  (e: IndexConsultLockbox) =>
427
- ({
428
- uuid: e.uuid,
429
- timestamp: e.timestamp,
430
- uniqueHash: e.uniqueHash,
431
- encryptedIndexEntry: CryptoRSA.jsonWithPubEncryptToBase64(
432
- {
433
- consultationId: e.consultationId,
434
- grant: e.grant,
435
- },
436
- rsaPub
437
- ),
438
- } as EncryptedIndexEntry)
429
+ ({
430
+ uuid: e.uuid,
431
+ timestamp: e.timestamp,
432
+ uniqueHash: e.uniqueHash,
433
+ encryptedIndexEntry: CryptoRSA.jsonWithPubEncryptToBase64(
434
+ {
435
+ consultationId: e.consultationId,
436
+ grant: e.grant,
437
+ },
438
+ rsaPub
439
+ ),
440
+ } as EncryptedIndexEntry)
439
441
  )
440
442
  break
441
443
  //// DEPRECATED : REMOVE ME : END ///////////////////////////////////////////
@@ -785,14 +787,15 @@ export class OroClient {
785
787
 
786
788
  // if there is a filter to apply, then the grant can be retrieved from the vault index, otherwise, all grants are fetched
787
789
  // Note: will work only if the filter being applied is exclusively a consult id
788
- const grantsByConsultLockbox = filter ? (
789
- await this.vaultClient.vaultIndexGet([IndexKey.ConsultationLockbox], [filter.consultationId])
790
- .then((res) => res[IndexKey.ConsultationLockbox])
791
- .catch((e) => {
792
- console.error(e)
793
- return []
794
- })
795
- ) : undefined
790
+ const grantsByConsultLockbox = filter
791
+ ? await this.vaultClient
792
+ .vaultIndexGet([IndexKey.ConsultationLockbox], [filter.consultationId])
793
+ .then((res) => res[IndexKey.ConsultationLockbox])
794
+ .catch((e) => {
795
+ console.error(e)
796
+ return []
797
+ })
798
+ : undefined
796
799
  const decryptedConsults = decryptConsultLockboxGrants(grantsByConsultLockbox ?? [], this.rsa)
797
800
  if (decryptedConsults.length > 0) {
798
801
  console.info('[sdk:index] Grants found in user`s constant time secure index')
@@ -27,7 +27,7 @@ import {
27
27
  identificationToPersonalInformations,
28
28
  OroClient,
29
29
  RegisterPatientOutput,
30
- toActualObject
30
+ toActualObject,
31
31
  } from '..'
32
32
 
33
33
  const MAX_RETRIES = 15
@@ -50,6 +50,7 @@ const MAX_RETRIES = 15
50
50
  * @param oroClient
51
51
  * @param masterKey
52
52
  * @param recoveryQA
53
+ * @param indexSearch create search index for the consultation if true
53
54
  * @returns the successful registration
54
55
  */
55
56
  export async function registerPatient(
@@ -61,7 +62,8 @@ export async function registerPatient(
61
62
  recoveryQA?: {
62
63
  recoverySecurityQuestions: string[]
63
64
  recoverySecurityAnswers: string[]
64
- }
65
+ },
66
+ indexSearch: boolean = true
65
67
  ): Promise<RegisterPatientOutput> {
66
68
  let consult: Consult | undefined = undefined
67
69
  let lockboxUuid: Uuid | undefined = undefined
@@ -95,8 +97,7 @@ export async function registerPatient(
95
97
  // Creating lockbox
96
98
  if (!lockboxUuid) lockboxUuid = await getOrCreatePatientLockbox(oroClient)
97
99
 
98
- if (!identity)
99
- identity = await oroClient.guardClient.identityGet(patientUuid)
100
+ if (!identity) identity = await oroClient.guardClient.identityGet(patientUuid)
100
101
 
101
102
  await oroClient.grantLockbox(practitionerAdmin, lockboxUuid).catch((err) => {
102
103
  console.error(`Error while granting lockbox to practitioner admin ${practitionerAdmin}`, err)
@@ -131,14 +132,16 @@ export async function registerPatient(
131
132
  // the index will identify in which lockbox a consultation resides
132
133
  let consultIndexPromises = practitioners.map(async (practitioner) => {
133
134
  return oroClient.vaultIndexAdd(consultIndex, practitioner.uuid).catch((err) => {
134
- console.error(`[SDK: registration] Error while adding to the practitioner's index ${practitioner.uuid}`, err)
135
+ console.error(
136
+ `[SDK: registration] Error while adding to the practitioner's index ${practitioner.uuid}`,
137
+ err
138
+ )
135
139
  // Acceptable to continue as the index can be rebuilt, but we should still retry until the last retry remains
136
140
  if (retry <= 1) return
137
141
  else errorsThrown.push(err)
138
142
  })
139
143
  })
140
144
 
141
-
142
145
  await storeImageAliases(consult.uuid, lockboxUuid, workflow, oroClient).catch((err) => {
143
146
  console.error('[SDK: registration] Some errors happened during image upload', err)
144
147
  // Acceptable to continue as images can be requested during the consultation, but we should still retry until the last retry remains
@@ -146,13 +149,19 @@ export async function registerPatient(
146
149
  else errorsThrown.push(err)
147
150
  })
148
151
 
149
- await storePatientData(consult.uuid, consultRequest.isoLanguageRequired, lockboxUuid, workflow, oroClient).catch((err) => {
152
+ await storePatientData(
153
+ consult.uuid,
154
+ consultRequest.isoLanguageRequired,
155
+ lockboxUuid,
156
+ workflow,
157
+ oroClient
158
+ ).catch((err) => {
150
159
  console.error('[SDK: registration] Some errors happened during patient data upload', err)
151
160
  errorsThrown.push(err)
152
161
  })
153
162
 
154
163
  if (masterKey && !identity?.recoveryMasterKey) {
155
- // generate and store recovery payload and updates the identity
164
+ // generate and store recovery payload and updates the identity
156
165
  identity = await oroClient.updateMasterKey(patientUuid, masterKey, lockboxUuid).catch((err) => {
157
166
  console.error(`[SDK: registration] Error while updating master key`, err)
158
167
  /// it's acceptable to continue registration (return old identity)
@@ -166,7 +175,7 @@ export async function registerPatient(
166
175
  }
167
176
 
168
177
  if (recoveryQA && !identity?.recoverySecurityQuestions)
169
- // Patient security question recovery threshold is 2 answers and updates the identity
178
+ // Patient security question recovery threshold is 2 answers and updates the identity
170
179
  identity = await oroClient
171
180
  .updateSecurityQuestions(
172
181
  patientUuid,
@@ -184,15 +193,19 @@ export async function registerPatient(
184
193
 
185
194
  await Promise.all([...grantPromises, ...consultIndexPromises])
186
195
 
187
- // TODO: uncomment when search is deployed in prod
188
- // await buildConsultSearchIndex(consult, workflow, oroClient).catch((err) => {
189
- // console.error('[SDK: registration] personal information not found or another error occured during search indexing', err)
190
- // 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
191
- // errorsThrown.push(err)
192
- // })
193
196
 
194
- if (errorsThrown.length > 0)
195
- throw errorsThrown
197
+ if(indexSearch) {
198
+ await buildConsultSearchIndex(consult, workflow, oroClient).catch((err) => {
199
+ console.error(
200
+ '[SDK: registration] personal information not found or another error occured during search indexing',
201
+ err
202
+ )
203
+ 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
204
+ errorsThrown.push(err)
205
+ })
206
+ }
207
+
208
+ if (errorsThrown.length > 0) throw errorsThrown
196
209
 
197
210
  // Deem the consultation as ready
198
211
  await oroClient.consultClient.updateConsultByUUID(consult.uuid, {
@@ -417,14 +430,14 @@ export async function extractAndStorePersonalWorkflowData(
417
430
  * @param workflow
418
431
  */
419
432
  export async function extractPersonalInfoFromWorkflowData(workflow: WorkflowData): Promise<{
420
- personalInfoPopulatedWfData: PopulatedWorkflowData,
421
- childPersonalInfoPopulatedWfData: PopulatedWorkflowData,
422
- otherPersonalInfoPopulatedWfData: PopulatedWorkflowData,
433
+ personalInfoPopulatedWfData: PopulatedWorkflowData
434
+ childPersonalInfoPopulatedWfData: PopulatedWorkflowData
435
+ otherPersonalInfoPopulatedWfData: PopulatedWorkflowData
423
436
  }> {
424
437
  return Promise.all([
425
438
  getWorkflowDataByCategory(workflow, MetadataCategory.Personal),
426
439
  getWorkflowDataByCategory(workflow, MetadataCategory.ChildPersonal),
427
- getWorkflowDataByCategory(workflow, MetadataCategory.OtherPersonal)
440
+ getWorkflowDataByCategory(workflow, MetadataCategory.OtherPersonal),
428
441
  ]).then(([personalInfoPopulatedWfData, childPersonalInfoPopulatedWfData, otherPersonalInfoPopulatedWfData]) => {
429
442
  return {
430
443
  personalInfoPopulatedWfData,
@@ -442,17 +455,14 @@ export async function extractPersonalInfoFromWorkflowData(workflow: WorkflowData
442
455
  */
443
456
  export async function buildConsultSearchIndex(consult: Consult, workflow: WorkflowData, oroClient: OroClient) {
444
457
  let terms: Terms = [
445
- <Term> {
458
+ <Term>{
446
459
  kind: 'consult-shortid',
447
- value: consult.shortId
448
- }
460
+ value: consult.shortId,
461
+ },
449
462
  ]
450
463
 
451
- const {
452
- personalInfoPopulatedWfData,
453
- childPersonalInfoPopulatedWfData,
454
- otherPersonalInfoPopulatedWfData
455
- } = await extractPersonalInfoFromWorkflowData(workflow)
464
+ const { personalInfoPopulatedWfData, childPersonalInfoPopulatedWfData, otherPersonalInfoPopulatedWfData } =
465
+ await extractPersonalInfoFromWorkflowData(workflow)
456
466
 
457
467
  const personalInfo = identificationToPersonalInformations(
458
468
  toActualObject(personalInfoPopulatedWfData),
@@ -467,32 +477,41 @@ export async function buildConsultSearchIndex(consult: Consult, workflow: Workfl
467
477
  MetadataCategory.OtherPersonal
468
478
  )
469
479
 
470
- terms.push(<Term>{
471
- kind: 'first-name',
472
- value: personalInfo.firstname,
473
- }, <Term> {
474
- kind: 'last-name',
475
- value: personalInfo.name
476
- })
477
-
478
- if(childPersonalInfo.firstname && childPersonalInfo.name) {
479
- terms.push(<Term>{
480
+ terms.push(
481
+ <Term>{
480
482
  kind: 'first-name',
481
- value: childPersonalInfo.firstname,
482
- }, <Term> {
483
+ value: personalInfo.firstname,
484
+ },
485
+ <Term>{
483
486
  kind: 'last-name',
484
- value: childPersonalInfo.name
485
- })
487
+ value: personalInfo.name,
488
+ }
489
+ )
490
+
491
+ if (childPersonalInfo.firstname && childPersonalInfo.name) {
492
+ terms.push(
493
+ <Term>{
494
+ kind: 'first-name',
495
+ value: childPersonalInfo.firstname,
496
+ },
497
+ <Term>{
498
+ kind: 'last-name',
499
+ value: childPersonalInfo.name,
500
+ }
501
+ )
486
502
  }
487
503
 
488
- if(otherPersonalInfo.firstname && otherPersonalInfo.name) {
489
- terms.push(<Term>{
490
- kind: 'first-name',
491
- value: otherPersonalInfo.firstname,
492
- }, <Term> {
493
- kind: 'last-name',
494
- value: otherPersonalInfo.name
495
- })
504
+ if (otherPersonalInfo.firstname && otherPersonalInfo.name) {
505
+ terms.push(
506
+ <Term>{
507
+ kind: 'first-name',
508
+ value: otherPersonalInfo.firstname,
509
+ },
510
+ <Term>{
511
+ kind: 'last-name',
512
+ value: otherPersonalInfo.name,
513
+ }
514
+ )
496
515
  }
497
516
 
498
517
  await oroClient.searchClient.index(consult.uuid, terms)