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