@healthcloudai/hc-login-connector 0.0.15 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +374 -365
- package/dist/index.d.cts +97 -194
- package/dist/index.d.ts +97 -194
- package/dist/index.js +382 -363
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -20,437 +20,411 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
24
|
-
ConfigError: () => ConfigError,
|
|
23
|
+
APIError: () => import_hc_http2.APIError,
|
|
24
|
+
ConfigError: () => import_hc_http2.ConfigError,
|
|
25
25
|
HCLoginClient: () => HCLoginClient,
|
|
26
|
-
|
|
26
|
+
HCServiceError: () => import_hc_http2.HCServiceError,
|
|
27
|
+
NetworkError: () => import_hc_http2.NetworkError,
|
|
28
|
+
ValidationError: () => import_hc_http2.ValidationError,
|
|
29
|
+
errorFromHttpStatus: () => import_hc_http2.errorFromHttpStatus
|
|
27
30
|
});
|
|
28
31
|
module.exports = __toCommonJS(index_exports);
|
|
29
32
|
|
|
30
|
-
// src/errors.ts
|
|
31
|
-
var ConfigError = class extends Error {
|
|
32
|
-
constructor(message) {
|
|
33
|
-
super(message);
|
|
34
|
-
this.name = "ConfigError";
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
var AuthError = class extends Error {
|
|
38
|
-
constructor(message) {
|
|
39
|
-
super(message);
|
|
40
|
-
this.name = "AuthError";
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
var HttpError = class extends Error {
|
|
44
|
-
constructor(status, message) {
|
|
45
|
-
super(message);
|
|
46
|
-
this.name = "HttpError";
|
|
47
|
-
this.status = status;
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
|
|
51
33
|
// src/client.ts
|
|
52
|
-
var
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
34
|
+
var import_hc_http = require("@healthcloudai/hc-http");
|
|
35
|
+
var API_BASE_URLS = {
|
|
36
|
+
dev: "https://dev-api-healthcheck.healthcloud-services.com",
|
|
37
|
+
uat: "https://uat-api-healthcheck.healthcloud-services.com",
|
|
38
|
+
prod: "https://api-healthcheck.healthcloud-services.com"
|
|
56
39
|
};
|
|
57
|
-
function buildBaseUrl(
|
|
58
|
-
const
|
|
59
|
-
|
|
40
|
+
function buildBaseUrl(environment, region) {
|
|
41
|
+
const base = API_BASE_URLS[environment];
|
|
42
|
+
if (!region) {
|
|
43
|
+
return base;
|
|
44
|
+
}
|
|
45
|
+
return base.replace(
|
|
46
|
+
"https://",
|
|
47
|
+
`https://${region}-`
|
|
48
|
+
);
|
|
60
49
|
}
|
|
61
50
|
var HCLoginClient = class {
|
|
62
51
|
constructor(httpClient) {
|
|
63
52
|
this.http = httpClient;
|
|
64
53
|
}
|
|
54
|
+
// =========================================================================
|
|
55
|
+
// Configuration
|
|
56
|
+
// =========================================================================
|
|
65
57
|
configure(tenantID, environment, region) {
|
|
66
58
|
const trimmedTenantID = tenantID == null ? void 0 : tenantID.trim();
|
|
67
59
|
if (!trimmedTenantID) {
|
|
68
|
-
throw new ConfigError(
|
|
60
|
+
throw new import_hc_http.ConfigError(
|
|
61
|
+
"tenantID is required."
|
|
62
|
+
);
|
|
69
63
|
}
|
|
70
|
-
|
|
71
|
-
|
|
64
|
+
const baseUrl = API_BASE_URLS[environment];
|
|
65
|
+
if (!baseUrl) {
|
|
66
|
+
throw new import_hc_http.ConfigError(
|
|
67
|
+
`Unsupported environment: "${environment}"`
|
|
68
|
+
);
|
|
72
69
|
}
|
|
73
70
|
this.config = {
|
|
74
71
|
tenantID: trimmedTenantID,
|
|
75
72
|
environment,
|
|
76
73
|
region,
|
|
77
|
-
baseUrl: buildBaseUrl(
|
|
74
|
+
baseUrl: buildBaseUrl(
|
|
75
|
+
environment,
|
|
76
|
+
region
|
|
77
|
+
)
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
80
|
setApiKey(headerName, value) {
|
|
81
81
|
const trimmedHeaderName = headerName == null ? void 0 : headerName.trim();
|
|
82
82
|
const trimmedValue = value == null ? void 0 : value.trim();
|
|
83
83
|
if (!trimmedHeaderName) {
|
|
84
|
-
throw new ConfigError(
|
|
84
|
+
throw new import_hc_http.ConfigError(
|
|
85
|
+
"API key header name is required."
|
|
86
|
+
);
|
|
85
87
|
}
|
|
86
88
|
if (!trimmedValue) {
|
|
87
|
-
throw new ConfigError(
|
|
89
|
+
throw new import_hc_http.ConfigError(
|
|
90
|
+
"API key value is required."
|
|
91
|
+
);
|
|
88
92
|
}
|
|
89
93
|
this.apiKeyHeaderName = trimmedHeaderName;
|
|
90
94
|
this.apiKeyValue = trimmedValue;
|
|
91
95
|
}
|
|
92
|
-
|
|
93
|
-
var _a, _b;
|
|
96
|
+
getEnvironment() {
|
|
94
97
|
this.ensureConfigured();
|
|
95
|
-
|
|
96
|
-
const userEmail = (_a = options.email) != null ? _a : email;
|
|
97
|
-
const attributes = {
|
|
98
|
-
...(_b = options.attributes) != null ? _b : {},
|
|
99
|
-
...options.verifyEmailCode === true ? { VERIFY_EMAIL_CODE: "true" } : {}
|
|
100
|
-
};
|
|
101
|
-
const requestPayload = {
|
|
102
|
-
Data: {
|
|
103
|
-
TenantID: config.tenantID,
|
|
104
|
-
Credentials: {
|
|
105
|
-
Email: email,
|
|
106
|
-
Password: password
|
|
107
|
-
},
|
|
108
|
-
User: {
|
|
109
|
-
FirstName: firstName || "Unknown",
|
|
110
|
-
LastName: lastName || "Unknown",
|
|
111
|
-
Email: userEmail,
|
|
112
|
-
Phone: options.phone,
|
|
113
|
-
BirthDate: options.birthDate,
|
|
114
|
-
Gender: options.gender,
|
|
115
|
-
Attributes: attributes
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
return this.http.post(
|
|
120
|
-
`${config.baseUrl}/patient/register`,
|
|
121
|
-
requestPayload,
|
|
122
|
-
{
|
|
123
|
-
"Content-Type": "application/json",
|
|
124
|
-
"X-Tenant-ID": config.tenantID,
|
|
125
|
-
...this.getApiKeyHeader()
|
|
126
|
-
}
|
|
127
|
-
);
|
|
98
|
+
return this.config.environment;
|
|
128
99
|
}
|
|
129
|
-
|
|
130
|
-
var _a, _b, _c, _d, _e;
|
|
100
|
+
getBaseUrl() {
|
|
131
101
|
this.ensureConfigured();
|
|
132
|
-
|
|
133
|
-
const attributes = {
|
|
134
|
-
...(_a = options.attributes) != null ? _a : {},
|
|
135
|
-
...options.verifyEmailCode === true ? { VERIFY_EMAIL_CODE: "true" } : {}
|
|
136
|
-
};
|
|
137
|
-
const requestPayload = {
|
|
138
|
-
Data: {
|
|
139
|
-
TenantID: config.tenantID,
|
|
140
|
-
Credentials: {
|
|
141
|
-
Email: (_b = options.email) != null ? _b : "",
|
|
142
|
-
Password: (_c = options.password) != null ? _c : "",
|
|
143
|
-
TenantID: config.tenantID,
|
|
144
|
-
...options.language ? { Language: options.language } : {}
|
|
145
|
-
},
|
|
146
|
-
User: {
|
|
147
|
-
FirstName: (_d = options.firstName) != null ? _d : "Unknown",
|
|
148
|
-
LastName: (_e = options.lastName) != null ? _e : "Unknown",
|
|
149
|
-
...options.email ? { Email: options.email } : {},
|
|
150
|
-
...options.phone ? { Phone: options.phone } : {},
|
|
151
|
-
...options.birthDate ? { BirthDate: options.birthDate } : {},
|
|
152
|
-
...options.gender ? { Gender: options.gender } : {},
|
|
153
|
-
...options.middleName ? { MiddleName: options.middleName } : {},
|
|
154
|
-
...options.race ? { Race: options.race } : {},
|
|
155
|
-
...options.ethnicity ? { Ethnicity: options.ethnicity } : {},
|
|
156
|
-
...options.sex ? { Sex: options.sex } : {},
|
|
157
|
-
...options.genderIdentity ? { GenderIdentity: options.genderIdentity } : {},
|
|
158
|
-
...options.status !== void 0 ? { Status: options.status } : {},
|
|
159
|
-
...options.address ? { Address: options.address } : {},
|
|
160
|
-
Attributes: attributes
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
return this.http.post(
|
|
165
|
-
`${config.baseUrl}/patient/register`,
|
|
166
|
-
requestPayload,
|
|
167
|
-
{
|
|
168
|
-
"Content-Type": "application/json",
|
|
169
|
-
"X-Tenant-ID": config.tenantID,
|
|
170
|
-
...this.getApiKeyHeader()
|
|
171
|
-
}
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
async verifyEmail(email, code, language = "en", options = { verifyEmailCode: false }) {
|
|
175
|
-
return this.submitOnboardingStep(
|
|
176
|
-
"EMAIL_VERIFY",
|
|
177
|
-
this.buildEmailVerificationInput(email, options),
|
|
178
|
-
code,
|
|
179
|
-
language
|
|
180
|
-
);
|
|
102
|
+
return this.config.baseUrl;
|
|
181
103
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
this.buildEmailVerificationInput(email, options),
|
|
186
|
-
"",
|
|
187
|
-
language
|
|
188
|
-
);
|
|
104
|
+
getTenantId() {
|
|
105
|
+
this.ensureConfigured();
|
|
106
|
+
return this.config.tenantID;
|
|
189
107
|
}
|
|
190
|
-
|
|
191
|
-
return this.
|
|
192
|
-
"RESEND_SMS_VERIFY",
|
|
193
|
-
{
|
|
194
|
-
Email: email,
|
|
195
|
-
Phone: phone
|
|
196
|
-
},
|
|
197
|
-
"",
|
|
198
|
-
language
|
|
199
|
-
);
|
|
108
|
+
getTokens() {
|
|
109
|
+
return this.tokens;
|
|
200
110
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
{
|
|
205
|
-
Email: email,
|
|
206
|
-
Phone: phone
|
|
207
|
-
},
|
|
208
|
-
code,
|
|
209
|
-
language
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
async saveHealthProfile(profile, language = "en") {
|
|
213
|
-
return this.submitOnboardingStep(
|
|
214
|
-
"SAVE_HEALTH_PROFILE",
|
|
215
|
-
profile,
|
|
216
|
-
"",
|
|
217
|
-
language
|
|
218
|
-
);
|
|
111
|
+
getAccessToken() {
|
|
112
|
+
var _a;
|
|
113
|
+
return (_a = this.tokens) == null ? void 0 : _a.accessToken;
|
|
219
114
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
{
|
|
224
|
-
Email: email,
|
|
225
|
-
Address: address
|
|
226
|
-
},
|
|
227
|
-
"",
|
|
228
|
-
language
|
|
229
|
-
);
|
|
115
|
+
getIDToken() {
|
|
116
|
+
var _a;
|
|
117
|
+
return (_a = this.tokens) == null ? void 0 : _a.idToken;
|
|
230
118
|
}
|
|
231
|
-
|
|
119
|
+
getAuthHeader() {
|
|
232
120
|
var _a;
|
|
233
121
|
this.ensureConfigured();
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
"X-Tenant-ID": this.config.tenantID,
|
|
246
|
-
...this.getApiKeyHeader()
|
|
247
|
-
}
|
|
248
|
-
);
|
|
249
|
-
const data = (_a = resp.Data) != null ? _a : resp;
|
|
250
|
-
const tokens = {
|
|
251
|
-
accessToken: data.AccessToken,
|
|
252
|
-
refreshToken: data.RefreshToken,
|
|
253
|
-
idToken: data.IDToken,
|
|
254
|
-
expiresIn: new Date(data.Expiration).getTime()
|
|
122
|
+
if (!((_a = this.tokens) == null ? void 0 : _a.idToken)) {
|
|
123
|
+
throw new import_hc_http.APIError({
|
|
124
|
+
message: "User is not authenticated.",
|
|
125
|
+
code: "UNAUTHORIZED",
|
|
126
|
+
statusCode: 401
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
Authorization: `Bearer ${this.tokens.idToken}`,
|
|
131
|
+
"X-Tenant-ID": this.config.tenantID,
|
|
132
|
+
...this.getApiKeyHeader()
|
|
255
133
|
};
|
|
256
|
-
this.tokens = tokens;
|
|
257
|
-
return tokens;
|
|
258
134
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
135
|
+
logout() {
|
|
136
|
+
this.tokens = void 0;
|
|
137
|
+
}
|
|
138
|
+
// =========================================================================
|
|
139
|
+
// Authentication
|
|
140
|
+
// =========================================================================
|
|
141
|
+
async login(email, password, context = "PATIENT") {
|
|
142
|
+
if (!(email == null ? void 0 : email.trim())) {
|
|
143
|
+
throw new import_hc_http.ValidationError({
|
|
144
|
+
message: "Email is required.",
|
|
145
|
+
code: "INVALID_INPUT"
|
|
146
|
+
});
|
|
264
147
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
{
|
|
275
|
-
|
|
276
|
-
|
|
148
|
+
if (!(password == null ? void 0 : password.trim())) {
|
|
149
|
+
throw new import_hc_http.ValidationError({
|
|
150
|
+
message: "Password is required.",
|
|
151
|
+
code: "INVALID_INPUT"
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
this.ensureConfigured();
|
|
155
|
+
return this.execute(
|
|
156
|
+
"login",
|
|
157
|
+
async () => {
|
|
158
|
+
const response = await this.http.post(
|
|
159
|
+
`${this.config.baseUrl}/api/${this.resolveContextPath(context)}/login`,
|
|
160
|
+
{
|
|
161
|
+
Data: {
|
|
162
|
+
Email: email,
|
|
163
|
+
Password: password,
|
|
164
|
+
TenantID: this.config.tenantID
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
this.headers()
|
|
168
|
+
);
|
|
169
|
+
if (!response.Data) {
|
|
170
|
+
throw new import_hc_http.APIError({
|
|
171
|
+
message: "login: identity authorization data is missing",
|
|
172
|
+
code: "INVALID_RESPONSE",
|
|
173
|
+
details: response
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
this.storeAuthTokens(
|
|
177
|
+
response.Data
|
|
178
|
+
);
|
|
179
|
+
return response;
|
|
277
180
|
}
|
|
278
181
|
);
|
|
279
|
-
const data = (_b = resp.Data) != null ? _b : resp;
|
|
280
|
-
const tokens = {
|
|
281
|
-
accessToken: data.AccessToken,
|
|
282
|
-
refreshToken: data.RefreshToken,
|
|
283
|
-
idToken: data.IDToken,
|
|
284
|
-
expiresIn: new Date(data.Expiration).getTime()
|
|
285
|
-
};
|
|
286
|
-
this.tokens = tokens;
|
|
287
|
-
return tokens;
|
|
288
182
|
}
|
|
289
|
-
async
|
|
290
|
-
var _a;
|
|
183
|
+
async refreshToken(refreshToken, context = "PATIENT") {
|
|
184
|
+
var _a, _b;
|
|
185
|
+
const token = (_b = refreshToken == null ? void 0 : refreshToken.trim()) != null ? _b : (_a = this.tokens) == null ? void 0 : _a.refreshToken;
|
|
186
|
+
if (!(token == null ? void 0 : token.trim())) {
|
|
187
|
+
throw new import_hc_http.ValidationError({
|
|
188
|
+
message: "Refresh token is required.",
|
|
189
|
+
code: "INVALID_INPUT"
|
|
190
|
+
});
|
|
191
|
+
}
|
|
291
192
|
this.ensureConfigured();
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
193
|
+
return this.execute(
|
|
194
|
+
"refreshToken",
|
|
195
|
+
async () => {
|
|
196
|
+
const requestPayload = {
|
|
197
|
+
Data: {
|
|
198
|
+
RefreshToken: token,
|
|
199
|
+
TenantID: this.config.tenantID
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
const response = await this.http.post(
|
|
203
|
+
`${this.config.baseUrl}/api/${this.resolveContextPath(context)}/refresh`,
|
|
204
|
+
requestPayload,
|
|
205
|
+
this.headers()
|
|
206
|
+
);
|
|
207
|
+
if (!response.Data) {
|
|
208
|
+
throw new import_hc_http.APIError({
|
|
209
|
+
message: "refreshToken: identity authorization data is missing",
|
|
210
|
+
code: "INVALID_RESPONSE",
|
|
211
|
+
details: response
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
this.storeAuthTokens(
|
|
215
|
+
response.Data
|
|
216
|
+
);
|
|
217
|
+
return response;
|
|
307
218
|
}
|
|
308
219
|
);
|
|
309
220
|
}
|
|
310
|
-
async
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
221
|
+
async register(email, password, firstName = "Unknown", lastName = "Unknown", options = {}) {
|
|
222
|
+
if (!(email == null ? void 0 : email.trim())) {
|
|
223
|
+
throw new import_hc_http.ValidationError({
|
|
224
|
+
message: "Email is required.",
|
|
225
|
+
code: "INVALID_INPUT"
|
|
226
|
+
});
|
|
316
227
|
}
|
|
317
|
-
if (!
|
|
318
|
-
throw new
|
|
228
|
+
if (!(password == null ? void 0 : password.trim())) {
|
|
229
|
+
throw new import_hc_http.ValidationError({
|
|
230
|
+
message: "Password is required.",
|
|
231
|
+
code: "INVALID_INPUT"
|
|
232
|
+
});
|
|
319
233
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
234
|
+
this.ensureConfigured();
|
|
235
|
+
return this.execute(
|
|
236
|
+
"register",
|
|
237
|
+
() => {
|
|
238
|
+
var _a, _b;
|
|
239
|
+
return this.http.post(
|
|
240
|
+
`${this.config.baseUrl}/api/patient/register`,
|
|
241
|
+
{
|
|
242
|
+
Data: {
|
|
243
|
+
TenantID: this.config.tenantID,
|
|
244
|
+
Credentials: {
|
|
245
|
+
Email: email,
|
|
246
|
+
Password: password
|
|
247
|
+
},
|
|
248
|
+
User: {
|
|
249
|
+
FirstName: firstName,
|
|
250
|
+
LastName: lastName,
|
|
251
|
+
Email: (_a = options.email) != null ? _a : email,
|
|
252
|
+
Phone: options.phone,
|
|
253
|
+
BirthDate: options.birthDate,
|
|
254
|
+
Gender: options.gender,
|
|
255
|
+
Attributes: {
|
|
256
|
+
...(_b = options.attributes) != null ? _b : {},
|
|
257
|
+
...options.verifyEmailCode === true ? {
|
|
258
|
+
VERIFY_EMAIL_CODE: "true"
|
|
259
|
+
} : {}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
this.headers()
|
|
265
|
+
);
|
|
333
266
|
}
|
|
334
267
|
);
|
|
335
268
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
return (_a = this.tokens) == null ? void 0 : _a.idToken;
|
|
343
|
-
}
|
|
344
|
-
async getUserInfo() {
|
|
345
|
-
var _a;
|
|
346
|
-
this.ensureConfigured();
|
|
347
|
-
if (!((_a = this.tokens) == null ? void 0 : _a.idToken)) {
|
|
348
|
-
throw new AuthError("No ID token available");
|
|
269
|
+
async requestPasswordReset(email, context = "PATIENT", isOTP = false) {
|
|
270
|
+
if (!(email == null ? void 0 : email.trim())) {
|
|
271
|
+
throw new import_hc_http.ValidationError({
|
|
272
|
+
message: "Email is required.",
|
|
273
|
+
code: "INVALID_INPUT"
|
|
274
|
+
});
|
|
349
275
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
276
|
+
this.ensureConfigured();
|
|
277
|
+
return this.execute(
|
|
278
|
+
"requestPasswordReset",
|
|
279
|
+
() => this.http.post(
|
|
280
|
+
`${this.config.baseUrl}/api/${this.resolveContextPath(context)}/resetpassword`,
|
|
281
|
+
{
|
|
282
|
+
Data: {
|
|
283
|
+
Email: email,
|
|
284
|
+
TenantID: this.config.tenantID,
|
|
285
|
+
IsPasswordResetWithOTP: isOTP
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
this.headers()
|
|
289
|
+
)
|
|
353
290
|
);
|
|
354
291
|
}
|
|
355
|
-
|
|
356
|
-
if (!
|
|
357
|
-
throw new
|
|
292
|
+
async confirmPasswordReset(email, password, code, context = "PATIENT") {
|
|
293
|
+
if (!(email == null ? void 0 : email.trim())) {
|
|
294
|
+
throw new import_hc_http.ValidationError({
|
|
295
|
+
message: "Email is required.",
|
|
296
|
+
code: "INVALID_INPUT"
|
|
297
|
+
});
|
|
358
298
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
case "RESEND_EMAIL_VERIFY":
|
|
365
|
-
return {
|
|
366
|
-
Email: user.Email,
|
|
367
|
-
TenantID: this.config.tenantID,
|
|
368
|
-
...user.Attributes ? { Attributes: user.Attributes } : {}
|
|
369
|
-
};
|
|
370
|
-
case "RESEND_SMS_VERIFY":
|
|
371
|
-
case "SMS_VERIFY":
|
|
372
|
-
return {
|
|
373
|
-
Email: user.Email,
|
|
374
|
-
TenantID: this.config.tenantID,
|
|
375
|
-
Phone: user.Phone
|
|
376
|
-
};
|
|
377
|
-
case "SAVE_HEALTH_PROFILE":
|
|
378
|
-
return {
|
|
379
|
-
Email: user.Email,
|
|
380
|
-
TenantID: this.config.tenantID,
|
|
381
|
-
FirstName: user.FirstName,
|
|
382
|
-
LastName: user.LastName,
|
|
383
|
-
BirthDate: user.BirthDate,
|
|
384
|
-
Gender: user.Gender,
|
|
385
|
-
Sex: user.Sex,
|
|
386
|
-
Status: (_a = user.Status) != null ? _a : 0,
|
|
387
|
-
Phone: user.Phone,
|
|
388
|
-
...user.Race !== void 0 ? { Race: user.Race } : {},
|
|
389
|
-
...user.Ethnicity !== void 0 ? { Ethnicity: user.Ethnicity } : {}
|
|
390
|
-
};
|
|
391
|
-
case "SAVE_ADDRESS":
|
|
392
|
-
return {
|
|
393
|
-
Email: user.Email,
|
|
394
|
-
TenantID: this.config.tenantID,
|
|
395
|
-
Address: user.Address ? {
|
|
396
|
-
StreetAndNumber: user.Address.StreetAndNumber,
|
|
397
|
-
Extension: user.Address.Extension,
|
|
398
|
-
City: user.Address.City,
|
|
399
|
-
State: user.Address.State,
|
|
400
|
-
PostalCode: user.Address.PostalCode,
|
|
401
|
-
Country: user.Address.Country
|
|
402
|
-
} : void 0
|
|
403
|
-
};
|
|
299
|
+
if (!(password == null ? void 0 : password.trim())) {
|
|
300
|
+
throw new import_hc_http.ValidationError({
|
|
301
|
+
message: "Password is required.",
|
|
302
|
+
code: "INVALID_INPUT"
|
|
303
|
+
});
|
|
404
304
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
...attributes ? { Attributes: attributes } : {}
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
buildEmailVerificationAttributes(options) {
|
|
414
|
-
var _a;
|
|
415
|
-
const attributes = {
|
|
416
|
-
...(_a = options.attributes) != null ? _a : {}
|
|
417
|
-
};
|
|
418
|
-
if (options.verifyEmailCode === true) {
|
|
419
|
-
attributes.VERIFY_EMAIL_CODE = "true";
|
|
305
|
+
if (!(code == null ? void 0 : code.trim())) {
|
|
306
|
+
throw new import_hc_http.ValidationError({
|
|
307
|
+
message: "Reset code is required.",
|
|
308
|
+
code: "INVALID_INPUT"
|
|
309
|
+
});
|
|
420
310
|
}
|
|
421
|
-
|
|
311
|
+
this.ensureConfigured();
|
|
312
|
+
return this.execute(
|
|
313
|
+
"confirmPasswordReset",
|
|
314
|
+
() => this.http.post(
|
|
315
|
+
`${this.config.baseUrl}/api/${this.resolveContextPath(context)}/password`,
|
|
316
|
+
{
|
|
317
|
+
Data: {
|
|
318
|
+
Email: email,
|
|
319
|
+
Password: password,
|
|
320
|
+
Code: code,
|
|
321
|
+
TenantID: this.config.tenantID
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
this.headers()
|
|
325
|
+
)
|
|
326
|
+
);
|
|
422
327
|
}
|
|
423
|
-
|
|
328
|
+
async getPatientHeader() {
|
|
424
329
|
this.ensureConfigured();
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
330
|
+
return this.execute(
|
|
331
|
+
"getPatientHeader",
|
|
332
|
+
() => this.http.get(
|
|
333
|
+
`${this.config.baseUrl}/api/patient/header`,
|
|
334
|
+
this.authHeaders()
|
|
335
|
+
)
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
// =========================================================================
|
|
339
|
+
// Private
|
|
340
|
+
// =========================================================================
|
|
341
|
+
async execute(operation, request) {
|
|
342
|
+
let response;
|
|
343
|
+
try {
|
|
344
|
+
response = await request();
|
|
345
|
+
} catch (err) {
|
|
346
|
+
if (err instanceof import_hc_http.APIError) {
|
|
347
|
+
throw err;
|
|
431
348
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
349
|
+
if (err instanceof TypeError) {
|
|
350
|
+
throw new import_hc_http.NetworkError({
|
|
351
|
+
message: `${operation}: network request failed`,
|
|
352
|
+
code: "NETWORK_ERROR",
|
|
353
|
+
details: err
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
if (err instanceof DOMException) {
|
|
357
|
+
if (err.name === "AbortError") {
|
|
358
|
+
throw new import_hc_http.NetworkError({
|
|
359
|
+
message: `${operation}: request aborted`,
|
|
360
|
+
code: "REQUEST_ABORTED",
|
|
361
|
+
details: err
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (err instanceof Error) {
|
|
366
|
+
throw new import_hc_http.APIError({
|
|
367
|
+
message: `${operation}: ${err.message}`,
|
|
368
|
+
code: "UNKNOWN_ERROR",
|
|
369
|
+
details: err
|
|
370
|
+
});
|
|
440
371
|
}
|
|
372
|
+
throw new import_hc_http.APIError({
|
|
373
|
+
message: `${operation}: unexpected runtime failure`,
|
|
374
|
+
code: "UNKNOWN_ERROR",
|
|
375
|
+
details: err
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
if (response == null) {
|
|
379
|
+
throw new import_hc_http.APIError({
|
|
380
|
+
message: `${operation}: empty response received`,
|
|
381
|
+
code: "EMPTY_RESPONSE",
|
|
382
|
+
details: response
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
if (!this.isApiResponse(response)) {
|
|
386
|
+
throw new import_hc_http.APIError({
|
|
387
|
+
message: `${operation}: invalid API response structure`,
|
|
388
|
+
code: "INVALID_RESPONSE",
|
|
389
|
+
details: response
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
if (!response.IsOK) {
|
|
393
|
+
throw this.mapBackendError(
|
|
394
|
+
operation,
|
|
395
|
+
response
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
return response;
|
|
399
|
+
}
|
|
400
|
+
mapBackendError(operation, response) {
|
|
401
|
+
return new import_hc_http.HCServiceError(
|
|
402
|
+
operation,
|
|
403
|
+
response.ErrorMessage || "Unknown backend error",
|
|
404
|
+
response
|
|
441
405
|
);
|
|
442
406
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
throw new AuthError("No ID token available");
|
|
407
|
+
isApiResponse(value) {
|
|
408
|
+
if (!value || typeof value !== "object") {
|
|
409
|
+
return false;
|
|
447
410
|
}
|
|
411
|
+
const response = value;
|
|
412
|
+
return "IsOK" in response && typeof response.IsOK === "boolean" && "Data" in response && "ErrorMessage" in response;
|
|
413
|
+
}
|
|
414
|
+
headers() {
|
|
448
415
|
return {
|
|
449
|
-
|
|
416
|
+
Accept: "application/json",
|
|
417
|
+
"Content-Type": "application/json",
|
|
450
418
|
"X-Tenant-ID": this.config.tenantID,
|
|
451
419
|
...this.getApiKeyHeader()
|
|
452
420
|
};
|
|
453
421
|
}
|
|
422
|
+
authHeaders() {
|
|
423
|
+
return {
|
|
424
|
+
...this.headers(),
|
|
425
|
+
...this.getAuthHeader()
|
|
426
|
+
};
|
|
427
|
+
}
|
|
454
428
|
getApiKeyHeader() {
|
|
455
429
|
if (!this.apiKeyHeaderName || !this.apiKeyValue) {
|
|
456
430
|
return {};
|
|
@@ -459,24 +433,59 @@ var HCLoginClient = class {
|
|
|
459
433
|
[this.apiKeyHeaderName]: this.apiKeyValue
|
|
460
434
|
};
|
|
461
435
|
}
|
|
462
|
-
|
|
436
|
+
resolveContextPath(context) {
|
|
437
|
+
switch (context) {
|
|
438
|
+
case "PATIENT":
|
|
439
|
+
return "patient";
|
|
440
|
+
case "PROVIDER":
|
|
441
|
+
return "provider";
|
|
442
|
+
case "KB":
|
|
443
|
+
return "kb";
|
|
444
|
+
case "ADMIN_PLATFORM":
|
|
445
|
+
return "admin/platform";
|
|
446
|
+
default:
|
|
447
|
+
return "patient";
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
ensureConfigured() {
|
|
463
451
|
if (!this.config) {
|
|
464
|
-
throw new ConfigError(
|
|
452
|
+
throw new import_hc_http.ConfigError(
|
|
453
|
+
"Login client must be configured before use."
|
|
454
|
+
);
|
|
465
455
|
}
|
|
466
|
-
return this.config.baseUrl;
|
|
467
456
|
}
|
|
468
|
-
|
|
457
|
+
storeAuthTokens(raw) {
|
|
458
|
+
var _a;
|
|
459
|
+
this.tokens = {
|
|
460
|
+
accessToken: raw.AccessToken,
|
|
461
|
+
refreshToken: raw.RefreshToken,
|
|
462
|
+
idToken: (_a = raw.IDToken) != null ? _a : null,
|
|
463
|
+
expiresAt: this.resolveExpiration(
|
|
464
|
+
raw
|
|
465
|
+
)
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
resolveExpiration(raw) {
|
|
469
469
|
var _a;
|
|
470
|
-
if (
|
|
471
|
-
|
|
470
|
+
if (raw.Expiration) {
|
|
471
|
+
const parsed = new Date(
|
|
472
|
+
raw.Expiration
|
|
473
|
+
).getTime();
|
|
474
|
+
return Number.isNaN(parsed) ? 0 : parsed;
|
|
472
475
|
}
|
|
473
|
-
return
|
|
476
|
+
return (_a = raw.ExpiresIn) != null ? _a : 0;
|
|
474
477
|
}
|
|
475
478
|
};
|
|
479
|
+
|
|
480
|
+
// src/errors.ts
|
|
481
|
+
var import_hc_http2 = require("@healthcloudai/hc-http");
|
|
476
482
|
// Annotate the CommonJS export names for ESM import in node:
|
|
477
483
|
0 && (module.exports = {
|
|
478
|
-
|
|
484
|
+
APIError,
|
|
479
485
|
ConfigError,
|
|
480
486
|
HCLoginClient,
|
|
481
|
-
|
|
487
|
+
HCServiceError,
|
|
488
|
+
NetworkError,
|
|
489
|
+
ValidationError,
|
|
490
|
+
errorFromHttpStatus
|
|
482
491
|
});
|