@healthcloudai/hc-login-connector 0.1.0 → 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 +372 -369
- package/dist/index.d.cts +96 -194
- package/dist/index.d.ts +96 -194
- package/dist/index.js +380 -367
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -20,443 +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
96
|
getEnvironment() {
|
|
93
|
-
|
|
94
|
-
throw new ConfigError("Login client must be configured first.");
|
|
95
|
-
}
|
|
97
|
+
this.ensureConfigured();
|
|
96
98
|
return this.config.environment;
|
|
97
99
|
}
|
|
98
|
-
|
|
99
|
-
var _a, _b;
|
|
100
|
+
getBaseUrl() {
|
|
100
101
|
this.ensureConfigured();
|
|
101
|
-
|
|
102
|
-
const userEmail = (_a = options.email) != null ? _a : email;
|
|
103
|
-
const attributes = {
|
|
104
|
-
...(_b = options.attributes) != null ? _b : {},
|
|
105
|
-
...options.verifyEmailCode === true ? { VERIFY_EMAIL_CODE: "true" } : {}
|
|
106
|
-
};
|
|
107
|
-
const requestPayload = {
|
|
108
|
-
Data: {
|
|
109
|
-
TenantID: config.tenantID,
|
|
110
|
-
Credentials: {
|
|
111
|
-
Email: email,
|
|
112
|
-
Password: password
|
|
113
|
-
},
|
|
114
|
-
User: {
|
|
115
|
-
FirstName: firstName || "Unknown",
|
|
116
|
-
LastName: lastName || "Unknown",
|
|
117
|
-
Email: userEmail,
|
|
118
|
-
Phone: options.phone,
|
|
119
|
-
BirthDate: options.birthDate,
|
|
120
|
-
Gender: options.gender,
|
|
121
|
-
Attributes: attributes
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
return this.http.post(
|
|
126
|
-
`${config.baseUrl}/patient/register`,
|
|
127
|
-
requestPayload,
|
|
128
|
-
{
|
|
129
|
-
"Content-Type": "application/json",
|
|
130
|
-
"X-Tenant-ID": config.tenantID,
|
|
131
|
-
...this.getApiKeyHeader()
|
|
132
|
-
}
|
|
133
|
-
);
|
|
102
|
+
return this.config.baseUrl;
|
|
134
103
|
}
|
|
135
|
-
|
|
136
|
-
var _a, _b, _c, _d, _e;
|
|
104
|
+
getTenantId() {
|
|
137
105
|
this.ensureConfigured();
|
|
138
|
-
|
|
139
|
-
const attributes = {
|
|
140
|
-
...(_a = options.attributes) != null ? _a : {},
|
|
141
|
-
...options.verifyEmailCode === true ? { VERIFY_EMAIL_CODE: "true" } : {}
|
|
142
|
-
};
|
|
143
|
-
const requestPayload = {
|
|
144
|
-
Data: {
|
|
145
|
-
TenantID: config.tenantID,
|
|
146
|
-
Credentials: {
|
|
147
|
-
Email: (_b = options.email) != null ? _b : "",
|
|
148
|
-
Password: (_c = options.password) != null ? _c : "",
|
|
149
|
-
TenantID: config.tenantID,
|
|
150
|
-
...options.language ? { Language: options.language } : {}
|
|
151
|
-
},
|
|
152
|
-
User: {
|
|
153
|
-
FirstName: (_d = options.firstName) != null ? _d : "Unknown",
|
|
154
|
-
LastName: (_e = options.lastName) != null ? _e : "Unknown",
|
|
155
|
-
...options.email ? { Email: options.email } : {},
|
|
156
|
-
...options.phone ? { Phone: options.phone } : {},
|
|
157
|
-
...options.birthDate ? { BirthDate: options.birthDate } : {},
|
|
158
|
-
...options.gender ? { Gender: options.gender } : {},
|
|
159
|
-
...options.middleName ? { MiddleName: options.middleName } : {},
|
|
160
|
-
...options.race ? { Race: options.race } : {},
|
|
161
|
-
...options.ethnicity ? { Ethnicity: options.ethnicity } : {},
|
|
162
|
-
...options.sex ? { Sex: options.sex } : {},
|
|
163
|
-
...options.genderIdentity ? { GenderIdentity: options.genderIdentity } : {},
|
|
164
|
-
...options.status !== void 0 ? { Status: options.status } : {},
|
|
165
|
-
...options.address ? { Address: options.address } : {},
|
|
166
|
-
Attributes: attributes
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
return this.http.post(
|
|
171
|
-
`${config.baseUrl}/patient/register`,
|
|
172
|
-
requestPayload,
|
|
173
|
-
{
|
|
174
|
-
"Content-Type": "application/json",
|
|
175
|
-
"X-Tenant-ID": config.tenantID,
|
|
176
|
-
...this.getApiKeyHeader()
|
|
177
|
-
}
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
async verifyEmail(email, code, language = "en", options = { verifyEmailCode: false }) {
|
|
181
|
-
return this.submitOnboardingStep(
|
|
182
|
-
"EMAIL_VERIFY",
|
|
183
|
-
this.buildEmailVerificationInput(email, options),
|
|
184
|
-
code,
|
|
185
|
-
language
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
async resendEmailVerify(email, language = "en", options = { verifyEmailCode: false }) {
|
|
189
|
-
return this.submitOnboardingStep(
|
|
190
|
-
"RESEND_EMAIL_VERIFY",
|
|
191
|
-
this.buildEmailVerificationInput(email, options),
|
|
192
|
-
"",
|
|
193
|
-
language
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
async resendSmsVerify(email, phone, language = "en") {
|
|
197
|
-
return this.submitOnboardingStep(
|
|
198
|
-
"RESEND_SMS_VERIFY",
|
|
199
|
-
{
|
|
200
|
-
Email: email,
|
|
201
|
-
Phone: phone
|
|
202
|
-
},
|
|
203
|
-
"",
|
|
204
|
-
language
|
|
205
|
-
);
|
|
106
|
+
return this.config.tenantID;
|
|
206
107
|
}
|
|
207
|
-
|
|
208
|
-
return this.
|
|
209
|
-
"SMS_VERIFY",
|
|
210
|
-
{
|
|
211
|
-
Email: email,
|
|
212
|
-
Phone: phone
|
|
213
|
-
},
|
|
214
|
-
code,
|
|
215
|
-
language
|
|
216
|
-
);
|
|
108
|
+
getTokens() {
|
|
109
|
+
return this.tokens;
|
|
217
110
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
profile,
|
|
222
|
-
"",
|
|
223
|
-
language
|
|
224
|
-
);
|
|
111
|
+
getAccessToken() {
|
|
112
|
+
var _a;
|
|
113
|
+
return (_a = this.tokens) == null ? void 0 : _a.accessToken;
|
|
225
114
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
{
|
|
230
|
-
Email: email,
|
|
231
|
-
Address: address
|
|
232
|
-
},
|
|
233
|
-
"",
|
|
234
|
-
language
|
|
235
|
-
);
|
|
115
|
+
getIDToken() {
|
|
116
|
+
var _a;
|
|
117
|
+
return (_a = this.tokens) == null ? void 0 : _a.idToken;
|
|
236
118
|
}
|
|
237
|
-
|
|
119
|
+
getAuthHeader() {
|
|
238
120
|
var _a;
|
|
239
121
|
this.ensureConfigured();
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
"X-Tenant-ID": this.config.tenantID,
|
|
252
|
-
...this.getApiKeyHeader()
|
|
253
|
-
}
|
|
254
|
-
);
|
|
255
|
-
const data = (_a = resp.Data) != null ? _a : resp;
|
|
256
|
-
const tokens = {
|
|
257
|
-
accessToken: data.AccessToken,
|
|
258
|
-
refreshToken: data.RefreshToken,
|
|
259
|
-
idToken: data.IDToken,
|
|
260
|
-
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()
|
|
261
133
|
};
|
|
262
|
-
this.tokens = tokens;
|
|
263
|
-
return tokens;
|
|
264
134
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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
|
+
});
|
|
270
147
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
{
|
|
281
|
-
|
|
282
|
-
|
|
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;
|
|
283
180
|
}
|
|
284
181
|
);
|
|
285
|
-
const data = (_b = resp.Data) != null ? _b : resp;
|
|
286
|
-
const tokens = {
|
|
287
|
-
accessToken: data.AccessToken,
|
|
288
|
-
refreshToken: data.RefreshToken,
|
|
289
|
-
idToken: data.IDToken,
|
|
290
|
-
expiresIn: new Date(data.Expiration).getTime()
|
|
291
|
-
};
|
|
292
|
-
this.tokens = tokens;
|
|
293
|
-
return tokens;
|
|
294
182
|
}
|
|
295
|
-
async
|
|
296
|
-
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
|
+
}
|
|
297
192
|
this.ensureConfigured();
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
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;
|
|
313
218
|
}
|
|
314
219
|
);
|
|
315
220
|
}
|
|
316
|
-
async
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
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
|
+
});
|
|
322
227
|
}
|
|
323
|
-
if (!
|
|
324
|
-
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
|
+
});
|
|
325
233
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
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
|
+
);
|
|
339
266
|
}
|
|
340
267
|
);
|
|
341
268
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
return (_a = this.tokens) == null ? void 0 : _a.idToken;
|
|
349
|
-
}
|
|
350
|
-
async getUserInfo() {
|
|
351
|
-
var _a;
|
|
352
|
-
this.ensureConfigured();
|
|
353
|
-
if (!((_a = this.tokens) == null ? void 0 : _a.idToken)) {
|
|
354
|
-
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
|
+
});
|
|
355
275
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
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
|
+
)
|
|
359
290
|
);
|
|
360
291
|
}
|
|
361
|
-
|
|
362
|
-
if (!
|
|
363
|
-
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
|
+
});
|
|
364
298
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
case "RESEND_EMAIL_VERIFY":
|
|
371
|
-
return {
|
|
372
|
-
Email: user.Email,
|
|
373
|
-
TenantID: this.config.tenantID,
|
|
374
|
-
...user.Attributes ? { Attributes: user.Attributes } : {}
|
|
375
|
-
};
|
|
376
|
-
case "RESEND_SMS_VERIFY":
|
|
377
|
-
case "SMS_VERIFY":
|
|
378
|
-
return {
|
|
379
|
-
Email: user.Email,
|
|
380
|
-
TenantID: this.config.tenantID,
|
|
381
|
-
Phone: user.Phone
|
|
382
|
-
};
|
|
383
|
-
case "SAVE_HEALTH_PROFILE":
|
|
384
|
-
return {
|
|
385
|
-
Email: user.Email,
|
|
386
|
-
TenantID: this.config.tenantID,
|
|
387
|
-
FirstName: user.FirstName,
|
|
388
|
-
LastName: user.LastName,
|
|
389
|
-
BirthDate: user.BirthDate,
|
|
390
|
-
Gender: user.Gender,
|
|
391
|
-
Sex: user.Sex,
|
|
392
|
-
Status: (_a = user.Status) != null ? _a : 0,
|
|
393
|
-
Phone: user.Phone,
|
|
394
|
-
...user.Race !== void 0 ? { Race: user.Race } : {},
|
|
395
|
-
...user.Ethnicity !== void 0 ? { Ethnicity: user.Ethnicity } : {}
|
|
396
|
-
};
|
|
397
|
-
case "SAVE_ADDRESS":
|
|
398
|
-
return {
|
|
399
|
-
Email: user.Email,
|
|
400
|
-
TenantID: this.config.tenantID,
|
|
401
|
-
Address: user.Address ? {
|
|
402
|
-
StreetAndNumber: user.Address.StreetAndNumber,
|
|
403
|
-
Extension: user.Address.Extension,
|
|
404
|
-
City: user.Address.City,
|
|
405
|
-
State: user.Address.State,
|
|
406
|
-
PostalCode: user.Address.PostalCode,
|
|
407
|
-
Country: user.Address.Country
|
|
408
|
-
} : void 0
|
|
409
|
-
};
|
|
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
|
+
});
|
|
410
304
|
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
...attributes ? { Attributes: attributes } : {}
|
|
417
|
-
};
|
|
418
|
-
}
|
|
419
|
-
buildEmailVerificationAttributes(options) {
|
|
420
|
-
var _a;
|
|
421
|
-
const attributes = {
|
|
422
|
-
...(_a = options.attributes) != null ? _a : {}
|
|
423
|
-
};
|
|
424
|
-
if (options.verifyEmailCode === true) {
|
|
425
|
-
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
|
+
});
|
|
426
310
|
}
|
|
427
|
-
|
|
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
|
+
);
|
|
428
327
|
}
|
|
429
|
-
|
|
328
|
+
async getPatientHeader() {
|
|
430
329
|
this.ensureConfigured();
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
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;
|
|
437
348
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
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
|
+
});
|
|
446
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
|
|
447
405
|
);
|
|
448
406
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
throw new AuthError("No ID token available");
|
|
407
|
+
isApiResponse(value) {
|
|
408
|
+
if (!value || typeof value !== "object") {
|
|
409
|
+
return false;
|
|
453
410
|
}
|
|
411
|
+
const response = value;
|
|
412
|
+
return "IsOK" in response && typeof response.IsOK === "boolean" && "Data" in response && "ErrorMessage" in response;
|
|
413
|
+
}
|
|
414
|
+
headers() {
|
|
454
415
|
return {
|
|
455
|
-
|
|
416
|
+
Accept: "application/json",
|
|
417
|
+
"Content-Type": "application/json",
|
|
456
418
|
"X-Tenant-ID": this.config.tenantID,
|
|
457
419
|
...this.getApiKeyHeader()
|
|
458
420
|
};
|
|
459
421
|
}
|
|
422
|
+
authHeaders() {
|
|
423
|
+
return {
|
|
424
|
+
...this.headers(),
|
|
425
|
+
...this.getAuthHeader()
|
|
426
|
+
};
|
|
427
|
+
}
|
|
460
428
|
getApiKeyHeader() {
|
|
461
429
|
if (!this.apiKeyHeaderName || !this.apiKeyValue) {
|
|
462
430
|
return {};
|
|
@@ -465,24 +433,59 @@ var HCLoginClient = class {
|
|
|
465
433
|
[this.apiKeyHeaderName]: this.apiKeyValue
|
|
466
434
|
};
|
|
467
435
|
}
|
|
468
|
-
|
|
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() {
|
|
469
451
|
if (!this.config) {
|
|
470
|
-
throw new ConfigError(
|
|
452
|
+
throw new import_hc_http.ConfigError(
|
|
453
|
+
"Login client must be configured before use."
|
|
454
|
+
);
|
|
471
455
|
}
|
|
472
|
-
return this.config.baseUrl;
|
|
473
456
|
}
|
|
474
|
-
|
|
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) {
|
|
475
469
|
var _a;
|
|
476
|
-
if (
|
|
477
|
-
|
|
470
|
+
if (raw.Expiration) {
|
|
471
|
+
const parsed = new Date(
|
|
472
|
+
raw.Expiration
|
|
473
|
+
).getTime();
|
|
474
|
+
return Number.isNaN(parsed) ? 0 : parsed;
|
|
478
475
|
}
|
|
479
|
-
return
|
|
476
|
+
return (_a = raw.ExpiresIn) != null ? _a : 0;
|
|
480
477
|
}
|
|
481
478
|
};
|
|
479
|
+
|
|
480
|
+
// src/errors.ts
|
|
481
|
+
var import_hc_http2 = require("@healthcloudai/hc-http");
|
|
482
482
|
// Annotate the CommonJS export names for ESM import in node:
|
|
483
483
|
0 && (module.exports = {
|
|
484
|
-
|
|
484
|
+
APIError,
|
|
485
485
|
ConfigError,
|
|
486
486
|
HCLoginClient,
|
|
487
|
-
|
|
487
|
+
HCServiceError,
|
|
488
|
+
NetworkError,
|
|
489
|
+
ValidationError,
|
|
490
|
+
errorFromHttpStatus
|
|
488
491
|
});
|