@healthcloudai/hc-safe-cdx 0.2.0 → 0.2.2
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 +695 -409
- package/dist/index.cjs +127 -202
- package/dist/index.d.cts +385 -165
- package/dist/index.d.ts +385 -165
- package/dist/index.js +127 -202
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -32,10 +32,10 @@ function buildUrl(baseUrl, route, query) {
|
|
|
32
32
|
return url.toString();
|
|
33
33
|
}
|
|
34
34
|
var HCSafeCDXClient = class {
|
|
35
|
-
constructor(httpClient,
|
|
35
|
+
constructor(httpClient, loginClient) {
|
|
36
36
|
this.http = httpClient;
|
|
37
|
-
this.
|
|
38
|
-
this.baseUrl = buildSafeCdxBaseUrl(
|
|
37
|
+
this.loginClient = loginClient;
|
|
38
|
+
this.baseUrl = buildSafeCdxBaseUrl(loginClient.getEnvironment());
|
|
39
39
|
}
|
|
40
40
|
setApiKey(headerName, value) {
|
|
41
41
|
const trimmedHeaderName = headerName == null ? void 0 : headerName.trim();
|
|
@@ -49,38 +49,12 @@ var HCSafeCDXClient = class {
|
|
|
49
49
|
this.apiKeyHeaderName = trimmedHeaderName;
|
|
50
50
|
this.apiKeyValue = trimmedValue;
|
|
51
51
|
}
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
getAuthHeaders() {
|
|
56
|
-
return {
|
|
57
|
-
...this.auth.getAuthHeader(),
|
|
58
|
-
...this.getApiKeyHeader()
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
getJsonHeaders() {
|
|
62
|
-
return {
|
|
63
|
-
...this.getAuthHeaders(),
|
|
64
|
-
"Content-Type": "application/json"
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
getApiKeyHeader() {
|
|
68
|
-
if (!this.apiKeyHeaderName || !this.apiKeyValue) {
|
|
69
|
-
return {};
|
|
70
|
-
}
|
|
71
|
-
return {
|
|
72
|
-
[this.apiKeyHeaderName]: this.apiKeyValue
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
url(route, query) {
|
|
76
|
-
return buildUrl(this.baseUrl, route, query);
|
|
77
|
-
}
|
|
78
|
-
// ---------------------------------------------------------------------------
|
|
79
|
-
// Scan
|
|
80
|
-
// ---------------------------------------------------------------------------
|
|
52
|
+
// -------------------------------------------------------------------------
|
|
53
|
+
// Test Profiles
|
|
54
|
+
// -------------------------------------------------------------------------
|
|
81
55
|
/**
|
|
82
56
|
* GET gs1/:gtin
|
|
83
|
-
* Resolves
|
|
57
|
+
* Resolves the SafeCDX test profile associated with a GTIN barcode.
|
|
84
58
|
*/
|
|
85
59
|
async getTestProfileByGTIN(gtin) {
|
|
86
60
|
return this.http.get(
|
|
@@ -88,18 +62,17 @@ var HCSafeCDXClient = class {
|
|
|
88
62
|
this.getAuthHeaders()
|
|
89
63
|
);
|
|
90
64
|
}
|
|
91
|
-
// ---------------------------------------------------------------------------
|
|
92
|
-
// Test Profiles
|
|
93
|
-
// ---------------------------------------------------------------------------
|
|
94
65
|
/**
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
66
|
+
* POST test/profiles/by-account
|
|
67
|
+
|
|
68
|
+
*
|
|
69
|
+
* TenantId is resolved by the backend from the authenticated patient context.
|
|
70
|
+
*/
|
|
71
|
+
async getTestProfilesByAccount(includeRegisterTestDetails = true) {
|
|
101
72
|
const request = {
|
|
102
|
-
Data:
|
|
73
|
+
Data: {
|
|
74
|
+
IncludeRegisterTestDetails: includeRegisterTestDetails
|
|
75
|
+
}
|
|
103
76
|
};
|
|
104
77
|
return this.http.post(
|
|
105
78
|
this.url("test/profiles/by-account"),
|
|
@@ -107,24 +80,22 @@ var HCSafeCDXClient = class {
|
|
|
107
80
|
this.getJsonHeaders()
|
|
108
81
|
);
|
|
109
82
|
}
|
|
110
|
-
//
|
|
111
|
-
// Upload
|
|
112
|
-
//
|
|
83
|
+
// -------------------------------------------------------------------------
|
|
84
|
+
// Image Upload
|
|
85
|
+
// -------------------------------------------------------------------------
|
|
113
86
|
/**
|
|
114
87
|
* POST upload/url
|
|
115
|
-
* Requests a pre-signed
|
|
116
|
-
* Use the returned Data.preSignedURL and Data.Metadata.UploadId in the next steps.
|
|
88
|
+
* Requests a pre-signed URL used to upload a test image.
|
|
117
89
|
*/
|
|
118
|
-
async createUploadUrl(userTestResultId, gtin, imageType) {
|
|
119
|
-
const payload = {
|
|
120
|
-
Gtin: gtin,
|
|
121
|
-
UserTestResultId: userTestResultId,
|
|
122
|
-
Metadata: {
|
|
123
|
-
ImageType: imageType != null ? imageType : "jpg"
|
|
124
|
-
}
|
|
125
|
-
};
|
|
90
|
+
async createUploadUrl(userTestResultId, gtin, imageType = "jpg") {
|
|
126
91
|
const request = {
|
|
127
|
-
Data:
|
|
92
|
+
Data: {
|
|
93
|
+
Gtin: gtin,
|
|
94
|
+
UserTestResultId: userTestResultId,
|
|
95
|
+
Metadata: {
|
|
96
|
+
ImageType: imageType
|
|
97
|
+
}
|
|
98
|
+
}
|
|
128
99
|
};
|
|
129
100
|
return this.http.post(
|
|
130
101
|
this.url("upload/url"),
|
|
@@ -133,11 +104,11 @@ var HCSafeCDXClient = class {
|
|
|
133
104
|
);
|
|
134
105
|
}
|
|
135
106
|
/**
|
|
136
|
-
* PUT preSignedURL
|
|
137
|
-
*
|
|
107
|
+
* PUT preSignedURL
|
|
108
|
+
* Uploads the image directly to the pre-signed storage URL.
|
|
138
109
|
*
|
|
139
|
-
* This
|
|
140
|
-
*
|
|
110
|
+
* This request does not call a SafeCDX API route and does not send
|
|
111
|
+
* authenticated Health Cloud headers.
|
|
141
112
|
*/
|
|
142
113
|
async uploadImage(preSignedURL, image, contentType = "image/jpeg") {
|
|
143
114
|
const response = await fetch(preSignedURL, {
|
|
@@ -152,200 +123,154 @@ var HCSafeCDXClient = class {
|
|
|
152
123
|
try {
|
|
153
124
|
body = (await response.text()).slice(0, 500);
|
|
154
125
|
} catch {
|
|
126
|
+
body = void 0;
|
|
155
127
|
}
|
|
156
|
-
throw new SafeCDXError(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
body
|
|
161
|
-
}
|
|
162
|
-
);
|
|
128
|
+
throw new SafeCDXError(`Image upload failed with HTTP ${response.status}.`, {
|
|
129
|
+
status: response.status,
|
|
130
|
+
body
|
|
131
|
+
});
|
|
163
132
|
}
|
|
164
133
|
}
|
|
165
|
-
//
|
|
134
|
+
// -------------------------------------------------------------------------
|
|
166
135
|
// CVML
|
|
167
|
-
//
|
|
136
|
+
// -------------------------------------------------------------------------
|
|
168
137
|
/**
|
|
169
138
|
* POST cvml/status
|
|
170
|
-
*
|
|
171
|
-
* NOTE: Returns raw service result — no ApiResponse wrapper on this endpoint.
|
|
139
|
+
* Returns the direct SafeCDX response without an outer APIResponse wrapper.
|
|
172
140
|
*/
|
|
173
141
|
async updateCvmlStatus(imageOfCaptureId, cvmlStatus) {
|
|
174
|
-
const payload = {
|
|
175
|
-
ImageOfCaptureId: imageOfCaptureId,
|
|
176
|
-
CvmlStatus: cvmlStatus
|
|
177
|
-
};
|
|
178
142
|
const request = {
|
|
179
|
-
Data:
|
|
143
|
+
Data: {
|
|
144
|
+
ImageOfCaptureId: imageOfCaptureId,
|
|
145
|
+
CvmlStatus: cvmlStatus
|
|
146
|
+
}
|
|
180
147
|
};
|
|
181
|
-
return this.http.post(
|
|
182
|
-
this.url("cvml/status"),
|
|
183
|
-
request,
|
|
184
|
-
this.getJsonHeaders()
|
|
185
|
-
);
|
|
148
|
+
return this.http.post(this.url("cvml/status"), request, this.getJsonHeaders());
|
|
186
149
|
}
|
|
187
150
|
/**
|
|
188
151
|
* GET cvml/results
|
|
189
|
-
*
|
|
190
|
-
* NOTE: Returns raw service result — no ApiResponse wrapper on this endpoint.
|
|
152
|
+
* Returns the direct SafeCDX response without an outer APIResponse wrapper.
|
|
191
153
|
*/
|
|
192
154
|
async getCvmlResults(imageOfCaptureId) {
|
|
193
|
-
return this.http.get(
|
|
194
|
-
this.url("cvml/results", {
|
|
195
|
-
imageOfCaptureId
|
|
196
|
-
}),
|
|
197
|
-
this.getAuthHeaders()
|
|
198
|
-
);
|
|
155
|
+
return this.http.get(this.url("cvml/results", { imageOfCaptureId }), this.getAuthHeaders());
|
|
199
156
|
}
|
|
200
|
-
//
|
|
157
|
+
// -------------------------------------------------------------------------
|
|
201
158
|
// Test Results
|
|
202
|
-
//
|
|
203
|
-
/**
|
|
204
|
-
|
|
205
|
-
* Returns test results in a pending/incomplete state.
|
|
206
|
-
*/
|
|
207
|
-
async getPendingResults(payload = {
|
|
208
|
-
ExcludeStatus: "Invalid,Canceled"
|
|
209
|
-
}) {
|
|
159
|
+
// -------------------------------------------------------------------------
|
|
160
|
+
/** POST test/result/pending */
|
|
161
|
+
async getPendingResults(excludeStatus = "Invalid,Canceled") {
|
|
210
162
|
const request = {
|
|
211
|
-
Data:
|
|
163
|
+
Data: {
|
|
164
|
+
ExcludeStatus: excludeStatus
|
|
165
|
+
}
|
|
212
166
|
};
|
|
213
|
-
return this.http.post(
|
|
214
|
-
this.url("test/result/pending"),
|
|
215
|
-
request,
|
|
216
|
-
this.getJsonHeaders()
|
|
217
|
-
);
|
|
167
|
+
return this.http.post(this.url("test/result/pending"), request, this.getJsonHeaders());
|
|
218
168
|
}
|
|
219
|
-
/**
|
|
220
|
-
|
|
221
|
-
* Returns the most recent test result for the authenticated patient.
|
|
222
|
-
*/
|
|
223
|
-
async getLastResults(payload = {
|
|
224
|
-
ExcludeStatus: "Invalid"
|
|
225
|
-
}) {
|
|
169
|
+
/** POST test/result/last */
|
|
170
|
+
async getLastResults(excludeStatus = "Invalid") {
|
|
226
171
|
const request = {
|
|
227
|
-
Data:
|
|
172
|
+
Data: {
|
|
173
|
+
ExcludeStatus: excludeStatus
|
|
174
|
+
}
|
|
228
175
|
};
|
|
229
|
-
return this.http.post(
|
|
230
|
-
this.url("test/result/last"),
|
|
231
|
-
request,
|
|
232
|
-
this.getJsonHeaders()
|
|
233
|
-
);
|
|
176
|
+
return this.http.post(this.url("test/result/last"), request, this.getJsonHeaders());
|
|
234
177
|
}
|
|
235
|
-
/**
|
|
236
|
-
|
|
237
|
-
* Returns the full test history for the authenticated patient.
|
|
238
|
-
*/
|
|
239
|
-
async getTestHistory(payload = {
|
|
240
|
-
ExcludeStatus: "Invalid"
|
|
241
|
-
}) {
|
|
178
|
+
/** POST test/result/history */
|
|
179
|
+
async getTestHistory(excludeStatus = "Invalid") {
|
|
242
180
|
const request = {
|
|
243
|
-
Data:
|
|
181
|
+
Data: {
|
|
182
|
+
ExcludeStatus: excludeStatus
|
|
183
|
+
}
|
|
244
184
|
};
|
|
245
|
-
return this.http.post(
|
|
246
|
-
this.url("test/result/history"),
|
|
247
|
-
request,
|
|
248
|
-
this.getJsonHeaders()
|
|
249
|
-
);
|
|
185
|
+
return this.http.post(this.url("test/result/history"), request, this.getJsonHeaders());
|
|
250
186
|
}
|
|
251
187
|
/**
|
|
252
188
|
* POST test/result/details
|
|
253
|
-
* Returns
|
|
254
|
-
* NOTE: Returns raw service result — no ApiResponse wrapper on this endpoint.
|
|
189
|
+
* Returns the direct SafeCDX response without an outer APIResponse wrapper.
|
|
255
190
|
*/
|
|
256
191
|
async getResultDetails(userTestResultId) {
|
|
257
|
-
const payload = {
|
|
258
|
-
UserTestResultId: userTestResultId
|
|
259
|
-
};
|
|
260
192
|
const request = {
|
|
261
|
-
Data:
|
|
193
|
+
Data: {
|
|
194
|
+
UserTestResultId: userTestResultId
|
|
195
|
+
}
|
|
262
196
|
};
|
|
263
|
-
return this.http.post(
|
|
264
|
-
this.url("test/result/details"),
|
|
265
|
-
request,
|
|
266
|
-
this.getJsonHeaders()
|
|
267
|
-
);
|
|
197
|
+
return this.http.post(this.url("test/result/details"), request, this.getJsonHeaders());
|
|
268
198
|
}
|
|
269
|
-
/**
|
|
270
|
-
|
|
271
|
-
* Requests the PDF result for a specific test result.
|
|
272
|
-
*/
|
|
273
|
-
async getResultPdf(payload) {
|
|
199
|
+
/** POST test/result/pdf */
|
|
200
|
+
async getResultPdf(userTestResultId) {
|
|
274
201
|
const request = {
|
|
275
|
-
Data:
|
|
202
|
+
Data: {
|
|
203
|
+
UserTestResultId: userTestResultId
|
|
204
|
+
}
|
|
276
205
|
};
|
|
277
|
-
return this.http.post(
|
|
278
|
-
this.url("test/result/pdf"),
|
|
279
|
-
request,
|
|
280
|
-
this.getJsonHeaders()
|
|
281
|
-
);
|
|
206
|
+
return this.http.post(this.url("test/result/pdf"), request, this.getJsonHeaders());
|
|
282
207
|
}
|
|
283
208
|
/**
|
|
284
209
|
* POST test/result/image/capture
|
|
285
|
-
*
|
|
286
|
-
* NOTE: Returns raw service result — no ApiResponse wrapper on this endpoint.
|
|
210
|
+
* Returns the direct SafeCDX response without an outer APIResponse wrapper.
|
|
287
211
|
*/
|
|
288
212
|
async getImageCaptureUrl(userTestResultId) {
|
|
289
|
-
const payload = {
|
|
290
|
-
UserTestResultId: userTestResultId
|
|
291
|
-
};
|
|
292
213
|
const request = {
|
|
293
|
-
Data:
|
|
214
|
+
Data: {
|
|
215
|
+
UserTestResultId: userTestResultId
|
|
216
|
+
}
|
|
294
217
|
};
|
|
295
|
-
return this.http.post(
|
|
296
|
-
this.url("test/result/image/capture"),
|
|
297
|
-
request,
|
|
298
|
-
this.getJsonHeaders()
|
|
299
|
-
);
|
|
218
|
+
return this.http.post(this.url("test/result/image/capture"), request, this.getJsonHeaders());
|
|
300
219
|
}
|
|
301
|
-
//
|
|
220
|
+
// -------------------------------------------------------------------------
|
|
302
221
|
// Resume / Answers / Finalize
|
|
303
|
-
//
|
|
304
|
-
/**
|
|
305
|
-
* POST test/resume
|
|
306
|
-
* Marks a test attempt as resumed (or not).
|
|
307
|
-
*/
|
|
222
|
+
// -------------------------------------------------------------------------
|
|
223
|
+
/** POST test/resume */
|
|
308
224
|
async resumeFlow(userTestResultId, resumed = true) {
|
|
309
|
-
const payload = {
|
|
310
|
-
UserTestResultId: userTestResultId,
|
|
311
|
-
Resumed: resumed
|
|
312
|
-
};
|
|
313
225
|
const request = {
|
|
314
|
-
Data:
|
|
226
|
+
Data: {
|
|
227
|
+
UserTestResultId: userTestResultId,
|
|
228
|
+
Resumed: resumed
|
|
229
|
+
}
|
|
315
230
|
};
|
|
316
|
-
return this.http.post(
|
|
317
|
-
this.url("test/resume"),
|
|
318
|
-
request,
|
|
319
|
-
this.getJsonHeaders()
|
|
320
|
-
);
|
|
231
|
+
return this.http.post(this.url("test/resume"), request, this.getJsonHeaders());
|
|
321
232
|
}
|
|
322
|
-
/**
|
|
323
|
-
|
|
324
|
-
* Submits analyte answers for a test attempt.
|
|
325
|
-
*/
|
|
326
|
-
async submitAnswers(payload) {
|
|
233
|
+
/** POST test/answers */
|
|
234
|
+
async submitAnswers(submission) {
|
|
327
235
|
const request = {
|
|
328
|
-
Data:
|
|
236
|
+
Data: submission
|
|
329
237
|
};
|
|
330
|
-
return this.http.post(
|
|
331
|
-
this.url("test/answers"),
|
|
332
|
-
request,
|
|
333
|
-
this.getJsonHeaders()
|
|
334
|
-
);
|
|
238
|
+
return this.http.post(this.url("test/answers"), request, this.getJsonHeaders());
|
|
335
239
|
}
|
|
336
|
-
/**
|
|
337
|
-
|
|
338
|
-
* Finalizes a test by UserTestResultId.
|
|
339
|
-
*/
|
|
340
|
-
async finalizeTest(payload) {
|
|
240
|
+
/** POST test/finalize */
|
|
241
|
+
async finalizeTest(userTestResultId) {
|
|
341
242
|
const request = {
|
|
342
|
-
Data:
|
|
243
|
+
Data: {
|
|
244
|
+
UserTestResultId: userTestResultId
|
|
245
|
+
}
|
|
343
246
|
};
|
|
344
|
-
return this.http.post(
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
247
|
+
return this.http.post(this.url("test/finalize"), request, this.getJsonHeaders());
|
|
248
|
+
}
|
|
249
|
+
// -------------------------------------------------------------------------
|
|
250
|
+
// Private Helpers
|
|
251
|
+
// -------------------------------------------------------------------------
|
|
252
|
+
getAuthHeaders() {
|
|
253
|
+
return {
|
|
254
|
+
...this.loginClient.getAuthHeader(),
|
|
255
|
+
...this.getApiKeyHeader()
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
getJsonHeaders() {
|
|
259
|
+
return {
|
|
260
|
+
...this.getAuthHeaders(),
|
|
261
|
+
"Content-Type": "application/json"
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
getApiKeyHeader() {
|
|
265
|
+
if (!this.apiKeyHeaderName || !this.apiKeyValue) {
|
|
266
|
+
return {};
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
[this.apiKeyHeaderName]: this.apiKeyValue
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
url(route, query) {
|
|
273
|
+
return buildUrl(this.baseUrl, route, query);
|
|
349
274
|
}
|
|
350
275
|
};
|
|
351
276
|
|