@healthcloudai/hc-login-connector 0.0.13 → 0.0.15
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 +131 -136
- package/dist/index.cjs +41 -38
- package/dist/index.d.cts +31 -16
- package/dist/index.d.ts +31 -16
- package/dist/index.js +41 -38
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,8 +18,8 @@ below follow the current behavior implemented in `src/client.ts`.
|
|
|
18
18
|
5. Patient login with in-memory access, refresh, and ID token storage
|
|
19
19
|
6. Password reset initiation and password reset confirmation
|
|
20
20
|
7. Access token, ID token, tenant, and base URL helper methods
|
|
21
|
-
8. Token refresh using the
|
|
22
|
-
9. Authenticated patient header retrieval through `getUserInfo()`
|
|
21
|
+
8. Token refresh using the stored refresh token
|
|
22
|
+
9. Authenticated patient header retrieval through `getUserInfo()`
|
|
23
23
|
10. Built on the shared Healthcheck HttpClient layer
|
|
24
24
|
|
|
25
25
|
---
|
|
@@ -71,9 +71,27 @@ The configuration example above updates local client state only.
|
|
|
71
71
|
It stores the tenant configuration locally for later requests.
|
|
72
72
|
|
|
73
73
|
|
|
74
|
-
|
|
75
74
|
---
|
|
76
75
|
|
|
76
|
+
|
|
77
|
+
## API Key
|
|
78
|
+
|
|
79
|
+
Use `setApiKey(...)` to include an API key header with requests made by `HCLoginClient`.
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
const apiKey = process.env.HEALTHCLOUD_API_KEY;
|
|
83
|
+
|
|
84
|
+
if (!apiKey) {
|
|
85
|
+
throw new Error("HEALTHCLOUD_API_KEY is required.");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
loginClient.setApiKey("x-api-key", apiKey);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The first argument is the header name and the second argument is the API key value. After it is configured, the API key header is included automatically with registration, onboarding, login, token refresh, password reset, and authenticated patient header requests.
|
|
92
|
+
|
|
93
|
+
If your environment does not require an API key, you can skip this step.
|
|
94
|
+
|
|
77
95
|
## Methods
|
|
78
96
|
|
|
79
97
|
### Get Base URL
|
|
@@ -388,7 +406,7 @@ Request sent for the usage example above:
|
|
|
388
406
|
}
|
|
389
407
|
```
|
|
390
408
|
|
|
391
|
-
####
|
|
409
|
+
#### API response
|
|
392
410
|
|
|
393
411
|
Status:
|
|
394
412
|
|
|
@@ -770,7 +788,7 @@ Status:
|
|
|
770
788
|
Public signature: `loginClient.login(email, password)`
|
|
771
789
|
|
|
772
790
|
`login(...)` accepts only `email` and `password`.
|
|
773
|
-
The client builds the
|
|
791
|
+
The client builds the login `Data` payload internally, and stores the
|
|
774
792
|
returned tokens in memory.
|
|
775
793
|
On tenants that require onboarding completion, login may depend on the relevant
|
|
776
794
|
onboarding steps already being finished.
|
|
@@ -783,20 +801,14 @@ await loginClient.login(
|
|
|
783
801
|
```
|
|
784
802
|
|
|
785
803
|
#### Full API request
|
|
786
|
-
Request sent for the usage example above:
|
|
804
|
+
Request sent for the full payload usage example above:
|
|
787
805
|
|
|
788
806
|
```json
|
|
789
807
|
{
|
|
790
808
|
"Data": {
|
|
791
|
-
"FirstName": "",
|
|
792
|
-
"LastName": "",
|
|
793
809
|
"Email": "john.smith@example.com",
|
|
794
810
|
"Password": "ExamplePassword123!",
|
|
795
|
-
"TenantID": "test-tenant"
|
|
796
|
-
"AppPoolID": "",
|
|
797
|
-
"GoogleIdToken": "",
|
|
798
|
-
"AppleIdToken": "",
|
|
799
|
-
"AppleCode": ""
|
|
811
|
+
"TenantID": "test-tenant"
|
|
800
812
|
}
|
|
801
813
|
}
|
|
802
814
|
```
|
|
@@ -817,12 +829,15 @@ Status:
|
|
|
817
829
|
"AccessToken": "eyJ_access_token_example",
|
|
818
830
|
"IDToken": "eyJ_id_token_example",
|
|
819
831
|
"EHR": "fhir",
|
|
832
|
+
"ErrorMessage": null,
|
|
820
833
|
"HasInsurance": false,
|
|
821
834
|
"HasIDCard": false,
|
|
822
835
|
"HasSelfie": false,
|
|
823
836
|
"Attributes": {
|
|
824
|
-
"EHR": "fhir"
|
|
837
|
+
"EHR": "fhir",
|
|
838
|
+
"Type": "PATIENT"
|
|
825
839
|
},
|
|
840
|
+
"ID": "john.smith@example.com",
|
|
826
841
|
"TenantID": "test-tenant",
|
|
827
842
|
"Expiration": "2030-01-01T00:00:00.000Z",
|
|
828
843
|
"Type": 0
|
|
@@ -836,21 +851,23 @@ Status:
|
|
|
836
851
|
|
|
837
852
|
### Reset Password
|
|
838
853
|
|
|
839
|
-
|
|
854
|
+
`resetPassword` supports both OTP-based and link-based reset initiation
|
|
855
|
+
flows.
|
|
856
|
+
|
|
857
|
+
`IsPasswordResetWithOTP` is optional. It is included in the request body only
|
|
858
|
+
when `isPasswordResetWithOTP` is `true`. When `false` or omitted, the field is
|
|
859
|
+
not sent at all and `false` is not serialized into the payload.
|
|
840
860
|
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
861
|
+
#### OTP-based password reset initiation
|
|
862
|
+
|
|
863
|
+
Use this when the password reset flow should be handled through an OTP code.
|
|
864
|
+
In this case, `IsPasswordResetWithOTP` should be `true`.
|
|
844
865
|
|
|
845
866
|
```ts
|
|
846
|
-
await loginClient.resetPassword(
|
|
847
|
-
"john.smith@example.com",
|
|
848
|
-
true
|
|
849
|
-
);
|
|
867
|
+
await loginClient.resetPassword("john.smith@example.com", true);
|
|
850
868
|
```
|
|
851
869
|
|
|
852
870
|
#### Full API request
|
|
853
|
-
Request sent for the usage example above:
|
|
854
871
|
|
|
855
872
|
```json
|
|
856
873
|
{
|
|
@@ -862,6 +879,27 @@ Request sent for the usage example above:
|
|
|
862
879
|
}
|
|
863
880
|
```
|
|
864
881
|
|
|
882
|
+
#### Link-based password reset initiation
|
|
883
|
+
|
|
884
|
+
Use this when the password reset flow should be handled from an email link.
|
|
885
|
+
In this case, `IsPasswordResetWithOTP` should be omitted by passing `false` or
|
|
886
|
+
leaving the second argument out.
|
|
887
|
+
|
|
888
|
+
```ts
|
|
889
|
+
await loginClient.resetPassword("john.smith@example.com", false);
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
Effective request body:
|
|
893
|
+
|
|
894
|
+
```json
|
|
895
|
+
{
|
|
896
|
+
"Data": {
|
|
897
|
+
"Email": "john.smith@example.com",
|
|
898
|
+
"TenantID": "test-tenant"
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
```
|
|
902
|
+
|
|
865
903
|
`Authorization: Bearer eyJ_id_token_example` may also be included when an ID token
|
|
866
904
|
is already stored.
|
|
867
905
|
|
|
@@ -885,23 +923,32 @@ Status:
|
|
|
885
923
|
|
|
886
924
|
### Reset Password Confirm
|
|
887
925
|
|
|
888
|
-
|
|
926
|
+
`resetPasswordConfirm` supports both OTP-based and link-based confirmation
|
|
927
|
+
flows.
|
|
928
|
+
|
|
929
|
+
If `IsPasswordResetWithOTP` is `true`, `Code` is required. If
|
|
930
|
+
`IsPasswordResetWithOTP` is not `true`, `Token` is required. For the
|
|
931
|
+
link-based flow, the frontend is responsible for taking the token from the
|
|
932
|
+
password reset email link and passing that token in the payload.
|
|
933
|
+
|
|
934
|
+
#### OTP-based password reset confirmation
|
|
889
935
|
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
936
|
+
Use this when the password reset flow was started with OTP. In this case,
|
|
937
|
+
`IsPasswordResetWithOTP` should be `true` and `Code` should contain the final
|
|
938
|
+
reset code.
|
|
893
939
|
|
|
894
940
|
```ts
|
|
895
|
-
await loginClient.resetPasswordConfirm(
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
941
|
+
await loginClient.resetPasswordConfirm({
|
|
942
|
+
Data: {
|
|
943
|
+
Email: "john.smith@example.com",
|
|
944
|
+
Password: "ExamplePassword123!",
|
|
945
|
+
IsPasswordResetWithOTP: true,
|
|
946
|
+
Code: "123456"
|
|
947
|
+
}
|
|
948
|
+
});
|
|
901
949
|
```
|
|
902
950
|
|
|
903
|
-
|
|
904
|
-
Request sent for the usage example above:
|
|
951
|
+
Request body:
|
|
905
952
|
|
|
906
953
|
```json
|
|
907
954
|
{
|
|
@@ -909,12 +956,42 @@ Request sent for the usage example above:
|
|
|
909
956
|
"Email": "john.smith@example.com",
|
|
910
957
|
"TenantID": "test-tenant",
|
|
911
958
|
"Password": "ExamplePassword123!",
|
|
912
|
-
"
|
|
959
|
+
"Code": "123456",
|
|
913
960
|
"IsPasswordResetWithOTP": true
|
|
914
961
|
}
|
|
915
962
|
}
|
|
916
963
|
```
|
|
917
964
|
|
|
965
|
+
#### Link-based password reset confirmation
|
|
966
|
+
|
|
967
|
+
Use this when the password reset flow was started from an email link. In this
|
|
968
|
+
case, `Token` should be included in the payload, the frontend should read the
|
|
969
|
+
token value from the password reset email link and send that token in the
|
|
970
|
+
request payload, and `IsPasswordResetWithOTP` should be omitted or `false`.
|
|
971
|
+
|
|
972
|
+
```ts
|
|
973
|
+
await loginClient.resetPasswordConfirm({
|
|
974
|
+
Data: {
|
|
975
|
+
Email: "john.smith@example.com",
|
|
976
|
+
Password: "ExamplePassword123!",
|
|
977
|
+
Token: "token-from-email-link"
|
|
978
|
+
}
|
|
979
|
+
});
|
|
980
|
+
```
|
|
981
|
+
|
|
982
|
+
Effective request body:
|
|
983
|
+
|
|
984
|
+
```json
|
|
985
|
+
{
|
|
986
|
+
"Data": {
|
|
987
|
+
"Email": "john.smith@example.com",
|
|
988
|
+
"TenantID": "test-tenant",
|
|
989
|
+
"Password": "ExamplePassword123!",
|
|
990
|
+
"Token": "token-from-email-link"
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
```
|
|
994
|
+
|
|
918
995
|
`Authorization: Bearer eyJ_id_token_example` may also be included when an ID token
|
|
919
996
|
is already stored.
|
|
920
997
|
|
|
@@ -940,8 +1017,8 @@ Status:
|
|
|
940
1017
|
|
|
941
1018
|
Public signature: `loginClient.refreshToken()`
|
|
942
1019
|
|
|
943
|
-
`refreshToken()` requires a successful
|
|
944
|
-
The client sends the stored refresh token
|
|
1020
|
+
`refreshToken()` requires a previous successful login and a stored refresh token.
|
|
1021
|
+
The client sends the stored refresh token and stores the returned token set in
|
|
945
1022
|
memory.
|
|
946
1023
|
|
|
947
1024
|
```ts
|
|
@@ -975,6 +1052,13 @@ Status:
|
|
|
975
1052
|
"RefreshToken": "eyJ_refresh_token_example",
|
|
976
1053
|
"AccessToken": "eyJ_access_token_example",
|
|
977
1054
|
"IDToken": "eyJ_id_token_example",
|
|
1055
|
+
"EHR": null,
|
|
1056
|
+
"ErrorMessage": null,
|
|
1057
|
+
"HasInsurance": false,
|
|
1058
|
+
"HasIDCard": false,
|
|
1059
|
+
"HasSelfie": false,
|
|
1060
|
+
"Attributes": null,
|
|
1061
|
+
"ID": null,
|
|
978
1062
|
"TenantID": "test-tenant",
|
|
979
1063
|
"Expiration": "2030-01-01T00:00:00.000Z",
|
|
980
1064
|
"Type": 0
|
|
@@ -1014,16 +1098,16 @@ The usage example above reads the value from local state.
|
|
|
1014
1098
|
}
|
|
1015
1099
|
```
|
|
1016
1100
|
|
|
1101
|
+
If an API key has been configured through setApiKey(...), the returned header object also includes the configured API key header.
|
|
1102
|
+
|
|
1017
1103
|
---
|
|
1018
1104
|
|
|
1019
1105
|
### Get User Info
|
|
1020
1106
|
|
|
1021
1107
|
Public signature: `loginClient.getUserInfo()`
|
|
1022
1108
|
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
It requires a stored ID token, and it currently targets the same endpoint as
|
|
1026
|
-
`getHeader()`.
|
|
1109
|
+
Calls the patient header endpoint and returns the raw server response.
|
|
1110
|
+
It requires a stored ID token.
|
|
1027
1111
|
|
|
1028
1112
|
```ts
|
|
1029
1113
|
const userInfo = await loginClient.getUserInfo();
|
|
@@ -1089,78 +1173,6 @@ Status:
|
|
|
1089
1173
|
|
|
1090
1174
|
---
|
|
1091
1175
|
|
|
1092
|
-
### Get Header
|
|
1093
|
-
|
|
1094
|
-
Public signature: `loginClient.getHeader()`
|
|
1095
|
-
|
|
1096
|
-
The current implementation also calls the patient header endpoint.
|
|
1097
|
-
It requires a stored ID token, and the response shape is effectively the same as
|
|
1098
|
-
`getUserInfo()`.
|
|
1099
|
-
|
|
1100
|
-
```ts
|
|
1101
|
-
await loginClient.getHeader();
|
|
1102
|
-
```
|
|
1103
|
-
|
|
1104
|
-
#### Full API request
|
|
1105
|
-
`getHeader()` does not send a request body.
|
|
1106
|
-
|
|
1107
|
-
#### API response
|
|
1108
|
-
|
|
1109
|
-
Status:
|
|
1110
|
-
|
|
1111
|
-
```txt
|
|
1112
|
-
200
|
|
1113
|
-
```
|
|
1114
|
-
|
|
1115
|
-
```json
|
|
1116
|
-
{
|
|
1117
|
-
"Data": {
|
|
1118
|
-
"Record": {
|
|
1119
|
-
"ID": "record-id-example",
|
|
1120
|
-
"TenantID": "test-tenant",
|
|
1121
|
-
"FirstName": "John",
|
|
1122
|
-
"LastName": "Smith",
|
|
1123
|
-
"Email": "john.smith@example.com",
|
|
1124
|
-
"Phone": "+15555550123",
|
|
1125
|
-
"BirthDate": "1990-01-01T00:00:00",
|
|
1126
|
-
"Gender": "male",
|
|
1127
|
-
"Sex": "Male",
|
|
1128
|
-
"Race": "White",
|
|
1129
|
-
"Ethnicity": "Not Hispanic or Latino",
|
|
1130
|
-
"HasInsurance": false,
|
|
1131
|
-
"HasIDCard": false,
|
|
1132
|
-
"HasSelfie": false,
|
|
1133
|
-
"Address": {
|
|
1134
|
-
"StreetAndNumber": "123 Test St",
|
|
1135
|
-
"Extension": null,
|
|
1136
|
-
"City": "Springfield",
|
|
1137
|
-
"State": "CA",
|
|
1138
|
-
"PostalCode": "90210",
|
|
1139
|
-
"Country": "US"
|
|
1140
|
-
},
|
|
1141
|
-
"Attributes": {
|
|
1142
|
-
"FHIRPatientID": "patient-id-example",
|
|
1143
|
-
"CompositeID": "composite-id-example",
|
|
1144
|
-
"VERIFY_EMAIL_CODE": "true"
|
|
1145
|
-
},
|
|
1146
|
-
"CompositeID": "composite-id-example",
|
|
1147
|
-
"FHIRID": "fhir-id-example"
|
|
1148
|
-
},
|
|
1149
|
-
"Encounters": null,
|
|
1150
|
-
"EHR": "fhir",
|
|
1151
|
-
"PendingActions": [
|
|
1152
|
-
"ADD_INSURANCE",
|
|
1153
|
-
"ADD_ID",
|
|
1154
|
-
"IMPORT_VITALS"
|
|
1155
|
-
]
|
|
1156
|
-
},
|
|
1157
|
-
"ErrorMessage": null,
|
|
1158
|
-
"IsOK": true
|
|
1159
|
-
}
|
|
1160
|
-
```
|
|
1161
|
-
|
|
1162
|
-
---
|
|
1163
|
-
|
|
1164
1176
|
### Get Access Token
|
|
1165
1177
|
|
|
1166
1178
|
Public signature: `loginClient.getAccessToken()`
|
|
@@ -1218,8 +1230,8 @@ eyJ_id_token_example
|
|
|
1218
1230
|
- Call `register(...)` if the patient account needs to be created.
|
|
1219
1231
|
- Use `submitOnboardingStep(...)` or the onboarding helper methods to complete required onboarding steps.
|
|
1220
1232
|
- Call `login(...)` to authenticate and store the returned access, refresh, and ID tokens in memory.
|
|
1221
|
-
- Use `refreshToken()` to replace the current token set when
|
|
1222
|
-
- Use `getAuthHeader()`, `getAccessToken()`, `getIDToken()`,
|
|
1233
|
+
- Use `refreshToken()` to replace the current token set when a stored refresh token is available.
|
|
1234
|
+
- Use `getAuthHeader()`, `getAccessToken()`, `getIDToken()`, and `getUserInfo()` for authenticated flows after login.
|
|
1223
1235
|
- Other Healthcheck connectors can consume `getAuthHeader()` instead of managing auth tokens directly.
|
|
1224
1236
|
|
|
1225
1237
|
|
|
@@ -1229,25 +1241,8 @@ eyJ_id_token_example
|
|
|
1229
1241
|
- `TenantID` is injected by the client into tenant-bound register, onboarding, login, refresh, and password requests.
|
|
1230
1242
|
- `register()`, `verifyEmail()`, and `resendEmailVerify()` all follow the same string-based `User.Attributes.VERIFY_EMAIL_CODE` pattern for OTP email verification flows.
|
|
1231
1243
|
- `saveAddress()` accepts an `Address`.
|
|
1232
|
-
- `login()` and `refreshToken()`
|
|
1233
|
-
- `
|
|
1244
|
+
- `login()` stores the initial token set internally, and `refreshToken()` updates that stored token set when a refresh token is available.
|
|
1245
|
+
- `refreshToken()` does not require a current ID token. It uses the stored refresh token from the previous successful login.
|
|
1246
|
+
- `getUserInfo()` calls the patient header endpoint.
|
|
1234
1247
|
- `getAuthHeader()`, `getAccessToken()`, `getIDToken()`, `getBaseUrl()`, and `getTenantId()` return local values and do not perform HTTP requests.
|
|
1235
1248
|
- This connector is intended to be reused by other Healthcheck SDK connectors built on the same HTTP layer.
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
## API Key
|
|
1239
|
-
|
|
1240
|
-
All outgoing requests from `HCLoginClient` can include an optional API key header.
|
|
1241
|
-
|
|
1242
|
-
```ts
|
|
1243
|
-
const apiKey = process.env.HEALTHCLOUD_API_KEY;
|
|
1244
|
-
|
|
1245
|
-
if (apiKey) {
|
|
1246
|
-
loginClient.setApiKey("x-api-key", apiKey);
|
|
1247
|
-
}
|
|
1248
|
-
```
|
|
1249
|
-
|
|
1250
|
-
- Header name should be `x-api-key`.
|
|
1251
|
-
- API key is optional unless required by the backend.
|
|
1252
|
-
- If not set, behavior remains unchanged and the header is omitted.
|
|
1253
|
-
- The header is applied to registration, onboarding, login, token refresh, password reset, and authenticated patient header requests.
|
package/dist/index.cjs
CHANGED
|
@@ -63,17 +63,31 @@ var HCLoginClient = class {
|
|
|
63
63
|
this.http = httpClient;
|
|
64
64
|
}
|
|
65
65
|
configure(tenantID, environment, region) {
|
|
66
|
-
|
|
66
|
+
const trimmedTenantID = tenantID == null ? void 0 : tenantID.trim();
|
|
67
|
+
if (!trimmedTenantID) {
|
|
68
|
+
throw new ConfigError("tenantID is required.");
|
|
69
|
+
}
|
|
70
|
+
if (!ENV_PREFIX[environment]) {
|
|
71
|
+
throw new ConfigError("Invalid environment.");
|
|
72
|
+
}
|
|
67
73
|
this.config = {
|
|
68
|
-
tenantID,
|
|
74
|
+
tenantID: trimmedTenantID,
|
|
69
75
|
environment,
|
|
70
76
|
region,
|
|
71
|
-
baseUrl: buildBaseUrl(
|
|
77
|
+
baseUrl: buildBaseUrl(trimmedTenantID, environment, region)
|
|
72
78
|
};
|
|
73
79
|
}
|
|
74
80
|
setApiKey(headerName, value) {
|
|
75
|
-
|
|
76
|
-
|
|
81
|
+
const trimmedHeaderName = headerName == null ? void 0 : headerName.trim();
|
|
82
|
+
const trimmedValue = value == null ? void 0 : value.trim();
|
|
83
|
+
if (!trimmedHeaderName) {
|
|
84
|
+
throw new ConfigError("API key header name is required.");
|
|
85
|
+
}
|
|
86
|
+
if (!trimmedValue) {
|
|
87
|
+
throw new ConfigError("API key value is required.");
|
|
88
|
+
}
|
|
89
|
+
this.apiKeyHeaderName = trimmedHeaderName;
|
|
90
|
+
this.apiKeyValue = trimmedValue;
|
|
77
91
|
}
|
|
78
92
|
async register(email, password, firstName = "Unknown", lastName = "Unknown", options = {}) {
|
|
79
93
|
var _a, _b;
|
|
@@ -219,15 +233,9 @@ var HCLoginClient = class {
|
|
|
219
233
|
this.ensureConfigured();
|
|
220
234
|
const requestPayload = {
|
|
221
235
|
Data: {
|
|
222
|
-
FirstName: "",
|
|
223
|
-
LastName: "",
|
|
224
236
|
Email: email,
|
|
225
237
|
Password: password,
|
|
226
|
-
TenantID: this.config.tenantID
|
|
227
|
-
AppPoolID: "",
|
|
228
|
-
GoogleIdToken: "",
|
|
229
|
-
AppleIdToken: "",
|
|
230
|
-
AppleCode: ""
|
|
238
|
+
TenantID: this.config.tenantID
|
|
231
239
|
}
|
|
232
240
|
};
|
|
233
241
|
const resp = await this.http.post(
|
|
@@ -263,7 +271,10 @@ var HCLoginClient = class {
|
|
|
263
271
|
const resp = await this.http.post(
|
|
264
272
|
`${this.config.baseUrl}/patient/refresh`,
|
|
265
273
|
requestPayload,
|
|
266
|
-
|
|
274
|
+
{
|
|
275
|
+
"X-Tenant-ID": this.config.tenantID,
|
|
276
|
+
...this.getApiKeyHeader()
|
|
277
|
+
}
|
|
267
278
|
);
|
|
268
279
|
const data = (_b = resp.Data) != null ? _b : resp;
|
|
269
280
|
const tokens = {
|
|
@@ -275,14 +286,14 @@ var HCLoginClient = class {
|
|
|
275
286
|
this.tokens = tokens;
|
|
276
287
|
return tokens;
|
|
277
288
|
}
|
|
278
|
-
async resetPassword(email, isPasswordResetWithOTP =
|
|
289
|
+
async resetPassword(email, isPasswordResetWithOTP = false) {
|
|
279
290
|
var _a;
|
|
280
291
|
this.ensureConfigured();
|
|
281
292
|
const requestPayload = {
|
|
282
293
|
Data: {
|
|
283
294
|
Email: email,
|
|
284
295
|
TenantID: this.config.tenantID,
|
|
285
|
-
IsPasswordResetWithOTP:
|
|
296
|
+
...isPasswordResetWithOTP === true ? { IsPasswordResetWithOTP: true } : {}
|
|
286
297
|
}
|
|
287
298
|
};
|
|
288
299
|
await this.http.post(
|
|
@@ -296,21 +307,24 @@ var HCLoginClient = class {
|
|
|
296
307
|
}
|
|
297
308
|
);
|
|
298
309
|
}
|
|
299
|
-
async resetPasswordConfirm(
|
|
310
|
+
async resetPasswordConfirm(payload) {
|
|
300
311
|
var _a;
|
|
301
312
|
this.ensureConfigured();
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
}
|
|
310
|
-
};
|
|
313
|
+
const isOtpFlow = payload.Data.IsPasswordResetWithOTP === true;
|
|
314
|
+
if (isOtpFlow && !payload.Data.Code) {
|
|
315
|
+
throw new ConfigError("Code is required for OTP password reset confirmation.");
|
|
316
|
+
}
|
|
317
|
+
if (!isOtpFlow && !payload.Data.Token) {
|
|
318
|
+
throw new ConfigError("Token is required for link-based password reset confirmation.");
|
|
319
|
+
}
|
|
311
320
|
await this.http.post(
|
|
312
321
|
`${this.config.baseUrl}/patient/password`,
|
|
313
|
-
|
|
322
|
+
{
|
|
323
|
+
Data: {
|
|
324
|
+
...payload.Data,
|
|
325
|
+
TenantID: this.config.tenantID
|
|
326
|
+
}
|
|
327
|
+
},
|
|
314
328
|
{
|
|
315
329
|
"Content-Type": "application/json",
|
|
316
330
|
"X-Tenant-ID": this.config.tenantID,
|
|
@@ -437,23 +451,12 @@ var HCLoginClient = class {
|
|
|
437
451
|
...this.getApiKeyHeader()
|
|
438
452
|
};
|
|
439
453
|
}
|
|
440
|
-
async getHeader() {
|
|
441
|
-
var _a;
|
|
442
|
-
this.ensureConfigured();
|
|
443
|
-
if (!((_a = this.tokens) == null ? void 0 : _a.idToken)) {
|
|
444
|
-
throw new AuthError("No ID token available");
|
|
445
|
-
}
|
|
446
|
-
return this.http.get(
|
|
447
|
-
`${this.config.baseUrl}/patient/header`,
|
|
448
|
-
this.getAuthHeader()
|
|
449
|
-
);
|
|
450
|
-
}
|
|
451
454
|
getApiKeyHeader() {
|
|
452
455
|
if (!this.apiKeyHeaderName || !this.apiKeyValue) {
|
|
453
456
|
return {};
|
|
454
457
|
}
|
|
455
458
|
return {
|
|
456
|
-
|
|
459
|
+
[this.apiKeyHeaderName]: this.apiKeyValue
|
|
457
460
|
};
|
|
458
461
|
}
|
|
459
462
|
getBaseUrl() {
|
package/dist/index.d.cts
CHANGED
|
@@ -39,17 +39,26 @@ interface VerifyEmailOptions {
|
|
|
39
39
|
attributes?: Record<string, string>;
|
|
40
40
|
}
|
|
41
41
|
interface LoginBody {
|
|
42
|
-
FirstName
|
|
43
|
-
LastName
|
|
42
|
+
FirstName?: string;
|
|
43
|
+
LastName?: string;
|
|
44
44
|
Email: string;
|
|
45
|
+
UserName?: string;
|
|
45
46
|
Password: string;
|
|
46
|
-
|
|
47
|
-
AppPoolID
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
PoolID?: string;
|
|
48
|
+
AppPoolID?: string;
|
|
49
|
+
AppClientID?: string;
|
|
50
|
+
TenantID?: string;
|
|
51
|
+
Token?: string;
|
|
52
|
+
Type?: number;
|
|
53
|
+
AppleIdToken?: string;
|
|
54
|
+
AppleCode?: string;
|
|
55
|
+
GoogleIdToken?: string;
|
|
56
|
+
IsPasswordResetWithOTP?: boolean;
|
|
57
|
+
Code?: string;
|
|
58
|
+
Language?: string;
|
|
51
59
|
}
|
|
52
60
|
type LoginRequest = ApiRequest<LoginBody>;
|
|
61
|
+
type LoginPayload = LoginRequest;
|
|
53
62
|
interface RefreshBody {
|
|
54
63
|
RefreshToken: string;
|
|
55
64
|
TenantID: string;
|
|
@@ -58,17 +67,24 @@ type RefreshRequest = ApiRequest<RefreshBody>;
|
|
|
58
67
|
interface ResetBody {
|
|
59
68
|
Email: string;
|
|
60
69
|
TenantID: string;
|
|
61
|
-
IsPasswordResetWithOTP
|
|
70
|
+
IsPasswordResetWithOTP?: boolean;
|
|
62
71
|
}
|
|
63
72
|
type ResetRequest = ApiRequest<ResetBody>;
|
|
64
|
-
|
|
73
|
+
type ResetConfirmBody = {
|
|
65
74
|
Email: string;
|
|
66
|
-
TenantID: string;
|
|
67
75
|
Password: string;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
IsPasswordResetWithOTP: true;
|
|
77
|
+
Code: string;
|
|
78
|
+
Token?: string;
|
|
79
|
+
} | {
|
|
80
|
+
Email: string;
|
|
81
|
+
Password: string;
|
|
82
|
+
Token: string;
|
|
83
|
+
IsPasswordResetWithOTP?: false;
|
|
84
|
+
Code?: string;
|
|
85
|
+
};
|
|
71
86
|
type ResetConfirmRequest = ApiRequest<ResetConfirmBody>;
|
|
87
|
+
type ResetPasswordConfirmPayload = ResetConfirmRequest;
|
|
72
88
|
interface RegisterCredentials {
|
|
73
89
|
Email: string;
|
|
74
90
|
Password: string;
|
|
@@ -204,7 +220,7 @@ declare class HCLoginClient {
|
|
|
204
220
|
login(email: string, password: string): Promise<AuthTokens>;
|
|
205
221
|
refreshToken(): Promise<AuthTokens>;
|
|
206
222
|
resetPassword(email: string, isPasswordResetWithOTP?: boolean): Promise<void>;
|
|
207
|
-
resetPasswordConfirm(
|
|
223
|
+
resetPasswordConfirm(payload: ResetPasswordConfirmPayload): Promise<void>;
|
|
208
224
|
getAccessToken(): string | undefined;
|
|
209
225
|
getIDToken(): string | undefined;
|
|
210
226
|
getUserInfo(): Promise<unknown>;
|
|
@@ -217,7 +233,6 @@ declare class HCLoginClient {
|
|
|
217
233
|
Authorization: string;
|
|
218
234
|
"X-Tenant-ID": string;
|
|
219
235
|
};
|
|
220
|
-
getHeader(): Promise<any>;
|
|
221
236
|
private getApiKeyHeader;
|
|
222
237
|
getBaseUrl(): string;
|
|
223
238
|
getTenantId(): string;
|
|
@@ -234,4 +249,4 @@ declare class HttpError extends Error {
|
|
|
234
249
|
constructor(status: number, message: string);
|
|
235
250
|
}
|
|
236
251
|
|
|
237
|
-
export { type Address, type ApiRequest, AuthError, type AuthTokens, ConfigError, type Environment, HCLoginClient, type HealthProfile, HttpError, type LoginBody, type LoginConfig, type LoginRequest, type OnboardBody, type OnboardInput, type OnboardRequest, type OnboardUser, type OnboardingStep, type RefreshBody, type RefreshRequest, type Region, type RegisterAttributes, type RegisterBody, type RegisterCredentials, type RegisterFullBody, type RegisterFullOptions, type RegisterFullRequest, type RegisterFullUser, type RegisterOptions, type RegisterOpts, type RegisterRequest, type RegisterUser, type ResetBody, type ResetConfirmBody, type ResetConfirmRequest, type ResetRequest, type SmsData, type UserInfo, type VerifyEmailOptions };
|
|
252
|
+
export { type Address, type ApiRequest, AuthError, type AuthTokens, ConfigError, type Environment, HCLoginClient, type HealthProfile, HttpError, type LoginBody, type LoginConfig, type LoginPayload, type LoginRequest, type OnboardBody, type OnboardInput, type OnboardRequest, type OnboardUser, type OnboardingStep, type RefreshBody, type RefreshRequest, type Region, type RegisterAttributes, type RegisterBody, type RegisterCredentials, type RegisterFullBody, type RegisterFullOptions, type RegisterFullRequest, type RegisterFullUser, type RegisterOptions, type RegisterOpts, type RegisterRequest, type RegisterUser, type ResetBody, type ResetConfirmBody, type ResetConfirmRequest, type ResetPasswordConfirmPayload, type ResetRequest, type SmsData, type UserInfo, type VerifyEmailOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -39,17 +39,26 @@ interface VerifyEmailOptions {
|
|
|
39
39
|
attributes?: Record<string, string>;
|
|
40
40
|
}
|
|
41
41
|
interface LoginBody {
|
|
42
|
-
FirstName
|
|
43
|
-
LastName
|
|
42
|
+
FirstName?: string;
|
|
43
|
+
LastName?: string;
|
|
44
44
|
Email: string;
|
|
45
|
+
UserName?: string;
|
|
45
46
|
Password: string;
|
|
46
|
-
|
|
47
|
-
AppPoolID
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
PoolID?: string;
|
|
48
|
+
AppPoolID?: string;
|
|
49
|
+
AppClientID?: string;
|
|
50
|
+
TenantID?: string;
|
|
51
|
+
Token?: string;
|
|
52
|
+
Type?: number;
|
|
53
|
+
AppleIdToken?: string;
|
|
54
|
+
AppleCode?: string;
|
|
55
|
+
GoogleIdToken?: string;
|
|
56
|
+
IsPasswordResetWithOTP?: boolean;
|
|
57
|
+
Code?: string;
|
|
58
|
+
Language?: string;
|
|
51
59
|
}
|
|
52
60
|
type LoginRequest = ApiRequest<LoginBody>;
|
|
61
|
+
type LoginPayload = LoginRequest;
|
|
53
62
|
interface RefreshBody {
|
|
54
63
|
RefreshToken: string;
|
|
55
64
|
TenantID: string;
|
|
@@ -58,17 +67,24 @@ type RefreshRequest = ApiRequest<RefreshBody>;
|
|
|
58
67
|
interface ResetBody {
|
|
59
68
|
Email: string;
|
|
60
69
|
TenantID: string;
|
|
61
|
-
IsPasswordResetWithOTP
|
|
70
|
+
IsPasswordResetWithOTP?: boolean;
|
|
62
71
|
}
|
|
63
72
|
type ResetRequest = ApiRequest<ResetBody>;
|
|
64
|
-
|
|
73
|
+
type ResetConfirmBody = {
|
|
65
74
|
Email: string;
|
|
66
|
-
TenantID: string;
|
|
67
75
|
Password: string;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
IsPasswordResetWithOTP: true;
|
|
77
|
+
Code: string;
|
|
78
|
+
Token?: string;
|
|
79
|
+
} | {
|
|
80
|
+
Email: string;
|
|
81
|
+
Password: string;
|
|
82
|
+
Token: string;
|
|
83
|
+
IsPasswordResetWithOTP?: false;
|
|
84
|
+
Code?: string;
|
|
85
|
+
};
|
|
71
86
|
type ResetConfirmRequest = ApiRequest<ResetConfirmBody>;
|
|
87
|
+
type ResetPasswordConfirmPayload = ResetConfirmRequest;
|
|
72
88
|
interface RegisterCredentials {
|
|
73
89
|
Email: string;
|
|
74
90
|
Password: string;
|
|
@@ -204,7 +220,7 @@ declare class HCLoginClient {
|
|
|
204
220
|
login(email: string, password: string): Promise<AuthTokens>;
|
|
205
221
|
refreshToken(): Promise<AuthTokens>;
|
|
206
222
|
resetPassword(email: string, isPasswordResetWithOTP?: boolean): Promise<void>;
|
|
207
|
-
resetPasswordConfirm(
|
|
223
|
+
resetPasswordConfirm(payload: ResetPasswordConfirmPayload): Promise<void>;
|
|
208
224
|
getAccessToken(): string | undefined;
|
|
209
225
|
getIDToken(): string | undefined;
|
|
210
226
|
getUserInfo(): Promise<unknown>;
|
|
@@ -217,7 +233,6 @@ declare class HCLoginClient {
|
|
|
217
233
|
Authorization: string;
|
|
218
234
|
"X-Tenant-ID": string;
|
|
219
235
|
};
|
|
220
|
-
getHeader(): Promise<any>;
|
|
221
236
|
private getApiKeyHeader;
|
|
222
237
|
getBaseUrl(): string;
|
|
223
238
|
getTenantId(): string;
|
|
@@ -234,4 +249,4 @@ declare class HttpError extends Error {
|
|
|
234
249
|
constructor(status: number, message: string);
|
|
235
250
|
}
|
|
236
251
|
|
|
237
|
-
export { type Address, type ApiRequest, AuthError, type AuthTokens, ConfigError, type Environment, HCLoginClient, type HealthProfile, HttpError, type LoginBody, type LoginConfig, type LoginRequest, type OnboardBody, type OnboardInput, type OnboardRequest, type OnboardUser, type OnboardingStep, type RefreshBody, type RefreshRequest, type Region, type RegisterAttributes, type RegisterBody, type RegisterCredentials, type RegisterFullBody, type RegisterFullOptions, type RegisterFullRequest, type RegisterFullUser, type RegisterOptions, type RegisterOpts, type RegisterRequest, type RegisterUser, type ResetBody, type ResetConfirmBody, type ResetConfirmRequest, type ResetRequest, type SmsData, type UserInfo, type VerifyEmailOptions };
|
|
252
|
+
export { type Address, type ApiRequest, AuthError, type AuthTokens, ConfigError, type Environment, HCLoginClient, type HealthProfile, HttpError, type LoginBody, type LoginConfig, type LoginPayload, type LoginRequest, type OnboardBody, type OnboardInput, type OnboardRequest, type OnboardUser, type OnboardingStep, type RefreshBody, type RefreshRequest, type Region, type RegisterAttributes, type RegisterBody, type RegisterCredentials, type RegisterFullBody, type RegisterFullOptions, type RegisterFullRequest, type RegisterFullUser, type RegisterOptions, type RegisterOpts, type RegisterRequest, type RegisterUser, type ResetBody, type ResetConfirmBody, type ResetConfirmRequest, type ResetPasswordConfirmPayload, type ResetRequest, type SmsData, type UserInfo, type VerifyEmailOptions };
|
package/dist/index.js
CHANGED
|
@@ -34,17 +34,31 @@ var HCLoginClient = class {
|
|
|
34
34
|
this.http = httpClient;
|
|
35
35
|
}
|
|
36
36
|
configure(tenantID, environment, region) {
|
|
37
|
-
|
|
37
|
+
const trimmedTenantID = tenantID == null ? void 0 : tenantID.trim();
|
|
38
|
+
if (!trimmedTenantID) {
|
|
39
|
+
throw new ConfigError("tenantID is required.");
|
|
40
|
+
}
|
|
41
|
+
if (!ENV_PREFIX[environment]) {
|
|
42
|
+
throw new ConfigError("Invalid environment.");
|
|
43
|
+
}
|
|
38
44
|
this.config = {
|
|
39
|
-
tenantID,
|
|
45
|
+
tenantID: trimmedTenantID,
|
|
40
46
|
environment,
|
|
41
47
|
region,
|
|
42
|
-
baseUrl: buildBaseUrl(
|
|
48
|
+
baseUrl: buildBaseUrl(trimmedTenantID, environment, region)
|
|
43
49
|
};
|
|
44
50
|
}
|
|
45
51
|
setApiKey(headerName, value) {
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
const trimmedHeaderName = headerName == null ? void 0 : headerName.trim();
|
|
53
|
+
const trimmedValue = value == null ? void 0 : value.trim();
|
|
54
|
+
if (!trimmedHeaderName) {
|
|
55
|
+
throw new ConfigError("API key header name is required.");
|
|
56
|
+
}
|
|
57
|
+
if (!trimmedValue) {
|
|
58
|
+
throw new ConfigError("API key value is required.");
|
|
59
|
+
}
|
|
60
|
+
this.apiKeyHeaderName = trimmedHeaderName;
|
|
61
|
+
this.apiKeyValue = trimmedValue;
|
|
48
62
|
}
|
|
49
63
|
async register(email, password, firstName = "Unknown", lastName = "Unknown", options = {}) {
|
|
50
64
|
var _a, _b;
|
|
@@ -190,15 +204,9 @@ var HCLoginClient = class {
|
|
|
190
204
|
this.ensureConfigured();
|
|
191
205
|
const requestPayload = {
|
|
192
206
|
Data: {
|
|
193
|
-
FirstName: "",
|
|
194
|
-
LastName: "",
|
|
195
207
|
Email: email,
|
|
196
208
|
Password: password,
|
|
197
|
-
TenantID: this.config.tenantID
|
|
198
|
-
AppPoolID: "",
|
|
199
|
-
GoogleIdToken: "",
|
|
200
|
-
AppleIdToken: "",
|
|
201
|
-
AppleCode: ""
|
|
209
|
+
TenantID: this.config.tenantID
|
|
202
210
|
}
|
|
203
211
|
};
|
|
204
212
|
const resp = await this.http.post(
|
|
@@ -234,7 +242,10 @@ var HCLoginClient = class {
|
|
|
234
242
|
const resp = await this.http.post(
|
|
235
243
|
`${this.config.baseUrl}/patient/refresh`,
|
|
236
244
|
requestPayload,
|
|
237
|
-
|
|
245
|
+
{
|
|
246
|
+
"X-Tenant-ID": this.config.tenantID,
|
|
247
|
+
...this.getApiKeyHeader()
|
|
248
|
+
}
|
|
238
249
|
);
|
|
239
250
|
const data = (_b = resp.Data) != null ? _b : resp;
|
|
240
251
|
const tokens = {
|
|
@@ -246,14 +257,14 @@ var HCLoginClient = class {
|
|
|
246
257
|
this.tokens = tokens;
|
|
247
258
|
return tokens;
|
|
248
259
|
}
|
|
249
|
-
async resetPassword(email, isPasswordResetWithOTP =
|
|
260
|
+
async resetPassword(email, isPasswordResetWithOTP = false) {
|
|
250
261
|
var _a;
|
|
251
262
|
this.ensureConfigured();
|
|
252
263
|
const requestPayload = {
|
|
253
264
|
Data: {
|
|
254
265
|
Email: email,
|
|
255
266
|
TenantID: this.config.tenantID,
|
|
256
|
-
IsPasswordResetWithOTP:
|
|
267
|
+
...isPasswordResetWithOTP === true ? { IsPasswordResetWithOTP: true } : {}
|
|
257
268
|
}
|
|
258
269
|
};
|
|
259
270
|
await this.http.post(
|
|
@@ -267,21 +278,24 @@ var HCLoginClient = class {
|
|
|
267
278
|
}
|
|
268
279
|
);
|
|
269
280
|
}
|
|
270
|
-
async resetPasswordConfirm(
|
|
281
|
+
async resetPasswordConfirm(payload) {
|
|
271
282
|
var _a;
|
|
272
283
|
this.ensureConfigured();
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
};
|
|
284
|
+
const isOtpFlow = payload.Data.IsPasswordResetWithOTP === true;
|
|
285
|
+
if (isOtpFlow && !payload.Data.Code) {
|
|
286
|
+
throw new ConfigError("Code is required for OTP password reset confirmation.");
|
|
287
|
+
}
|
|
288
|
+
if (!isOtpFlow && !payload.Data.Token) {
|
|
289
|
+
throw new ConfigError("Token is required for link-based password reset confirmation.");
|
|
290
|
+
}
|
|
282
291
|
await this.http.post(
|
|
283
292
|
`${this.config.baseUrl}/patient/password`,
|
|
284
|
-
|
|
293
|
+
{
|
|
294
|
+
Data: {
|
|
295
|
+
...payload.Data,
|
|
296
|
+
TenantID: this.config.tenantID
|
|
297
|
+
}
|
|
298
|
+
},
|
|
285
299
|
{
|
|
286
300
|
"Content-Type": "application/json",
|
|
287
301
|
"X-Tenant-ID": this.config.tenantID,
|
|
@@ -408,23 +422,12 @@ var HCLoginClient = class {
|
|
|
408
422
|
...this.getApiKeyHeader()
|
|
409
423
|
};
|
|
410
424
|
}
|
|
411
|
-
async getHeader() {
|
|
412
|
-
var _a;
|
|
413
|
-
this.ensureConfigured();
|
|
414
|
-
if (!((_a = this.tokens) == null ? void 0 : _a.idToken)) {
|
|
415
|
-
throw new AuthError("No ID token available");
|
|
416
|
-
}
|
|
417
|
-
return this.http.get(
|
|
418
|
-
`${this.config.baseUrl}/patient/header`,
|
|
419
|
-
this.getAuthHeader()
|
|
420
|
-
);
|
|
421
|
-
}
|
|
422
425
|
getApiKeyHeader() {
|
|
423
426
|
if (!this.apiKeyHeaderName || !this.apiKeyValue) {
|
|
424
427
|
return {};
|
|
425
428
|
}
|
|
426
429
|
return {
|
|
427
|
-
|
|
430
|
+
[this.apiKeyHeaderName]: this.apiKeyValue
|
|
428
431
|
};
|
|
429
432
|
}
|
|
430
433
|
getBaseUrl() {
|
package/package.json
CHANGED