@healthcloudai/hc-login-connector 0.2.0 → 0.3.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/README.md +275 -77
- package/dist/index.cjs +322 -223
- package/dist/index.d.cts +102 -60
- package/dist/index.d.ts +102 -60
- package/dist/index.js +327 -234
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ below follow the current behavior implemented in `src/client.ts`.
|
|
|
19
19
|
6. Password reset initiation and password reset confirmation
|
|
20
20
|
7. Access token, ID token, tenant, and base URL helper methods
|
|
21
21
|
8. Token refresh using the stored refresh token
|
|
22
|
-
9. Authenticated patient header retrieval through `
|
|
22
|
+
9. Authenticated patient header retrieval through `getPatientHeader()`
|
|
23
23
|
10. Built on the shared Healthcheck HttpClient layer
|
|
24
24
|
|
|
25
25
|
---
|
|
@@ -114,7 +114,7 @@ The usage example above reads the value from local state.
|
|
|
114
114
|
`getBaseUrl()` returns the currently configured base URL from local state.
|
|
115
115
|
|
|
116
116
|
```txt
|
|
117
|
-
https://dev-api-healthcheck.healthcloud-services.com
|
|
117
|
+
https://dev-api-healthcheck.healthcloud-services.com
|
|
118
118
|
```
|
|
119
119
|
|
|
120
120
|
---
|
|
@@ -242,10 +242,14 @@ strings. If a field needs to contain multiple values, serialize those values int
|
|
|
242
242
|
one string value, such as a comma separated list or another separator-separated
|
|
243
243
|
list expected by the integration.
|
|
244
244
|
|
|
245
|
-
`
|
|
245
|
+
`isOTP` is a dedicated boolean option that controls whether `User.Attributes.VERIFY_EMAIL_CODE` is included in the registration payload, depending on whether email verification should be handled through an OTP code.
|
|
246
246
|
|
|
247
|
-
- If `
|
|
248
|
-
- If `
|
|
247
|
+
- If `isOTP` is `true`, the client sends `VERIFY_EMAIL_CODE: "true"`.
|
|
248
|
+
- If `isOTP` is `false` or omitted, `VERIFY_EMAIL_CODE` is not sent.
|
|
249
|
+
|
|
250
|
+
#### OTP-based registration
|
|
251
|
+
|
|
252
|
+
Use this when email verification should be handled through an OTP code. In this case, `isOTP` should be `true`.
|
|
249
253
|
|
|
250
254
|
```ts
|
|
251
255
|
await loginClient.register(
|
|
@@ -254,7 +258,7 @@ await loginClient.register(
|
|
|
254
258
|
"John",
|
|
255
259
|
"Smith",
|
|
256
260
|
{
|
|
257
|
-
|
|
261
|
+
isOTP: true,
|
|
258
262
|
attributes: {
|
|
259
263
|
Specialty: "Cardiology",
|
|
260
264
|
NPINumber: "1234567890",
|
|
@@ -268,7 +272,7 @@ await loginClient.register(
|
|
|
268
272
|
```
|
|
269
273
|
|
|
270
274
|
#### Full API request
|
|
271
|
-
Request sent for the
|
|
275
|
+
Request sent for the OTP example above:
|
|
272
276
|
|
|
273
277
|
```json
|
|
274
278
|
{
|
|
@@ -295,6 +299,39 @@ Request sent for the usage example above:
|
|
|
295
299
|
}
|
|
296
300
|
```
|
|
297
301
|
|
|
302
|
+
#### Link-based registration
|
|
303
|
+
|
|
304
|
+
Use this when email verification should be handled through an email link. In this case, `isOTP` should be omitted or `false`.
|
|
305
|
+
|
|
306
|
+
```ts
|
|
307
|
+
await loginClient.register(
|
|
308
|
+
"john.smith@example.com",
|
|
309
|
+
"ExamplePassword123!",
|
|
310
|
+
"John",
|
|
311
|
+
"Smith"
|
|
312
|
+
);
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Effective request body:
|
|
316
|
+
|
|
317
|
+
```json
|
|
318
|
+
{
|
|
319
|
+
"Data": {
|
|
320
|
+
"TenantID": "test-tenant",
|
|
321
|
+
"Credentials": {
|
|
322
|
+
"Email": "john.smith@example.com",
|
|
323
|
+
"Password": "ExamplePassword123!"
|
|
324
|
+
},
|
|
325
|
+
"User": {
|
|
326
|
+
"FirstName": "John",
|
|
327
|
+
"LastName": "Smith",
|
|
328
|
+
"Email": "john.smith@example.com",
|
|
329
|
+
"Attributes": {}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
298
335
|
#### API response
|
|
299
336
|
|
|
300
337
|
Status:
|
|
@@ -317,7 +354,7 @@ Notes:
|
|
|
317
354
|
- `attributes` is the extension point for arbitrary additional registration fields.
|
|
318
355
|
- The module does not need to know custom attribute names in advance.
|
|
319
356
|
- All `attributes` values should be strings. Multi-value attributes should be serialized into one string value, such as a comma separated list or another integration-specific separator-separated list.
|
|
320
|
-
- `
|
|
357
|
+
- `isOTP` takes precedence over any manually provided `VERIFY_EMAIL_CODE` inside `attributes`.
|
|
321
358
|
|
|
322
359
|
---
|
|
323
360
|
|
|
@@ -329,9 +366,13 @@ Registers a patient for the configured tenant using the richer registration payl
|
|
|
329
366
|
|
|
330
367
|
`TenantID` is injected internally from `configure(...)`.
|
|
331
368
|
|
|
332
|
-
`
|
|
369
|
+
`isOTP` behaves the same way as in `register(...)`:
|
|
333
370
|
when enabled, the client injects `VERIFY_EMAIL_CODE: "true"` into `User.Attributes`.
|
|
334
371
|
|
|
372
|
+
#### OTP-based registration
|
|
373
|
+
|
|
374
|
+
Use this when email verification should be handled through an OTP code. In this case, `isOTP` should be `true`.
|
|
375
|
+
|
|
335
376
|
```ts
|
|
336
377
|
await loginClient.registerFull({
|
|
337
378
|
email: "john.smith@example.com",
|
|
@@ -348,7 +389,7 @@ await loginClient.registerFull({
|
|
|
348
389
|
genderIdentity: "Male",
|
|
349
390
|
status: 0,
|
|
350
391
|
language: "en",
|
|
351
|
-
|
|
392
|
+
isOTP: true,
|
|
352
393
|
attributes: {
|
|
353
394
|
source: "sdk-test"
|
|
354
395
|
},
|
|
@@ -406,6 +447,40 @@ Request sent for the usage example above:
|
|
|
406
447
|
}
|
|
407
448
|
```
|
|
408
449
|
|
|
450
|
+
#### Link-based registration
|
|
451
|
+
|
|
452
|
+
Use this when email verification should be handled through an email link. In this case, `isOTP` should be omitted or `false`.
|
|
453
|
+
|
|
454
|
+
```ts
|
|
455
|
+
await loginClient.registerFull({
|
|
456
|
+
email: "john.smith@example.com",
|
|
457
|
+
password: "ExamplePassword123!",
|
|
458
|
+
firstName: "John",
|
|
459
|
+
lastName: "Smith"
|
|
460
|
+
});
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
Effective request body:
|
|
464
|
+
|
|
465
|
+
```json
|
|
466
|
+
{
|
|
467
|
+
"Data": {
|
|
468
|
+
"TenantID": "test-tenant",
|
|
469
|
+
"Credentials": {
|
|
470
|
+
"Email": "john.smith@example.com",
|
|
471
|
+
"Password": "ExamplePassword123!",
|
|
472
|
+
"TenantID": "test-tenant"
|
|
473
|
+
},
|
|
474
|
+
"User": {
|
|
475
|
+
"FirstName": "John",
|
|
476
|
+
"LastName": "Smith",
|
|
477
|
+
"Email": "john.smith@example.com",
|
|
478
|
+
"Attributes": {}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
409
484
|
#### API response
|
|
410
485
|
|
|
411
486
|
Status:
|
|
@@ -435,24 +510,28 @@ verification settings.
|
|
|
435
510
|
when email verification should be handled through an OTP code, the client sends
|
|
436
511
|
`VERIFY_EMAIL_CODE: "true"` inside `User.Attributes`.
|
|
437
512
|
|
|
438
|
-
- If `options.
|
|
439
|
-
- The value is sent as a string inside `User.Attributes`, matching the `register(...)` method behavior when `
|
|
440
|
-
- If `options.
|
|
513
|
+
- If `options.isOTP` is `true`, the client sends `VERIFY_EMAIL_CODE: "true"`.
|
|
514
|
+
- The value is sent as a string inside `User.Attributes`, matching the `register(...)` method behavior when `isOTP` is `true`.
|
|
515
|
+
- If `options.isOTP` is `false` or omitted, `VERIFY_EMAIL_CODE` is not sent.
|
|
441
516
|
- Calling `verifyEmail(...)` without `options` keeps OTP email verification disabled by default.
|
|
442
517
|
|
|
518
|
+
#### OTP-based email verification
|
|
519
|
+
|
|
520
|
+
Use this when email verification should be handled through an OTP code. In this case, `options.isOTP` should be `true`.
|
|
521
|
+
|
|
443
522
|
```ts
|
|
444
523
|
await loginClient.verifyEmail(
|
|
445
524
|
"john.smith@example.com",
|
|
446
525
|
"123456",
|
|
447
526
|
"en",
|
|
448
527
|
{
|
|
449
|
-
|
|
528
|
+
isOTP: true
|
|
450
529
|
}
|
|
451
530
|
);
|
|
452
531
|
```
|
|
453
532
|
|
|
454
533
|
#### Full API request
|
|
455
|
-
Request sent for the
|
|
534
|
+
Request sent for the OTP example above:
|
|
456
535
|
|
|
457
536
|
```json
|
|
458
537
|
{
|
|
@@ -471,6 +550,34 @@ Request sent for the usage example above:
|
|
|
471
550
|
}
|
|
472
551
|
```
|
|
473
552
|
|
|
553
|
+
#### Link-based email verification
|
|
554
|
+
|
|
555
|
+
Use this when email verification should be handled through an email link. In this case, `options.isOTP` should be omitted or `false`.
|
|
556
|
+
|
|
557
|
+
```ts
|
|
558
|
+
await loginClient.verifyEmail(
|
|
559
|
+
"john.smith@example.com",
|
|
560
|
+
"123456",
|
|
561
|
+
"en"
|
|
562
|
+
);
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
Effective request body:
|
|
566
|
+
|
|
567
|
+
```json
|
|
568
|
+
{
|
|
569
|
+
"Data": {
|
|
570
|
+
"Data": "123456",
|
|
571
|
+
"Step": "EMAIL_VERIFY",
|
|
572
|
+
"User": {
|
|
573
|
+
"Email": "john.smith@example.com",
|
|
574
|
+
"TenantID": "test-tenant"
|
|
575
|
+
},
|
|
576
|
+
"Language": "en"
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
```
|
|
580
|
+
|
|
474
581
|
#### API response
|
|
475
582
|
|
|
476
583
|
Status:
|
|
@@ -500,23 +607,27 @@ settings.
|
|
|
500
607
|
when email verification should be handled through an OTP code, the client sends
|
|
501
608
|
`VERIFY_EMAIL_CODE: "true"` inside `User.Attributes`.
|
|
502
609
|
|
|
503
|
-
- If `options.
|
|
504
|
-
- The value is sent as a string inside `User.Attributes`, matching the `register(...)` method behavior when `
|
|
505
|
-
- If `options.
|
|
610
|
+
- If `options.isOTP` is `true`, the client sends `VERIFY_EMAIL_CODE: "true"`.
|
|
611
|
+
- The value is sent as a string inside `User.Attributes`, matching the `register(...)` method behavior when `isOTP` is `true`.
|
|
612
|
+
- If `options.isOTP` is `false` or omitted, `VERIFY_EMAIL_CODE` is not sent.
|
|
506
613
|
- Calling `resendEmailVerify(...)` without `options` keeps OTP email verification disabled by default.
|
|
507
614
|
|
|
615
|
+
#### OTP-based resend
|
|
616
|
+
|
|
617
|
+
Use this when email verification should be handled through an OTP code. In this case, `options.isOTP` should be `true`.
|
|
618
|
+
|
|
508
619
|
```ts
|
|
509
620
|
await loginClient.resendEmailVerify(
|
|
510
621
|
"john.smith@example.com",
|
|
511
622
|
"en",
|
|
512
623
|
{
|
|
513
|
-
|
|
624
|
+
isOTP: true
|
|
514
625
|
}
|
|
515
626
|
);
|
|
516
627
|
```
|
|
517
628
|
|
|
518
629
|
#### Full API request
|
|
519
|
-
Request sent for the
|
|
630
|
+
Request sent for the OTP example above:
|
|
520
631
|
|
|
521
632
|
```json
|
|
522
633
|
{
|
|
@@ -535,6 +646,33 @@ Request sent for the usage example above:
|
|
|
535
646
|
}
|
|
536
647
|
```
|
|
537
648
|
|
|
649
|
+
#### Link-based resend
|
|
650
|
+
|
|
651
|
+
Use this when email verification should be handled through an email link. In this case, `options.isOTP` should be omitted or `false`.
|
|
652
|
+
|
|
653
|
+
```ts
|
|
654
|
+
await loginClient.resendEmailVerify(
|
|
655
|
+
"john.smith@example.com",
|
|
656
|
+
"en"
|
|
657
|
+
);
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
Effective request body:
|
|
661
|
+
|
|
662
|
+
```json
|
|
663
|
+
{
|
|
664
|
+
"Data": {
|
|
665
|
+
"Data": "",
|
|
666
|
+
"Step": "RESEND_EMAIL_VERIFY",
|
|
667
|
+
"User": {
|
|
668
|
+
"Email": "john.smith@example.com",
|
|
669
|
+
"TenantID": "test-tenant"
|
|
670
|
+
},
|
|
671
|
+
"Language": "en"
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
```
|
|
675
|
+
|
|
538
676
|
#### API response
|
|
539
677
|
|
|
540
678
|
Status:
|
|
@@ -851,20 +989,20 @@ Status:
|
|
|
851
989
|
|
|
852
990
|
### Reset Password
|
|
853
991
|
|
|
854
|
-
`
|
|
992
|
+
`requestPasswordReset` supports both OTP-based and link-based reset initiation
|
|
855
993
|
flows.
|
|
856
994
|
|
|
857
|
-
`
|
|
858
|
-
|
|
859
|
-
|
|
995
|
+
`isOTP` is optional. When it is `true`, the client includes
|
|
996
|
+
`IsPasswordResetWithOTP: true` in the API request. When `false` or omitted, the
|
|
997
|
+
backend field is not sent at all.
|
|
860
998
|
|
|
861
999
|
#### OTP-based password reset initiation
|
|
862
1000
|
|
|
863
1001
|
Use this when the password reset flow should be handled through an OTP code.
|
|
864
|
-
In this case, `
|
|
1002
|
+
In this case, `isOTP` should be `true`.
|
|
865
1003
|
|
|
866
1004
|
```ts
|
|
867
|
-
await loginClient.
|
|
1005
|
+
await loginClient.requestPasswordReset("john.smith@example.com", true);
|
|
868
1006
|
```
|
|
869
1007
|
|
|
870
1008
|
#### Full API request
|
|
@@ -882,11 +1020,11 @@ await loginClient.resetPassword("john.smith@example.com", true);
|
|
|
882
1020
|
#### Link-based password reset initiation
|
|
883
1021
|
|
|
884
1022
|
Use this when the password reset flow should be handled from an email link.
|
|
885
|
-
In this case, `
|
|
1023
|
+
In this case, `isOTP` should be omitted by passing `false` or
|
|
886
1024
|
leaving the second argument out.
|
|
887
1025
|
|
|
888
1026
|
```ts
|
|
889
|
-
await loginClient.
|
|
1027
|
+
await loginClient.requestPasswordReset("john.smith@example.com", false);
|
|
890
1028
|
```
|
|
891
1029
|
|
|
892
1030
|
Effective request body:
|
|
@@ -923,28 +1061,27 @@ Status:
|
|
|
923
1061
|
|
|
924
1062
|
### Reset Password Confirm
|
|
925
1063
|
|
|
926
|
-
`
|
|
1064
|
+
`confirmPasswordReset` supports both OTP-based and link-based confirmation
|
|
927
1065
|
flows.
|
|
928
1066
|
|
|
929
|
-
If `
|
|
930
|
-
|
|
931
|
-
link-based flow, the frontend is responsible for taking
|
|
932
|
-
password reset email link and passing that token in the
|
|
1067
|
+
If `isOTP` is `true`, `Code` is required. If `isOTP` is not `true`, `Token` is
|
|
1068
|
+
required. The client maps `isOTP: true` to `IsPasswordResetWithOTP: true` in the
|
|
1069
|
+
API request. For the link-based flow, the frontend is responsible for taking
|
|
1070
|
+
the token from the password reset email link and passing that token in the
|
|
1071
|
+
payload.
|
|
933
1072
|
|
|
934
1073
|
#### OTP-based password reset confirmation
|
|
935
1074
|
|
|
936
1075
|
Use this when the password reset flow was started with OTP. In this case,
|
|
937
|
-
`
|
|
1076
|
+
`isOTP` should be `true` and `Code` should contain the final
|
|
938
1077
|
reset code.
|
|
939
1078
|
|
|
940
1079
|
```ts
|
|
941
|
-
await loginClient.
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
Code: "123456"
|
|
947
|
-
}
|
|
1080
|
+
await loginClient.confirmPasswordReset({
|
|
1081
|
+
Email: "john.smith@example.com",
|
|
1082
|
+
Password: "ExamplePassword123!",
|
|
1083
|
+
isOTP: true,
|
|
1084
|
+
Code: "123456"
|
|
948
1085
|
});
|
|
949
1086
|
```
|
|
950
1087
|
|
|
@@ -967,15 +1104,13 @@ Request body:
|
|
|
967
1104
|
Use this when the password reset flow was started from an email link. In this
|
|
968
1105
|
case, `Token` should be included in the payload, the frontend should read the
|
|
969
1106
|
token value from the password reset email link and send that token in the
|
|
970
|
-
request payload, and `
|
|
1107
|
+
request payload, and `isOTP` should be omitted or `false`.
|
|
971
1108
|
|
|
972
1109
|
```ts
|
|
973
|
-
await loginClient.
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
Token: "token-from-email-link"
|
|
978
|
-
}
|
|
1110
|
+
await loginClient.confirmPasswordReset({
|
|
1111
|
+
Email: "john.smith@example.com",
|
|
1112
|
+
Password: "ExamplePassword123!",
|
|
1113
|
+
Token: "token-from-email-link"
|
|
979
1114
|
});
|
|
980
1115
|
```
|
|
981
1116
|
|
|
@@ -1102,19 +1237,19 @@ If an API key has been configured through setApiKey(...), the returned header ob
|
|
|
1102
1237
|
|
|
1103
1238
|
---
|
|
1104
1239
|
|
|
1105
|
-
### Get
|
|
1240
|
+
### Get Patient Header
|
|
1106
1241
|
|
|
1107
|
-
Public signature: `loginClient.
|
|
1242
|
+
Public signature: `loginClient.getPatientHeader()`
|
|
1108
1243
|
|
|
1109
1244
|
Calls the patient header endpoint and returns the raw server response.
|
|
1110
1245
|
It requires a stored ID token.
|
|
1111
1246
|
|
|
1112
1247
|
```ts
|
|
1113
|
-
const
|
|
1248
|
+
const header = await loginClient.getPatientHeader();
|
|
1114
1249
|
```
|
|
1115
1250
|
|
|
1116
1251
|
#### Full API request
|
|
1117
|
-
`
|
|
1252
|
+
`getPatientHeader()` does not send a request body.
|
|
1118
1253
|
|
|
1119
1254
|
#### API response
|
|
1120
1255
|
|
|
@@ -1128,42 +1263,60 @@ Status:
|
|
|
1128
1263
|
{
|
|
1129
1264
|
"Data": {
|
|
1130
1265
|
"Record": {
|
|
1131
|
-
"
|
|
1132
|
-
"
|
|
1266
|
+
"Status": 1,
|
|
1267
|
+
"Sex": "Male",
|
|
1268
|
+
"GenderIdentity": "Male",
|
|
1269
|
+
"HasInsurance": true,
|
|
1270
|
+
"HasIDCard": true,
|
|
1271
|
+
"HasSelfie": true,
|
|
1272
|
+
"Flags": null,
|
|
1133
1273
|
"FirstName": "John",
|
|
1134
1274
|
"LastName": "Smith",
|
|
1275
|
+
"MiddleName": null,
|
|
1276
|
+
"BirthDate": "1990-01-01T00:00:00",
|
|
1135
1277
|
"Email": "john.smith@example.com",
|
|
1136
1278
|
"Phone": "+15555550123",
|
|
1137
|
-
"
|
|
1138
|
-
"Gender": "male",
|
|
1139
|
-
"Sex": "Male",
|
|
1279
|
+
"Gender": "Male",
|
|
1140
1280
|
"Race": "White",
|
|
1141
|
-
"Ethnicity": "
|
|
1142
|
-
"
|
|
1143
|
-
"
|
|
1144
|
-
"HasSelfie": false,
|
|
1281
|
+
"Ethnicity": "",
|
|
1282
|
+
"CRMID": null,
|
|
1283
|
+
"AppleUserId": null,
|
|
1145
1284
|
"Address": {
|
|
1146
|
-
"StreetAndNumber": "
|
|
1285
|
+
"StreetAndNumber": "1 Main St",
|
|
1147
1286
|
"Extension": null,
|
|
1148
1287
|
"City": "Springfield",
|
|
1149
|
-
"State": "
|
|
1150
|
-
"PostalCode": "
|
|
1288
|
+
"State": "IL",
|
|
1289
|
+
"PostalCode": "62701",
|
|
1151
1290
|
"Country": "US"
|
|
1152
1291
|
},
|
|
1153
1292
|
"Attributes": {
|
|
1154
|
-
"
|
|
1155
|
-
"
|
|
1156
|
-
"
|
|
1293
|
+
"AthenaPatientID": "patient-id-example",
|
|
1294
|
+
"AthenaGuarantorFirstName": "John",
|
|
1295
|
+
"AthenaGuarantorLastName": "Smith",
|
|
1296
|
+
"AthenaGuarantorEmail": "john.smith@example.com",
|
|
1297
|
+
"AthenaCountryCode": "USA",
|
|
1298
|
+
"AthenaDepartmentId": "1",
|
|
1299
|
+
"AthenaEmailExists": "True",
|
|
1300
|
+
"AthenaTestPatient": "False",
|
|
1301
|
+
"PatientImageURL": "https://storage.example.com/selfie_example.jpg",
|
|
1302
|
+
"CompositeID": "tenant-id/john.smith@example.com",
|
|
1303
|
+
"Insurance": "EXAMPLE INSURANCE"
|
|
1157
1304
|
},
|
|
1158
|
-
"CompositeID": "
|
|
1159
|
-
"FHIRID": "fhir-id-example"
|
|
1305
|
+
"CompositeID": "tenant-id/john.smith@example.com",
|
|
1306
|
+
"FHIRID": "fhir-id-example",
|
|
1307
|
+
"AthenaID": "patient-id-example",
|
|
1308
|
+
"Created": "0001-01-01T00:00:00",
|
|
1309
|
+
"Modified": "0001-01-01T00:00:00",
|
|
1310
|
+
"CreatedByID": null,
|
|
1311
|
+
"ModifiedByID": null,
|
|
1312
|
+
"IsDeactivated": false,
|
|
1313
|
+
"TenantID": "test-tenant",
|
|
1314
|
+
"ID": "record-uuid-example"
|
|
1160
1315
|
},
|
|
1161
1316
|
"Encounters": null,
|
|
1162
|
-
"EHR": "
|
|
1317
|
+
"EHR": "athena",
|
|
1163
1318
|
"PendingActions": [
|
|
1164
|
-
"
|
|
1165
|
-
"ADD_ID",
|
|
1166
|
-
"IMPORT_VITALS"
|
|
1319
|
+
"TAKE_TEST"
|
|
1167
1320
|
]
|
|
1168
1321
|
},
|
|
1169
1322
|
"ErrorMessage": null,
|
|
@@ -1231,10 +1384,47 @@ eyJ_id_token_example
|
|
|
1231
1384
|
- Use `submitOnboardingStep(...)` or the onboarding helper methods to complete required onboarding steps.
|
|
1232
1385
|
- Call `login(...)` to authenticate and store the returned access, refresh, and ID tokens in memory.
|
|
1233
1386
|
- Use `refreshToken()` to replace the current token set when a stored refresh token is available.
|
|
1234
|
-
- Use `getAuthHeader()`, `getAccessToken()`, `getIDToken()`, and `
|
|
1387
|
+
- Use `getAuthHeader()`, `getAccessToken()`, `getIDToken()`, and `getPatientHeader()` for authenticated flows after login.
|
|
1235
1388
|
- Other Healthcheck connectors can consume `getAuthHeader()` instead of managing auth tokens directly.
|
|
1236
1389
|
|
|
1237
1390
|
|
|
1391
|
+
## Token Expiry and Refresh
|
|
1392
|
+
|
|
1393
|
+
The SDK does **not** auto-refresh tokens. Call `refreshToken()` proactively when the token is about to expire.
|
|
1394
|
+
|
|
1395
|
+
`getTokens()` returns the current in-memory token set, including `expiresAt` — an absolute Unix millisecond timestamp parsed from the `Expiration` field the backend returns.
|
|
1396
|
+
|
|
1397
|
+
`isTokenExpired()` is a helper that returns `true` when there is no stored token or when `Date.now() >= expiresAt`.
|
|
1398
|
+
|
|
1399
|
+
Recommended pattern:
|
|
1400
|
+
|
|
1401
|
+
```ts
|
|
1402
|
+
async function ensureFreshToken(loginClient: HCLoginClient): Promise<void> {
|
|
1403
|
+
if (loginClient.isTokenExpired()) {
|
|
1404
|
+
await loginClient.refreshToken();
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
// Call before any authenticated connector operation
|
|
1409
|
+
await ensureFreshToken(loginClient);
|
|
1410
|
+
const result = await otherConnector.someMethod();
|
|
1411
|
+
```
|
|
1412
|
+
|
|
1413
|
+
`getTokens()` shape:
|
|
1414
|
+
|
|
1415
|
+
```ts
|
|
1416
|
+
interface AuthTokens {
|
|
1417
|
+
accessToken: string;
|
|
1418
|
+
refreshToken: string;
|
|
1419
|
+
idToken: string | null;
|
|
1420
|
+
expiresAt: number; // absolute milliseconds since Unix epoch
|
|
1421
|
+
}
|
|
1422
|
+
```
|
|
1423
|
+
|
|
1424
|
+
`refreshToken()` does not require a current ID token. It uses the stored refresh token from the previous successful `login()` call.
|
|
1425
|
+
|
|
1426
|
+
---
|
|
1427
|
+
|
|
1238
1428
|
## Notes
|
|
1239
1429
|
|
|
1240
1430
|
- `configure()` stores tenant configuration locally and does not send an HTTP request.
|
|
@@ -1242,7 +1432,15 @@ eyJ_id_token_example
|
|
|
1242
1432
|
- `register()`, `verifyEmail()`, and `resendEmailVerify()` all follow the same string-based `User.Attributes.VERIFY_EMAIL_CODE` pattern for OTP email verification flows.
|
|
1243
1433
|
- `saveAddress()` accepts an `Address`.
|
|
1244
1434
|
- `login()` stores the initial token set internally, and `refreshToken()` updates that stored token set when a refresh token is available.
|
|
1245
|
-
- `
|
|
1246
|
-
- `
|
|
1247
|
-
- `getAuthHeader()`, `getAccessToken()`, `getIDToken()`, `getBaseUrl()`, and `
|
|
1435
|
+
- `getPatientHeader()` calls the patient header endpoint.
|
|
1436
|
+
- `getAuthHeader()` returns `Authorization: Bearer <idToken>` + `X-Tenant-ID`. It does **not** carry an API key — each connector adds its own key independently.
|
|
1437
|
+
- `getAuthHeader()`, `getAccessToken()`, `getIDToken()`, `getBaseUrl()`, `getTenantId()`, `getTokens()`, and `isTokenExpired()` return or evaluate local values and do not perform HTTP requests.
|
|
1248
1438
|
- This connector is intended to be reused by other Healthcheck SDK connectors built on the same HTTP layer.
|
|
1439
|
+
|
|
1440
|
+
---
|
|
1441
|
+
|
|
1442
|
+
## getPatientHeader vs getDashboard
|
|
1443
|
+
|
|
1444
|
+
`HCLoginClient.getPatientHeader()` calls `/api/patient/header` and returns a lightweight patient record plus pending actions. Typically called once after login to check patient state.
|
|
1445
|
+
|
|
1446
|
+
`HCSettingsClient.getDashboard()` (in `hc-settings-connector`) calls `/api/patient/dashboard` and returns a richer dashboard including encounters. These are different endpoints with different response shapes — not duplicates.
|