@healthcloudai/hc-safe-cdx 0.2.2 → 0.4.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 +45 -16
- package/dist/index.cjs +183 -133
- package/dist/index.d.cts +28 -60
- package/dist/index.d.ts +28 -60
- package/dist/index.js +184 -132
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
// src/client.ts
|
|
2
|
-
|
|
3
|
-
constructor(message, response) {
|
|
4
|
-
super(message);
|
|
5
|
-
this.name = "SafeCDXError";
|
|
6
|
-
this.response = response;
|
|
7
|
-
Object.setPrototypeOf(this, _SafeCDXError.prototype);
|
|
8
|
-
}
|
|
9
|
-
};
|
|
2
|
+
import { HCBaseConnector, APIError, ConfigError, HCServiceError, ValidationError } from "@healthcloudai/hc-http";
|
|
10
3
|
var ENV_HOST = {
|
|
11
4
|
dev: "dev-api-hcs.healthcloud-services.com",
|
|
12
5
|
uat: "uat-api-hcs.healthcloud-services.com",
|
|
@@ -16,7 +9,7 @@ var ROUTE_PREFIX = "api/console/hcservice/safecdx";
|
|
|
16
9
|
function buildSafeCdxBaseUrl(environment) {
|
|
17
10
|
const host = ENV_HOST[environment];
|
|
18
11
|
if (!host) {
|
|
19
|
-
throw new
|
|
12
|
+
throw new ConfigError("Invalid Safe CDX environment.");
|
|
20
13
|
}
|
|
21
14
|
return `https://${host}/${ROUTE_PREFIX}`;
|
|
22
15
|
}
|
|
@@ -31,24 +24,12 @@ function buildUrl(baseUrl, route, query) {
|
|
|
31
24
|
}
|
|
32
25
|
return url.toString();
|
|
33
26
|
}
|
|
34
|
-
var HCSafeCDXClient = class {
|
|
27
|
+
var HCSafeCDXClient = class extends HCBaseConnector {
|
|
35
28
|
constructor(httpClient, loginClient) {
|
|
36
|
-
|
|
37
|
-
this.
|
|
29
|
+
super(httpClient);
|
|
30
|
+
this.auth = loginClient;
|
|
38
31
|
this.baseUrl = buildSafeCdxBaseUrl(loginClient.getEnvironment());
|
|
39
32
|
}
|
|
40
|
-
setApiKey(headerName, value) {
|
|
41
|
-
const trimmedHeaderName = headerName == null ? void 0 : headerName.trim();
|
|
42
|
-
const trimmedValue = value == null ? void 0 : value.trim();
|
|
43
|
-
if (!trimmedHeaderName) {
|
|
44
|
-
throw new SafeCDXError("API key header name is required.");
|
|
45
|
-
}
|
|
46
|
-
if (!trimmedValue) {
|
|
47
|
-
throw new SafeCDXError("API key value is required.");
|
|
48
|
-
}
|
|
49
|
-
this.apiKeyHeaderName = trimmedHeaderName;
|
|
50
|
-
this.apiKeyValue = trimmedValue;
|
|
51
|
-
}
|
|
52
33
|
// -------------------------------------------------------------------------
|
|
53
34
|
// Test Profiles
|
|
54
35
|
// -------------------------------------------------------------------------
|
|
@@ -57,27 +38,32 @@ var HCSafeCDXClient = class {
|
|
|
57
38
|
* Resolves the SafeCDX test profile associated with a GTIN barcode.
|
|
58
39
|
*/
|
|
59
40
|
async getTestProfileByGTIN(gtin) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
41
|
+
const resolvedGtin = this.requireValue(gtin, "GTIN");
|
|
42
|
+
return this.execute(
|
|
43
|
+
"getTestProfileByGTIN",
|
|
44
|
+
() => this.http.get(
|
|
45
|
+
this.url(`gs1/${encodeURIComponent(resolvedGtin)}`),
|
|
46
|
+
this.getAuthHeaders()
|
|
47
|
+
)
|
|
63
48
|
);
|
|
64
49
|
}
|
|
65
50
|
/**
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
async
|
|
51
|
+
* POST test/profiles/by-account
|
|
52
|
+
*
|
|
53
|
+
* Returns test profiles configured for the authenticated patient's account.
|
|
54
|
+
* TenantId is resolved by the backend from the authenticated patient context.
|
|
55
|
+
*/
|
|
56
|
+
async listTestProfilesByAccount(includeRegisterTestDetails = true) {
|
|
72
57
|
const request = {
|
|
73
|
-
Data: {
|
|
74
|
-
IncludeRegisterTestDetails: includeRegisterTestDetails
|
|
75
|
-
}
|
|
58
|
+
Data: { IncludeRegisterTestDetails: includeRegisterTestDetails }
|
|
76
59
|
};
|
|
77
|
-
return this.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
60
|
+
return this.executeSafe(
|
|
61
|
+
"listTestProfilesByAccount",
|
|
62
|
+
() => this.http.post(
|
|
63
|
+
this.url("test/profiles/by-account"),
|
|
64
|
+
request,
|
|
65
|
+
this.getAuthHeaders()
|
|
66
|
+
)
|
|
81
67
|
);
|
|
82
68
|
}
|
|
83
69
|
// -------------------------------------------------------------------------
|
|
@@ -88,34 +74,42 @@ var HCSafeCDXClient = class {
|
|
|
88
74
|
* Requests a pre-signed URL used to upload a test image.
|
|
89
75
|
*/
|
|
90
76
|
async createUploadUrl(userTestResultId, gtin, imageType = "jpg") {
|
|
77
|
+
const resolvedUserTestResultId = this.requireValue(userTestResultId, "User test result ID");
|
|
78
|
+
const resolvedGtin = this.requireValue(gtin, "GTIN");
|
|
79
|
+
const resolvedImageType = this.requireValue(imageType, "Image type");
|
|
91
80
|
const request = {
|
|
92
81
|
Data: {
|
|
93
|
-
Gtin:
|
|
94
|
-
UserTestResultId:
|
|
95
|
-
Metadata: {
|
|
96
|
-
ImageType: imageType
|
|
97
|
-
}
|
|
82
|
+
Gtin: resolvedGtin,
|
|
83
|
+
UserTestResultId: resolvedUserTestResultId,
|
|
84
|
+
Metadata: { ImageType: resolvedImageType }
|
|
98
85
|
}
|
|
99
86
|
};
|
|
100
|
-
return this.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
87
|
+
return this.execute(
|
|
88
|
+
"createUploadUrl",
|
|
89
|
+
() => this.http.post(
|
|
90
|
+
this.url("upload/url"),
|
|
91
|
+
request,
|
|
92
|
+
this.getAuthHeaders()
|
|
93
|
+
)
|
|
104
94
|
);
|
|
105
95
|
}
|
|
106
96
|
/**
|
|
107
97
|
* PUT preSignedURL
|
|
108
98
|
* Uploads the image directly to the pre-signed storage URL.
|
|
109
99
|
*
|
|
110
|
-
* This request does
|
|
111
|
-
*
|
|
100
|
+
* This request does NOT call a SafeCDX API route and does NOT send
|
|
101
|
+
* Health Cloud auth headers — it targets the storage provider directly.
|
|
102
|
+
* The pre-signed URL embeds credentials; no Authorization header is needed.
|
|
112
103
|
*/
|
|
113
104
|
async uploadImage(preSignedURL, image, contentType = "image/jpeg") {
|
|
114
|
-
const
|
|
105
|
+
const resolvedPreSignedURL = this.requireValue(preSignedURL, "Pre-signed URL");
|
|
106
|
+
const resolvedContentType = this.requireValue(contentType, "Content type");
|
|
107
|
+
if (image == null) {
|
|
108
|
+
throw new ValidationError({ message: "Image is required.", code: "INVALID_INPUT" });
|
|
109
|
+
}
|
|
110
|
+
const response = await fetch(resolvedPreSignedURL, {
|
|
115
111
|
method: "PUT",
|
|
116
|
-
headers: {
|
|
117
|
-
"Content-Type": contentType
|
|
118
|
-
},
|
|
112
|
+
headers: { "Content-Type": resolvedContentType },
|
|
119
113
|
body: image
|
|
120
114
|
});
|
|
121
115
|
if (!response.ok) {
|
|
@@ -125,9 +119,12 @@ var HCSafeCDXClient = class {
|
|
|
125
119
|
} catch {
|
|
126
120
|
body = void 0;
|
|
127
121
|
}
|
|
128
|
-
throw new
|
|
129
|
-
|
|
130
|
-
|
|
122
|
+
throw new APIError({
|
|
123
|
+
message: `uploadImage: image upload failed with HTTP ${response.status}.`,
|
|
124
|
+
code: response.status >= 500 ? "SERVER_ERROR" : "UNKNOWN_ERROR",
|
|
125
|
+
statusCode: response.status,
|
|
126
|
+
backendMessage: body,
|
|
127
|
+
details: { status: response.status, body }
|
|
131
128
|
});
|
|
132
129
|
}
|
|
133
130
|
}
|
|
@@ -136,138 +133,188 @@ var HCSafeCDXClient = class {
|
|
|
136
133
|
// -------------------------------------------------------------------------
|
|
137
134
|
/**
|
|
138
135
|
* POST cvml/status
|
|
139
|
-
*
|
|
136
|
+
* Updates the CVML processing status for an image capture.
|
|
140
137
|
*/
|
|
141
138
|
async updateCvmlStatus(imageOfCaptureId, cvmlStatus) {
|
|
139
|
+
const resolvedImageOfCaptureId = this.requireValue(imageOfCaptureId, "Image capture ID");
|
|
140
|
+
const resolvedCvmlStatus = this.requireValue(cvmlStatus, "CVML status");
|
|
142
141
|
const request = {
|
|
143
142
|
Data: {
|
|
144
|
-
ImageOfCaptureId:
|
|
145
|
-
CvmlStatus:
|
|
143
|
+
ImageOfCaptureId: resolvedImageOfCaptureId,
|
|
144
|
+
CvmlStatus: resolvedCvmlStatus
|
|
146
145
|
}
|
|
147
146
|
};
|
|
148
|
-
return this.
|
|
147
|
+
return this.executeSafe(
|
|
148
|
+
"updateCvmlStatus",
|
|
149
|
+
() => this.http.post(this.url("cvml/status"), request, this.getAuthHeaders())
|
|
150
|
+
);
|
|
149
151
|
}
|
|
150
152
|
/**
|
|
151
153
|
* GET cvml/results
|
|
152
|
-
* Returns the
|
|
154
|
+
* Returns the CVML analysis results for an image capture.
|
|
153
155
|
*/
|
|
154
156
|
async getCvmlResults(imageOfCaptureId) {
|
|
155
|
-
|
|
157
|
+
const resolvedImageOfCaptureId = this.requireValue(imageOfCaptureId, "Image capture ID");
|
|
158
|
+
return this.executeSafe(
|
|
159
|
+
"getCvmlResults",
|
|
160
|
+
() => this.http.get(
|
|
161
|
+
this.url("cvml/results", { imageOfCaptureId: resolvedImageOfCaptureId }),
|
|
162
|
+
this.getAuthHeaders()
|
|
163
|
+
)
|
|
164
|
+
);
|
|
156
165
|
}
|
|
157
166
|
// -------------------------------------------------------------------------
|
|
158
167
|
// Test Results
|
|
159
168
|
// -------------------------------------------------------------------------
|
|
160
|
-
/** POST test/result/pending */
|
|
161
|
-
async
|
|
169
|
+
/** POST test/result/pending — returns pending test results excluding the given statuses. */
|
|
170
|
+
async listPendingResults(excludeStatus = "Invalid,Canceled") {
|
|
162
171
|
const request = {
|
|
163
|
-
Data: {
|
|
164
|
-
ExcludeStatus: excludeStatus
|
|
165
|
-
}
|
|
172
|
+
Data: { ExcludeStatus: excludeStatus }
|
|
166
173
|
};
|
|
167
|
-
return this.
|
|
174
|
+
return this.executeSafe(
|
|
175
|
+
"listPendingResults",
|
|
176
|
+
() => this.http.post(this.url("test/result/pending"), request, this.getAuthHeaders())
|
|
177
|
+
);
|
|
168
178
|
}
|
|
169
|
-
/** POST test/result/last */
|
|
179
|
+
/** POST test/result/last — returns the most recent test result. */
|
|
170
180
|
async getLastResults(excludeStatus = "Invalid") {
|
|
171
181
|
const request = {
|
|
172
|
-
Data: {
|
|
173
|
-
ExcludeStatus: excludeStatus
|
|
174
|
-
}
|
|
182
|
+
Data: { ExcludeStatus: excludeStatus }
|
|
175
183
|
};
|
|
176
|
-
return this.
|
|
184
|
+
return this.executeSafe(
|
|
185
|
+
"getLastResults",
|
|
186
|
+
() => this.http.post(this.url("test/result/last"), request, this.getAuthHeaders())
|
|
187
|
+
);
|
|
177
188
|
}
|
|
178
|
-
/** POST test/result/history */
|
|
179
|
-
async
|
|
189
|
+
/** POST test/result/history — returns all test results excluding the given statuses. */
|
|
190
|
+
async listTestHistory(excludeStatus = "Invalid") {
|
|
180
191
|
const request = {
|
|
181
|
-
Data: {
|
|
182
|
-
ExcludeStatus: excludeStatus
|
|
183
|
-
}
|
|
192
|
+
Data: { ExcludeStatus: excludeStatus }
|
|
184
193
|
};
|
|
185
|
-
return this.
|
|
194
|
+
return this.executeSafe(
|
|
195
|
+
"listTestHistory",
|
|
196
|
+
() => this.http.post(this.url("test/result/history"), request, this.getAuthHeaders())
|
|
197
|
+
);
|
|
186
198
|
}
|
|
187
199
|
/**
|
|
188
200
|
* POST test/result/details
|
|
189
|
-
* Returns
|
|
201
|
+
* Returns full details for a single test result.
|
|
190
202
|
*/
|
|
191
203
|
async getResultDetails(userTestResultId) {
|
|
204
|
+
const resolvedUserTestResultId = this.requireValue(userTestResultId, "User test result ID");
|
|
192
205
|
const request = {
|
|
193
|
-
Data: {
|
|
194
|
-
UserTestResultId: userTestResultId
|
|
195
|
-
}
|
|
206
|
+
Data: { UserTestResultId: resolvedUserTestResultId }
|
|
196
207
|
};
|
|
197
|
-
return this.
|
|
208
|
+
return this.executeSafe(
|
|
209
|
+
"getResultDetails",
|
|
210
|
+
() => this.http.post(this.url("test/result/details"), request, this.getAuthHeaders())
|
|
211
|
+
);
|
|
198
212
|
}
|
|
199
|
-
/** POST test/result/pdf */
|
|
213
|
+
/** POST test/result/pdf — returns the PDF report for a test result. */
|
|
200
214
|
async getResultPdf(userTestResultId) {
|
|
215
|
+
const resolvedUserTestResultId = this.requireValue(userTestResultId, "User test result ID");
|
|
201
216
|
const request = {
|
|
202
|
-
Data: {
|
|
203
|
-
UserTestResultId: userTestResultId
|
|
204
|
-
}
|
|
217
|
+
Data: { UserTestResultId: resolvedUserTestResultId }
|
|
205
218
|
};
|
|
206
|
-
return this.
|
|
219
|
+
return this.executeSafe(
|
|
220
|
+
"getResultPdf",
|
|
221
|
+
() => this.http.post(this.url("test/result/pdf"), request, this.getAuthHeaders())
|
|
222
|
+
);
|
|
207
223
|
}
|
|
208
224
|
/**
|
|
209
225
|
* POST test/result/image/capture
|
|
210
|
-
* Returns
|
|
226
|
+
* Returns a URL to capture an image for the given test result.
|
|
211
227
|
*/
|
|
212
228
|
async getImageCaptureUrl(userTestResultId) {
|
|
229
|
+
const resolvedUserTestResultId = this.requireValue(userTestResultId, "User test result ID");
|
|
213
230
|
const request = {
|
|
214
|
-
Data: {
|
|
215
|
-
UserTestResultId: userTestResultId
|
|
216
|
-
}
|
|
231
|
+
Data: { UserTestResultId: resolvedUserTestResultId }
|
|
217
232
|
};
|
|
218
|
-
return this.
|
|
233
|
+
return this.executeSafe(
|
|
234
|
+
"getImageCaptureUrl",
|
|
235
|
+
() => this.http.post(this.url("test/result/image/capture"), request, this.getAuthHeaders())
|
|
236
|
+
);
|
|
219
237
|
}
|
|
220
238
|
// -------------------------------------------------------------------------
|
|
221
239
|
// Resume / Answers / Finalize
|
|
222
240
|
// -------------------------------------------------------------------------
|
|
223
241
|
/** POST test/resume */
|
|
224
242
|
async resumeFlow(userTestResultId, resumed = true) {
|
|
243
|
+
const resolvedUserTestResultId = this.requireValue(userTestResultId, "User test result ID");
|
|
225
244
|
const request = {
|
|
226
|
-
Data: {
|
|
227
|
-
UserTestResultId: userTestResultId,
|
|
228
|
-
Resumed: resumed
|
|
229
|
-
}
|
|
245
|
+
Data: { UserTestResultId: resolvedUserTestResultId, Resumed: resumed }
|
|
230
246
|
};
|
|
231
|
-
return this.
|
|
247
|
+
return this.executeSafe(
|
|
248
|
+
"resumeFlow",
|
|
249
|
+
() => this.http.post(this.url("test/resume"), request, this.getAuthHeaders())
|
|
250
|
+
);
|
|
232
251
|
}
|
|
233
252
|
/** POST test/answers */
|
|
234
253
|
async submitAnswers(submission) {
|
|
254
|
+
const resolvedId = this.requireValue(submission == null ? void 0 : submission.UserTestResultId, "User test result ID");
|
|
255
|
+
if (!(submission == null ? void 0 : submission.Result) || submission.Result.length === 0) {
|
|
256
|
+
throw new ValidationError({
|
|
257
|
+
message: "At least one answer result is required.",
|
|
258
|
+
code: "INVALID_INPUT",
|
|
259
|
+
param: "Result"
|
|
260
|
+
});
|
|
261
|
+
}
|
|
235
262
|
const request = {
|
|
236
|
-
Data: submission
|
|
263
|
+
Data: { ...submission, UserTestResultId: resolvedId }
|
|
237
264
|
};
|
|
238
|
-
return this.
|
|
265
|
+
return this.executeSafe(
|
|
266
|
+
"submitAnswers",
|
|
267
|
+
() => this.http.post(this.url("test/answers"), request, this.getAuthHeaders())
|
|
268
|
+
);
|
|
239
269
|
}
|
|
240
270
|
/** POST test/finalize */
|
|
241
271
|
async finalizeTest(userTestResultId) {
|
|
272
|
+
const resolvedUserTestResultId = this.requireValue(userTestResultId, "User test result ID");
|
|
242
273
|
const request = {
|
|
243
|
-
Data: {
|
|
244
|
-
UserTestResultId: userTestResultId
|
|
245
|
-
}
|
|
274
|
+
Data: { UserTestResultId: resolvedUserTestResultId }
|
|
246
275
|
};
|
|
247
|
-
return this.
|
|
276
|
+
return this.execute(
|
|
277
|
+
"finalizeTest",
|
|
278
|
+
() => this.http.post(this.url("test/finalize"), request, this.getAuthHeaders())
|
|
279
|
+
);
|
|
248
280
|
}
|
|
249
281
|
// -------------------------------------------------------------------------
|
|
250
282
|
// Private Helpers
|
|
251
283
|
// -------------------------------------------------------------------------
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
284
|
+
async executeSafe(operation, request) {
|
|
285
|
+
var _a;
|
|
286
|
+
let response;
|
|
287
|
+
try {
|
|
288
|
+
response = await request();
|
|
289
|
+
} catch (err) {
|
|
290
|
+
if (err instanceof APIError) throw err;
|
|
291
|
+
if (err instanceof Error) {
|
|
292
|
+
throw new APIError({ message: `${operation}: ${err.message}`, code: "UNKNOWN_ERROR", details: err });
|
|
293
|
+
}
|
|
294
|
+
throw new APIError({ message: `${operation}: unexpected runtime failure`, code: "UNKNOWN_ERROR", details: err });
|
|
295
|
+
}
|
|
296
|
+
if (response == null) {
|
|
297
|
+
throw new APIError({ message: `${operation}: empty response received`, code: "EMPTY_RESPONSE", details: response });
|
|
298
|
+
}
|
|
299
|
+
if (!this.isSafeApiResponse(response)) {
|
|
300
|
+
throw new APIError({ message: `${operation}: invalid SafeCDX response structure`, code: "INVALID_RESPONSE", details: response });
|
|
301
|
+
}
|
|
302
|
+
if (!response.success) {
|
|
303
|
+
throw new HCServiceError(
|
|
304
|
+
operation,
|
|
305
|
+
(_a = response.message) != null ? _a : "Backend returned success: false",
|
|
306
|
+
response
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
return response;
|
|
257
310
|
}
|
|
258
|
-
|
|
259
|
-
return
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
};
|
|
311
|
+
isSafeApiResponse(value) {
|
|
312
|
+
if (!value || typeof value !== "object") return false;
|
|
313
|
+
const r = value;
|
|
314
|
+
return "success" in r && typeof r.success === "boolean" && "data" in r && "message" in r && "code" in r && typeof r.code === "number";
|
|
263
315
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
return {};
|
|
267
|
-
}
|
|
268
|
-
return {
|
|
269
|
-
[this.apiKeyHeaderName]: this.apiKeyValue
|
|
270
|
-
};
|
|
316
|
+
getAuthHeaders() {
|
|
317
|
+
return { ...this.getHeaders(), ...this.auth.getAuthHeader() };
|
|
271
318
|
}
|
|
272
319
|
url(route, query) {
|
|
273
320
|
return buildUrl(this.baseUrl, route, query);
|
|
@@ -275,13 +322,18 @@ var HCSafeCDXClient = class {
|
|
|
275
322
|
};
|
|
276
323
|
|
|
277
324
|
// src/errors.ts
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
325
|
+
import {
|
|
326
|
+
APIError as APIError2,
|
|
327
|
+
ConfigError as ConfigError2,
|
|
328
|
+
HCServiceError as HCServiceError2,
|
|
329
|
+
NetworkError,
|
|
330
|
+
ValidationError as ValidationError2
|
|
331
|
+
} from "@healthcloudai/hc-http";
|
|
284
332
|
export {
|
|
285
|
-
|
|
286
|
-
|
|
333
|
+
APIError2 as APIError,
|
|
334
|
+
ConfigError2 as ConfigError,
|
|
335
|
+
HCSafeCDXClient,
|
|
336
|
+
HCServiceError2 as HCServiceError,
|
|
337
|
+
NetworkError,
|
|
338
|
+
ValidationError2 as ValidationError
|
|
287
339
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@healthcloudai/hc-safe-cdx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Healthcheck Safe CDX connector.",
|
|
5
5
|
"author": "Healthcheck Systems Inc",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"prepublishOnly": "npm run build"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@healthcloudai/hc-http": "^0.0
|
|
37
|
-
"@healthcloudai/hc-login-connector": "^0.
|
|
36
|
+
"@healthcloudai/hc-http": "^0.2.0",
|
|
37
|
+
"@healthcloudai/hc-login-connector": "^0.3.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"react-native": ">=0.70.0"
|