oro-sdk 3.4.0 → 3.6.1

Sign up to get free protection for your applications and to get access to all the features.
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)