@healthcloudai/hc-safe-cdx 0.2.0 → 0.2.1

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 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, authClient) {
62
+ constructor(httpClient, loginClient) {
63
63
  this.http = httpClient;
64
- this.auth = authClient;
65
- this.baseUrl = buildSafeCdxBaseUrl(authClient.getEnvironment());
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
- // Private helpers
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 a test profile by GTIN barcode and creates a UserTestResultId.
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
93
  * POST test/profiles/by-account
123
- * Lists all test profiles available to the authenticated account.
94
+ * Lists test profiles available to the authenticated patient account.
95
+ *
96
+ * TenantId is resolved by the backend from the authenticated patient context.
124
97
  */
125
- async getTestProfilesByAccount(payload = {
126
- IncludeRegisterTestDetails: true
127
- }) {
98
+ async getTestProfilesByAccount(includeRegisterTestDetails = true) {
128
99
  const request = {
129
- Data: payload
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 S3 URL for image upload.
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: payload
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 — direct S3 upload, not a SafeCDX API route.
164
- * preSignedURL comes from createUploadUrl() response: Data.preSignedURL.
134
+ * PUT preSignedURL
135
+ * Uploads the image directly to the pre-signed storage URL.
165
136
  *
166
- * This intentionally does not use the shared HttpClient because the existing
167
- * HttpClient.put() is JSON-oriented and stringifies the request body.
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
- `Image upload failed with HTTP ${response.status}.`,
185
- {
186
- status: response.status,
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
- * Updates the ML processing status for a captured image.
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: payload
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
- * Polls ML analysis results for a captured image.
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
- * POST test/result/pending
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: payload
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
- * POST test/result/last
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: payload
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
- * POST test/result/history
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: payload
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 detailed result data for a specific test attempt.
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: payload
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
- * POST test/result/pdf
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: payload
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
- * Requests image capture data for a specific test result.
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: payload
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: payload
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
- * POST test/answers
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: payload
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
- * POST test/finalize
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: payload
270
+ Data: {
271
+ UserTestResultId: userTestResultId
272
+ }
370
273
  };
371
- return this.http.post(
372
- this.url("test/finalize"),
373
- request,
374
- this.getJsonHeaders()
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