@healthcloudai/hc-safe-cdx 0.0.1 → 0.1.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 +621 -2
- package/dist/index.cjs +394 -0
- package/dist/index.d.cts +375 -1
- package/dist/index.d.ts +375 -1
- package/dist/index.js +384 -0
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -1,3 +1,622 @@
|
|
|
1
|
-
# Healthcheck Safe CDX
|
|
1
|
+
# Healthcheck Safe CDX Connector
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Safe CDX connector provides a thin TypeScript wrapper around Safe CDX API routes.
|
|
4
|
+
|
|
5
|
+
The connector follows the same shared-client pattern used by other Health Cloud connector modules:
|
|
6
|
+
|
|
7
|
+
- `HttpClient` handles HTTP transport.
|
|
8
|
+
- `HCLoginClient` provides the authenticated request headers.
|
|
9
|
+
- `HCSafeCDXClient` builds Safe CDX URLs, wraps request payloads, and exposes one method per Safe CDX route.
|
|
10
|
+
|
|
11
|
+
Safe CDX has its own API host. The connector uses `HCLoginClient` for authentication only; it does not use `loginClient.getBaseUrl()` for Safe CDX routes.
|
|
12
|
+
|
|
13
|
+
Image upload is handled separately because the upload target is a pre-signed S3 URL, not a Safe CDX API route.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npm install @healthcloudai/hc-safe-cdx @healthcloudai/hc-http @healthcloudai/hc-login-connector
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Import
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { FetchClient } from "@healthcloudai/hc-http";
|
|
25
|
+
import { HCLoginClient } from "@healthcloudai/hc-login-connector";
|
|
26
|
+
import { HCSafeCDXClient } from "@healthcloudai/hc-safe-cdx";
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Basic Setup
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
const http = new FetchClient();
|
|
33
|
+
|
|
34
|
+
const loginClient = new HCLoginClient(http);
|
|
35
|
+
|
|
36
|
+
// Configure and authenticate the login client first.
|
|
37
|
+
// Exact login/configuration calls depend on the login connector setup used by the app.
|
|
38
|
+
|
|
39
|
+
const safeCdx = new HCSafeCDXClient(http, loginClient, {
|
|
40
|
+
environment: "dev",
|
|
41
|
+
defaultLanguage: "en",
|
|
42
|
+
defaultImageType: "jpg",
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The connector does not perform login. The consuming application should authenticate through the Health Cloud login connector first. Safe CDX then reuses the authenticated headers from `loginClient.getAuthHeader()`.
|
|
47
|
+
|
|
48
|
+
There is no `setAccessToken()` step in this version of the client.
|
|
49
|
+
|
|
50
|
+
## Dependency Notes
|
|
51
|
+
|
|
52
|
+
Because `HCSafeCDXClient` accepts `HCLoginClient` in the constructor, `@healthcloudai/hc-login-connector` should be included as a package dependency.
|
|
53
|
+
|
|
54
|
+
Example package configuration:
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@healthcloudai/hc-http": "^0.x.x",
|
|
60
|
+
"@healthcloudai/hc-login-connector": "^0.x.x"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
In a workspace setup, use the same dependency versioning strategy already used by the other connector packages.
|
|
66
|
+
|
|
67
|
+
Example:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"@healthcloudai/hc-http": "workspace:*",
|
|
73
|
+
"@healthcloudai/hc-login-connector": "workspace:*"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## How the Client Works
|
|
79
|
+
|
|
80
|
+
The client receives both the HTTP client and the login client:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
const http = new FetchClient();
|
|
84
|
+
const loginClient = new HCLoginClient(http);
|
|
85
|
+
|
|
86
|
+
const safeCdx = new HCSafeCDXClient(http, loginClient, {
|
|
87
|
+
environment: "dev",
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The shared `HttpClient` is responsible for executing HTTP requests.
|
|
92
|
+
|
|
93
|
+
The `HCLoginClient` is responsible for the authenticated request headers.
|
|
94
|
+
|
|
95
|
+
The Safe CDX client is responsible for:
|
|
96
|
+
|
|
97
|
+
- resolving the Safe CDX environment host
|
|
98
|
+
- building Safe CDX URLs
|
|
99
|
+
- adding auth headers from `HCLoginClient`
|
|
100
|
+
- adding optional API key headers when configured
|
|
101
|
+
- wrapping POST request payloads into `{ Data: payload }`
|
|
102
|
+
- validating `ApiResponse` results where the backend returns `{ IsOK, Data, ErrorMessage }`
|
|
103
|
+
- exposing one SDK method per Safe CDX route
|
|
104
|
+
|
|
105
|
+
The Safe CDX client does not create its own internal `fetch` helpers for standard Safe CDX API routes.
|
|
106
|
+
|
|
107
|
+
## Environment Configuration
|
|
108
|
+
|
|
109
|
+
The connector supports the following environments:
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
const safeCdx = new HCSafeCDXClient(http, loginClient, {
|
|
113
|
+
environment: "dev",
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Available environments:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
"dev" | "uat" | "prod"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Safe CDX environment host mapping is handled internally by the connector:
|
|
124
|
+
|
|
125
|
+
```txt
|
|
126
|
+
dev -> dev-api-hcs.healthcloud-services.com
|
|
127
|
+
uat -> uat-api-hcs.healthcloud-services.com
|
|
128
|
+
prod -> api-hcs.healthcloud-services.com
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
These hosts are separate from the login connector base URL.
|
|
132
|
+
|
|
133
|
+
## Authentication
|
|
134
|
+
|
|
135
|
+
Safe CDX API calls require authenticated Health Cloud headers.
|
|
136
|
+
|
|
137
|
+
The connector gets those headers from:
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
loginClient.getAuthHeader()
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
This means the login connector must be configured and authenticated before Safe CDX methods are called.
|
|
144
|
+
|
|
145
|
+
Example flow:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
const http = new FetchClient();
|
|
149
|
+
|
|
150
|
+
const loginClient = new HCLoginClient(http);
|
|
151
|
+
|
|
152
|
+
// loginClient.configure(...)
|
|
153
|
+
// await loginClient.loginPatient(...)
|
|
154
|
+
|
|
155
|
+
const safeCdx = new HCSafeCDXClient(http, loginClient, {
|
|
156
|
+
environment: "dev",
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Safe CDX does not manually receive a token. It does not expose `setAccessToken()`. Auth is inherited from the configured login client.
|
|
161
|
+
|
|
162
|
+
## Optional API Key Header
|
|
163
|
+
|
|
164
|
+
If an API key header is required by the environment, it can be set on the Safe CDX client:
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
safeCdx.setApiKey("x-api-key", apiKeyValue);
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
When configured, the API key header is added to Safe CDX API calls together with the login auth headers.
|
|
171
|
+
|
|
172
|
+
## Request Payload Wrapping
|
|
173
|
+
|
|
174
|
+
For POST requests, only the inner payload should be passed to SDK methods.
|
|
175
|
+
|
|
176
|
+
The SDK wraps the payload internally as:
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
{
|
|
180
|
+
Data: payload
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Correct:
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
await safeCdx.submitAnswers({
|
|
188
|
+
UserTestResultId: userTestResultId,
|
|
189
|
+
Result: [
|
|
190
|
+
{
|
|
191
|
+
Analyte: "Purchase",
|
|
192
|
+
ReportedValue: "drug store",
|
|
193
|
+
StoredValue: "drug store",
|
|
194
|
+
Score: "0",
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Incorrect:
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
await safeCdx.submitAnswers({
|
|
204
|
+
Data: {
|
|
205
|
+
UserTestResultId: userTestResultId,
|
|
206
|
+
Result: [],
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The caller should not manually add the `Data` wrapper.
|
|
212
|
+
|
|
213
|
+
## API Response Handling
|
|
214
|
+
|
|
215
|
+
Most Safe CDX endpoints return the standard backend response envelope:
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
{
|
|
219
|
+
Data: T;
|
|
220
|
+
IsOK: boolean;
|
|
221
|
+
ErrorMessage: string | null;
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
For these endpoints, the client validates `IsOK`.
|
|
226
|
+
|
|
227
|
+
If `IsOK` is `false`, the client throws `SafeCDXError`.
|
|
228
|
+
|
|
229
|
+
This validation exists because an HTTP `200` response does not always mean the backend operation succeeded. The HTTP client validates the transport layer, while the Safe CDX client validates the API response envelope.
|
|
230
|
+
|
|
231
|
+
Some endpoints return a raw service result instead of the standard `ApiResponse` envelope. Those methods return the raw result directly.
|
|
232
|
+
|
|
233
|
+
Raw result methods include:
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
updateCvmlStatus(...)
|
|
237
|
+
getCvmlResults(...)
|
|
238
|
+
getResultDetails(...)
|
|
239
|
+
getImageCaptureUrl(...)
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Image Upload Handling
|
|
243
|
+
|
|
244
|
+
Image upload is different from normal Safe CDX API calls.
|
|
245
|
+
|
|
246
|
+
The method `createUploadUrl(...)` returns a pre-signed S3 URL. That URL is then used to upload the image file directly.
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
await safeCdx.uploadImage(preSignedURL, imageBody, "image/jpeg");
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
This upload does not go through the shared `HttpClient`.
|
|
253
|
+
|
|
254
|
+
The reason is that the shared `FetchClient.put()` is JSON-oriented and sends request bodies with `JSON.stringify(...)`. Image upload needs to send a raw `BodyInit`, such as a `Blob`, `File`, `ArrayBuffer`, or stream-compatible body.
|
|
255
|
+
|
|
256
|
+
Authorization headers should not be sent to the pre-signed URL. The pre-signed URL already contains temporary upload authorization.
|
|
257
|
+
|
|
258
|
+
## Typical Safe CDX Flow
|
|
259
|
+
|
|
260
|
+
A typical flow looks like this:
|
|
261
|
+
|
|
262
|
+
```ts
|
|
263
|
+
const http = new FetchClient();
|
|
264
|
+
|
|
265
|
+
const loginClient = new HCLoginClient(http);
|
|
266
|
+
|
|
267
|
+
// Configure and authenticate loginClient first.
|
|
268
|
+
|
|
269
|
+
const safeCdx = new HCSafeCDXClient(http, loginClient, {
|
|
270
|
+
environment: "dev",
|
|
271
|
+
defaultLanguage: "en",
|
|
272
|
+
defaultImageType: "jpg",
|
|
273
|
+
});
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### 1. Get available test profiles
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
const profiles = await safeCdx.getTestProfilesByAccount();
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### 2. Resolve test profile by GTIN
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
const profile = await safeCdx.getTestProfileByGTIN("850024942325");
|
|
286
|
+
|
|
287
|
+
const userTestResultId = profile.Data.ID;
|
|
288
|
+
const gtin = profile.Data.DiagnosticProfile.TestInfo.gtin;
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### 3. Create upload URL
|
|
292
|
+
|
|
293
|
+
```ts
|
|
294
|
+
const upload = await safeCdx.createUploadUrl(userTestResultId, gtin);
|
|
295
|
+
|
|
296
|
+
const preSignedURL = upload.Data.preSignedURL;
|
|
297
|
+
const imageOfCaptureId = upload.Data.Metadata.UploadId;
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### 4. Upload image
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
await safeCdx.uploadImage(preSignedURL, imageBody, "image/jpeg");
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### 5. Update CVML status
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
await safeCdx.updateCvmlStatus(imageOfCaptureId, "ImageProcessing");
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### 6. Poll CVML results
|
|
313
|
+
|
|
314
|
+
```ts
|
|
315
|
+
const cvmlResults = await safeCdx.getCvmlResults(imageOfCaptureId);
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### 7. Submit answers
|
|
319
|
+
|
|
320
|
+
```ts
|
|
321
|
+
await safeCdx.submitAnswers({
|
|
322
|
+
UserTestResultId: userTestResultId,
|
|
323
|
+
Result: [
|
|
324
|
+
{
|
|
325
|
+
Analyte: "Purchase",
|
|
326
|
+
ReportedValue: "drug store",
|
|
327
|
+
StoredValue: "drug store",
|
|
328
|
+
Score: "0",
|
|
329
|
+
},
|
|
330
|
+
],
|
|
331
|
+
});
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### 8. Finalize test
|
|
335
|
+
|
|
336
|
+
```ts
|
|
337
|
+
await safeCdx.finalizeTest({
|
|
338
|
+
UserTestResultId: userTestResultId,
|
|
339
|
+
ctaResult: {
|
|
340
|
+
id: "2",
|
|
341
|
+
title: "Connect with a Telehealth Provider for Next Steps",
|
|
342
|
+
instructions: "Share your test results with a telehealth provider for next steps.",
|
|
343
|
+
urlText: "Connect with Telehealth",
|
|
344
|
+
url: "https://example.com/start",
|
|
345
|
+
},
|
|
346
|
+
indicationResult: {
|
|
347
|
+
id: "4",
|
|
348
|
+
title: "Indication",
|
|
349
|
+
text: "Results suggest follow-up may be needed.",
|
|
350
|
+
recommendTitle: "Recommendation",
|
|
351
|
+
recommendText: "Review the result with a healthcare provider.",
|
|
352
|
+
ctaId: "2",
|
|
353
|
+
},
|
|
354
|
+
decisionResult: {
|
|
355
|
+
calculation: "Total: analyte.responses.score",
|
|
356
|
+
results: [
|
|
357
|
+
{
|
|
358
|
+
indicationId: "4",
|
|
359
|
+
value: "4",
|
|
360
|
+
},
|
|
361
|
+
],
|
|
362
|
+
},
|
|
363
|
+
});
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### 9. Retrieve result data
|
|
367
|
+
|
|
368
|
+
```ts
|
|
369
|
+
const details = await safeCdx.getResultDetails(userTestResultId);
|
|
370
|
+
|
|
371
|
+
const pdf = await safeCdx.getResultPdf({
|
|
372
|
+
UserTestResultId: userTestResultId,
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
const imageCaptureUrl = await safeCdx.getImageCaptureUrl(userTestResultId);
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## State Management
|
|
379
|
+
|
|
380
|
+
The connector does not manage the full Safe CDX flow state.
|
|
381
|
+
|
|
382
|
+
The application should keep track of values returned between steps, such as:
|
|
383
|
+
|
|
384
|
+
```ts
|
|
385
|
+
const state = {
|
|
386
|
+
gtin: undefined,
|
|
387
|
+
userTestResultId: undefined,
|
|
388
|
+
preSignedURL: undefined,
|
|
389
|
+
imageOfCaptureId: undefined,
|
|
390
|
+
};
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
Important values:
|
|
394
|
+
|
|
395
|
+
- `gtin`: product or test kit identifier
|
|
396
|
+
- `userTestResultId`: test result record ID used across the flow
|
|
397
|
+
- `preSignedURL`: temporary URL used for image upload
|
|
398
|
+
- `imageOfCaptureId`: upload identifier returned after creating the upload URL
|
|
399
|
+
|
|
400
|
+
These values should be stored by the consuming app and passed to the next SDK method when needed.
|
|
401
|
+
|
|
402
|
+
## Public Methods
|
|
403
|
+
|
|
404
|
+
### getTestProfileByGTIN
|
|
405
|
+
|
|
406
|
+
```ts
|
|
407
|
+
const profile = await safeCdx.getTestProfileByGTIN(gtin, language);
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
Resolves a test profile by GTIN barcode.
|
|
411
|
+
|
|
412
|
+
`language` is optional. If not provided, the client uses `defaultLanguage` from config when available.
|
|
413
|
+
|
|
414
|
+
### scan2Ddm
|
|
415
|
+
|
|
416
|
+
```ts
|
|
417
|
+
const scan = await safeCdx.scan2Ddm(payload);
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
Scans a 2D data matrix barcode and resolves the related test data.
|
|
421
|
+
|
|
422
|
+
This method requires a real 2D DataMatrix payload. A plain GTIN should not be used as the DataMatrix payload.
|
|
423
|
+
|
|
424
|
+
### getTestProfile
|
|
425
|
+
|
|
426
|
+
```ts
|
|
427
|
+
const profile = await safeCdx.getTestProfile(payload);
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Returns the full test profile for a given payload.
|
|
431
|
+
|
|
432
|
+
### getTestProfilesByAccount
|
|
433
|
+
|
|
434
|
+
```ts
|
|
435
|
+
const profiles = await safeCdx.getTestProfilesByAccount();
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
Lists test profiles available to the authenticated account.
|
|
439
|
+
|
|
440
|
+
A custom payload may also be provided:
|
|
441
|
+
|
|
442
|
+
```ts
|
|
443
|
+
const profiles = await safeCdx.getTestProfilesByAccount({
|
|
444
|
+
IncludeRegisterTestDetails: true,
|
|
445
|
+
});
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### createUploadUrl
|
|
449
|
+
|
|
450
|
+
```ts
|
|
451
|
+
const upload = await safeCdx.createUploadUrl(
|
|
452
|
+
userTestResultId,
|
|
453
|
+
gtin,
|
|
454
|
+
"jpg"
|
|
455
|
+
);
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
Creates a pre-signed image upload URL.
|
|
459
|
+
|
|
460
|
+
`imageType` is optional. If not provided, the client uses `defaultImageType` from config, or `jpg` by default.
|
|
461
|
+
|
|
462
|
+
### uploadImage
|
|
463
|
+
|
|
464
|
+
```ts
|
|
465
|
+
await safeCdx.uploadImage(preSignedURL, imageBody, "image/jpeg");
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Uploads the image directly to the pre-signed URL.
|
|
469
|
+
|
|
470
|
+
This method does not call a Safe CDX API route.
|
|
471
|
+
|
|
472
|
+
### updateCvmlStatus
|
|
473
|
+
|
|
474
|
+
```ts
|
|
475
|
+
const result = await safeCdx.updateCvmlStatus(
|
|
476
|
+
imageOfCaptureId,
|
|
477
|
+
"ImageProcessing"
|
|
478
|
+
);
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
Updates the CVML processing status for a captured image.
|
|
482
|
+
|
|
483
|
+
This method returns a raw service result.
|
|
484
|
+
|
|
485
|
+
### getCvmlResults
|
|
486
|
+
|
|
487
|
+
```ts
|
|
488
|
+
const result = await safeCdx.getCvmlResults(imageOfCaptureId);
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
Polls CVML analysis results for a captured image.
|
|
492
|
+
|
|
493
|
+
This method returns a raw service result.
|
|
494
|
+
|
|
495
|
+
### getPendingResults
|
|
496
|
+
|
|
497
|
+
```ts
|
|
498
|
+
const pending = await safeCdx.getPendingResults();
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Returns pending or incomplete test results.
|
|
502
|
+
|
|
503
|
+
A custom payload may also be provided:
|
|
504
|
+
|
|
505
|
+
```ts
|
|
506
|
+
const pending = await safeCdx.getPendingResults({
|
|
507
|
+
ExcludeStatus: "Started",
|
|
508
|
+
});
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
### getLastResults
|
|
512
|
+
|
|
513
|
+
```ts
|
|
514
|
+
const last = await safeCdx.getLastResults();
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
Returns the most recent test result for the authenticated patient.
|
|
518
|
+
|
|
519
|
+
### getTestHistory
|
|
520
|
+
|
|
521
|
+
```ts
|
|
522
|
+
const history = await safeCdx.getTestHistory();
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
Returns the test history for the authenticated patient.
|
|
526
|
+
|
|
527
|
+
### getResultDetails
|
|
528
|
+
|
|
529
|
+
```ts
|
|
530
|
+
const details = await safeCdx.getResultDetails(userTestResultId);
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
Returns detailed result data for a specific test attempt.
|
|
534
|
+
|
|
535
|
+
This method returns a raw service result.
|
|
536
|
+
|
|
537
|
+
### getResultPdf
|
|
538
|
+
|
|
539
|
+
```ts
|
|
540
|
+
const pdf = await safeCdx.getResultPdf({
|
|
541
|
+
UserTestResultId: userTestResultId,
|
|
542
|
+
});
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
Generates or retrieves the PDF report for a specific test result.
|
|
546
|
+
|
|
547
|
+
### getImageCaptureUrl
|
|
548
|
+
|
|
549
|
+
```ts
|
|
550
|
+
const imageUrl = await safeCdx.getImageCaptureUrl(userTestResultId);
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
Returns the image capture URL for a specific test result.
|
|
554
|
+
|
|
555
|
+
This method returns a raw service result.
|
|
556
|
+
|
|
557
|
+
### getAnalytics
|
|
558
|
+
|
|
559
|
+
```ts
|
|
560
|
+
const analytics = await safeCdx.getAnalytics();
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
Returns analytics data for test results.
|
|
564
|
+
|
|
565
|
+
A custom payload may also be provided:
|
|
566
|
+
|
|
567
|
+
```ts
|
|
568
|
+
const analytics = await safeCdx.getAnalytics(payload);
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### resumeFlow
|
|
572
|
+
|
|
573
|
+
```ts
|
|
574
|
+
const resumed = await safeCdx.resumeFlow(userTestResultId);
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
Marks a test attempt as resumed.
|
|
578
|
+
|
|
579
|
+
The second argument can be used to explicitly set the resumed value:
|
|
580
|
+
|
|
581
|
+
```ts
|
|
582
|
+
const resumed = await safeCdx.resumeFlow(userTestResultId, true);
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
### submitAnswers
|
|
586
|
+
|
|
587
|
+
```ts
|
|
588
|
+
const result = await safeCdx.submitAnswers(payload);
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
Submits analyte answers for a test attempt.
|
|
592
|
+
|
|
593
|
+
`Result` should contain at least one answer item. The connector does not generate analyte answers automatically.
|
|
594
|
+
|
|
595
|
+
### finalizeTest
|
|
596
|
+
|
|
597
|
+
```ts
|
|
598
|
+
const result = await safeCdx.finalizeTest(payload);
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
Finalizes a test attempt with CTA, indication, and decision results.
|
|
602
|
+
|
|
603
|
+
The payload should include:
|
|
604
|
+
|
|
605
|
+
- `UserTestResultId`
|
|
606
|
+
- `ctaResult`
|
|
607
|
+
- `indicationResult`
|
|
608
|
+
- `decisionResult`
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
## Notes
|
|
612
|
+
|
|
613
|
+
- The connector does not perform login.
|
|
614
|
+
- The connector uses `HCLoginClient` for authenticated request headers.
|
|
615
|
+
- The connector does not use `loginClient.getBaseUrl()` for Safe CDX API routes.
|
|
616
|
+
- Safe CDX routes use the Safe CDX environment host from `SafeCDXConfig`.
|
|
617
|
+
- Standard Safe CDX API methods use the shared `HttpClient`.
|
|
618
|
+
- POST payloads are wrapped internally as `{ Data: payload }`.
|
|
619
|
+
- The caller should pass only the inner payload to SDK methods.
|
|
620
|
+
- Image upload uses the pre-signed URL directly and sends the raw file body.
|
|
621
|
+
- Authorization headers should not be sent to the pre-signed upload URL.
|
|
622
|
+
- Pre-signed URLs are time-bound and should not be logged in production.
|