@haau3/sdk 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 +67 -14
- package/dist/index.cjs +681 -58
- package/dist/index.d.cts +429 -153
- package/dist/index.d.mts +429 -153
- package/dist/index.mjs +681 -58
- package/package.json +18 -6
package/dist/index.mjs
CHANGED
|
@@ -36,14 +36,45 @@ var APIPromise = class extends Promise {
|
|
|
36
36
|
};
|
|
37
37
|
//#endregion
|
|
38
38
|
//#region src/errors.ts
|
|
39
|
+
/** The fields {@link Haau3Error.toJSON} copies when they are set, in this order. */
|
|
40
|
+
const LOGGED = [
|
|
41
|
+
"status",
|
|
42
|
+
"reason",
|
|
43
|
+
"retryAfter",
|
|
44
|
+
"attempts",
|
|
45
|
+
"durationMs",
|
|
46
|
+
"requestId",
|
|
47
|
+
"correlationId"
|
|
48
|
+
];
|
|
39
49
|
/** What every error this package throws has. */
|
|
40
50
|
var Haau3Error = class extends Error {
|
|
41
51
|
name = "Haau3Error";
|
|
42
52
|
/** The `X-Request-Id` the API sent, when it answered. Quote it when you ask for help. */
|
|
43
53
|
requestId;
|
|
54
|
+
/** The `correlationId` you sent, as the API returned it in `X-Correlation-Id`, when it answered. */
|
|
55
|
+
correlationId;
|
|
44
56
|
constructor(message, requestId, options) {
|
|
45
|
-
super(message, options);
|
|
57
|
+
super(message, options?.cause === void 0 ? void 0 : { cause: options.cause });
|
|
46
58
|
this.requestId = requestId;
|
|
59
|
+
this.correlationId = options?.correlationId;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The error as a plain object that is safe to log: its name, its message and every field that is
|
|
63
|
+
* set, and never the body the API answered with (`outcome`, `problem`) or the `cause`.
|
|
64
|
+
* `JSON.stringify(error)` and loggers that call `toJSON` print this.
|
|
65
|
+
*
|
|
66
|
+
* ```ts
|
|
67
|
+
* logger.warn({ error: error.toJSON() }, "the plan read failed");
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
toJSON() {
|
|
71
|
+
const json = {
|
|
72
|
+
name: this.name,
|
|
73
|
+
message: this.message
|
|
74
|
+
};
|
|
75
|
+
const fields = this;
|
|
76
|
+
for (const key of LOGGED) if (fields[key] !== void 0) json[key] = fields[key];
|
|
77
|
+
return json;
|
|
47
78
|
}
|
|
48
79
|
};
|
|
49
80
|
/**
|
|
@@ -70,7 +101,7 @@ var AuthError = class extends Haau3Error {
|
|
|
70
101
|
/** Milliseconds from the first attempt to the answer. */
|
|
71
102
|
durationMs;
|
|
72
103
|
constructor(message, status, requestId, body, timing) {
|
|
73
|
-
super(message, requestId);
|
|
104
|
+
super(message, requestId, { correlationId: timing?.correlationId });
|
|
74
105
|
this.status = status;
|
|
75
106
|
this.attempts = timing?.attempts ?? 1;
|
|
76
107
|
this.durationMs = timing?.durationMs;
|
|
@@ -90,7 +121,7 @@ var RefusedError = class extends Haau3Error {
|
|
|
90
121
|
/** Milliseconds from the first attempt to the answer. */
|
|
91
122
|
durationMs;
|
|
92
123
|
constructor(message, status, requestId, body, timing) {
|
|
93
|
-
super(message, requestId);
|
|
124
|
+
super(message, requestId, { correlationId: timing?.correlationId });
|
|
94
125
|
this.status = status;
|
|
95
126
|
this.attempts = timing?.attempts ?? 1;
|
|
96
127
|
this.durationMs = timing?.durationMs;
|
|
@@ -113,7 +144,10 @@ var NoAnswerError = class extends Haau3Error {
|
|
|
113
144
|
/** Milliseconds from the first attempt to the last failure, waits between attempts included. */
|
|
114
145
|
durationMs;
|
|
115
146
|
constructor(message, details) {
|
|
116
|
-
super(message, details.requestId,
|
|
147
|
+
super(message, details.requestId, {
|
|
148
|
+
cause: details.cause,
|
|
149
|
+
correlationId: details.correlationId
|
|
150
|
+
});
|
|
117
151
|
this.reason = details.reason;
|
|
118
152
|
this.status = details.status;
|
|
119
153
|
this.retryAfter = details.retryAfter;
|
|
@@ -125,9 +159,14 @@ var NoAnswerError = class extends Haau3Error {
|
|
|
125
159
|
//#endregion
|
|
126
160
|
//#region src/version.ts
|
|
127
161
|
/** This package's version, sent in the `User-Agent` header. A test holds it to package.json. */
|
|
128
|
-
const VERSION = "0.2.
|
|
162
|
+
const VERSION = "0.2.2";
|
|
129
163
|
//#endregion
|
|
130
164
|
//#region src/transport.ts
|
|
165
|
+
/**
|
|
166
|
+
* The form the API takes for your own request id: a UUID in its usual text form, any version, as the
|
|
167
|
+
* spec's `X-Request-Id` parameter declares (`format: uuid`).
|
|
168
|
+
*/
|
|
169
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
131
170
|
const DEFAULT_BASE_URL = "https://api.haau3.com";
|
|
132
171
|
const DEFAULT_TIMEOUT = 65e3;
|
|
133
172
|
const DEFAULT_MAX_RETRIES = 1;
|
|
@@ -214,6 +253,85 @@ function noAnswerReason(status) {
|
|
|
214
253
|
if (status === 504) return "timeout";
|
|
215
254
|
return "server-error";
|
|
216
255
|
}
|
|
256
|
+
/** Appends a query to a URL's parameters: a list sends the parameter once per value, `undefined` sends none. */
|
|
257
|
+
function appendQuery(params, query) {
|
|
258
|
+
for (const [name, value] of Object.entries(query ?? {})) {
|
|
259
|
+
if (value === void 0) continue;
|
|
260
|
+
for (const item of Array.isArray(value) ? value : [value]) params.append(name, String(item));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* What one answer means: the answer itself, or the error it is. A single call and each entry of a
|
|
265
|
+
* batch are judged alike. `name` says which request it was, in words that carry no value a caller
|
|
266
|
+
* sent: the method and the operation's path with its `{id}` left in.
|
|
267
|
+
*/
|
|
268
|
+
function judge(name, status, body, context) {
|
|
269
|
+
const { requestId, attempts, durationMs, expects } = context;
|
|
270
|
+
const timing = {
|
|
271
|
+
attempts,
|
|
272
|
+
durationMs,
|
|
273
|
+
correlationId: context.correlationId
|
|
274
|
+
};
|
|
275
|
+
if (status >= 200 && status < 300) {
|
|
276
|
+
if (body === void 0) return {
|
|
277
|
+
ok: false,
|
|
278
|
+
error: new NoAnswerError(`${name} answered ${status} with ${context.missing}.`, {
|
|
279
|
+
reason: "unreadable",
|
|
280
|
+
status,
|
|
281
|
+
requestId,
|
|
282
|
+
...timing
|
|
283
|
+
})
|
|
284
|
+
};
|
|
285
|
+
if (expects && !expects.includes(body?.resourceType)) {
|
|
286
|
+
const wanted = expects.map(withArticle).join(" or ");
|
|
287
|
+
return {
|
|
288
|
+
ok: false,
|
|
289
|
+
error: new NoAnswerError(`${name} answered ${describeAnswer(body)} where ${wanted} was expected.`, {
|
|
290
|
+
reason: "unreadable",
|
|
291
|
+
status,
|
|
292
|
+
requestId,
|
|
293
|
+
...timing
|
|
294
|
+
})
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
return {
|
|
298
|
+
ok: true,
|
|
299
|
+
data: body
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
const errorBody = readErrorBody(body);
|
|
303
|
+
if ((status === 401 || status === 403) && !context.entry) return {
|
|
304
|
+
ok: false,
|
|
305
|
+
error: new AuthError(`${name} was refused: the API key was not accepted (${status}).`, status, requestId, errorBody, timing)
|
|
306
|
+
};
|
|
307
|
+
if (status === 429 || status >= 500) {
|
|
308
|
+
const reason = noAnswerReason(status);
|
|
309
|
+
return {
|
|
310
|
+
ok: false,
|
|
311
|
+
error: new NoAnswerError(`${name} got no answer (${reason}, ${status}) after ${attempts} attempt${attempts === 1 ? "" : "s"}.`, {
|
|
312
|
+
reason,
|
|
313
|
+
status,
|
|
314
|
+
retryAfter: context.retryAfter,
|
|
315
|
+
requestId,
|
|
316
|
+
body: errorBody,
|
|
317
|
+
...timing
|
|
318
|
+
})
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
if (status >= 400) return {
|
|
322
|
+
ok: false,
|
|
323
|
+
error: new RefusedError(`${name} was refused (${status}).`, status, requestId, errorBody, timing)
|
|
324
|
+
};
|
|
325
|
+
return {
|
|
326
|
+
ok: false,
|
|
327
|
+
error: new NoAnswerError(`${name} answered ${status}, which is not an answer.`, {
|
|
328
|
+
reason: "unreadable",
|
|
329
|
+
status,
|
|
330
|
+
requestId,
|
|
331
|
+
...timing
|
|
332
|
+
})
|
|
333
|
+
};
|
|
334
|
+
}
|
|
217
335
|
/** The connection, retries and errors every operation shares. */
|
|
218
336
|
var Transport = class {
|
|
219
337
|
#apiKey;
|
|
@@ -252,6 +370,7 @@ var Transport = class {
|
|
|
252
370
|
headers: sent.response.headers,
|
|
253
371
|
body: parseBody(sent.text, sent.response.headers.get("content-type")) ?? sent.text,
|
|
254
372
|
requestId: sent.response.headers.get("x-request-id") ?? void 0,
|
|
373
|
+
correlationId: sent.response.headers.get("x-correlation-id") ?? void 0,
|
|
255
374
|
attempts: sent.attempts,
|
|
256
375
|
durationMs: sent.durationMs
|
|
257
376
|
};
|
|
@@ -284,57 +403,26 @@ var Transport = class {
|
|
|
284
403
|
const { response, text, attempts, durationMs } = await this.#send(method, url, body, options, label);
|
|
285
404
|
const status = response.status;
|
|
286
405
|
const requestId = response.headers.get("x-request-id") ?? void 0;
|
|
287
|
-
const
|
|
288
|
-
const
|
|
289
|
-
const timing = {
|
|
290
|
-
attempts,
|
|
291
|
-
durationMs
|
|
292
|
-
};
|
|
293
|
-
if (status >= 200 && status < 300) {
|
|
294
|
-
if (parsed === void 0) throw new NoAnswerError(`${name} answered ${status} with a body that is not JSON.`, {
|
|
295
|
-
reason: "unreadable",
|
|
296
|
-
status,
|
|
297
|
-
requestId,
|
|
298
|
-
...timing
|
|
299
|
-
});
|
|
300
|
-
if (expects && !expects.includes(parsed?.resourceType)) {
|
|
301
|
-
const wanted = expects.map(withArticle).join(" or ");
|
|
302
|
-
throw new NoAnswerError(`${name} answered ${describeAnswer(parsed)} where ${wanted} was expected.`, {
|
|
303
|
-
reason: "unreadable",
|
|
304
|
-
status,
|
|
305
|
-
requestId,
|
|
306
|
-
...timing
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
return {
|
|
310
|
-
data: parsed,
|
|
311
|
-
requestId,
|
|
312
|
-
durationMs,
|
|
313
|
-
attempts,
|
|
314
|
-
status,
|
|
315
|
-
headers: response.headers
|
|
316
|
-
};
|
|
317
|
-
}
|
|
318
|
-
const errorBody = readErrorBody(parsed);
|
|
319
|
-
if (status === 401 || status === 403) throw new AuthError(`${name} was refused: the API key was not accepted (${status}).`, status, requestId, errorBody, timing);
|
|
320
|
-
if (status === 429 || status >= 500) {
|
|
321
|
-
const reason = noAnswerReason(status);
|
|
322
|
-
throw new NoAnswerError(`${name} got no answer (${reason}, ${status}) after ${attempts} attempt${attempts === 1 ? "" : "s"}.`, {
|
|
323
|
-
reason,
|
|
324
|
-
status,
|
|
325
|
-
retryAfter: retryAfterSeconds(response.headers),
|
|
326
|
-
requestId,
|
|
327
|
-
body: errorBody,
|
|
328
|
-
...timing
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
if (status >= 400) throw new RefusedError(`${name} was refused (${status}).`, status, requestId, errorBody, timing);
|
|
332
|
-
throw new NoAnswerError(`${name} answered ${status}, which is not an answer.`, {
|
|
333
|
-
reason: "unreadable",
|
|
334
|
-
status,
|
|
406
|
+
const correlationId = response.headers.get("x-correlation-id") ?? void 0;
|
|
407
|
+
const verdict = judge(`${method} ${label}`, status, parseBody(text, response.headers.get("content-type")), {
|
|
335
408
|
requestId,
|
|
336
|
-
|
|
409
|
+
correlationId,
|
|
410
|
+
attempts,
|
|
411
|
+
durationMs,
|
|
412
|
+
retryAfter: retryAfterSeconds(response.headers),
|
|
413
|
+
expects,
|
|
414
|
+
missing: "a body that is not JSON"
|
|
337
415
|
});
|
|
416
|
+
if (!verdict.ok) throw verdict.error;
|
|
417
|
+
return {
|
|
418
|
+
data: verdict.data,
|
|
419
|
+
requestId,
|
|
420
|
+
correlationId,
|
|
421
|
+
durationMs,
|
|
422
|
+
attempts,
|
|
423
|
+
status,
|
|
424
|
+
headers: response.headers
|
|
425
|
+
};
|
|
338
426
|
}
|
|
339
427
|
/** A URL on this client's base, refusing any other host so the key is never sent to one. */
|
|
340
428
|
url(pathOrUrl) {
|
|
@@ -344,10 +432,7 @@ var Transport = class {
|
|
|
344
432
|
const base = new URL(this.baseURL);
|
|
345
433
|
const url = /^https?:\/\//i.test(pathOrUrl) ? new URL(pathOrUrl) : new URL(base.pathname.replace(/\/$/, "") + (pathOrUrl.startsWith("/") ? pathOrUrl : `/${pathOrUrl}`), base);
|
|
346
434
|
if (url.origin !== base.origin) throw new Haau3Error(`Refusing to send the API key to ${url.origin}: the client's baseURL is ${base.origin}.`);
|
|
347
|
-
|
|
348
|
-
if (value === void 0) continue;
|
|
349
|
-
for (const item of Array.isArray(value) ? value : [value]) url.searchParams.append(name, String(item));
|
|
350
|
-
}
|
|
435
|
+
appendQuery(url.searchParams, query);
|
|
351
436
|
return url;
|
|
352
437
|
}
|
|
353
438
|
async #send(method, url, body, options, label) {
|
|
@@ -363,6 +448,10 @@ var Transport = class {
|
|
|
363
448
|
headers["content-type"] = fhir ? FHIR_JSON : "application/json";
|
|
364
449
|
}
|
|
365
450
|
for (const [name, value] of Object.entries(options.headers ?? {})) headers[name.toLowerCase()] = value;
|
|
451
|
+
if (options.correlationId !== void 0) {
|
|
452
|
+
if (!UUID.test(options.correlationId)) throw new Haau3Error(`${method} ${label} was not sent: correlationId must be a UUID, which is all the API keeps (it drops anything else).`);
|
|
453
|
+
headers["x-request-id"] = options.correlationId;
|
|
454
|
+
}
|
|
366
455
|
const timeout = options.timeout ?? this.timeout;
|
|
367
456
|
const maxRetries = options.maxRetries ?? this.maxRetries;
|
|
368
457
|
const fetchOptions = {
|
|
@@ -420,6 +509,499 @@ var Transport = class {
|
|
|
420
509
|
}
|
|
421
510
|
};
|
|
422
511
|
//#endregion
|
|
512
|
+
//#region src/batch.ts
|
|
513
|
+
/** What the batch needs from each entry it sends, kept off the entry itself. */
|
|
514
|
+
const made = /* @__PURE__ */ new WeakMap();
|
|
515
|
+
/** An entry for one operation. Called by the generated builder. */
|
|
516
|
+
function entry(call) {
|
|
517
|
+
let path = call.path;
|
|
518
|
+
for (const [name, value] of Object.entries(call.pathParams ?? {})) path = path.replace(`{${name}}`, encodeURIComponent(value));
|
|
519
|
+
const search = new URLSearchParams();
|
|
520
|
+
appendQuery(search, call.query);
|
|
521
|
+
const relative = path.slice(12);
|
|
522
|
+
const query = search.toString();
|
|
523
|
+
const url = query ? `${relative}?${query}` : relative;
|
|
524
|
+
const value = Object.freeze({
|
|
525
|
+
method: call.method,
|
|
526
|
+
url
|
|
527
|
+
});
|
|
528
|
+
made.set(value, {
|
|
529
|
+
label: `${call.method} ${call.path}`,
|
|
530
|
+
resource: call.body,
|
|
531
|
+
expects: call.expects
|
|
532
|
+
});
|
|
533
|
+
return value;
|
|
534
|
+
}
|
|
535
|
+
/** The batch Bundle for these entries. Throws for anything the builder did not make. */
|
|
536
|
+
function batchBundle(entries) {
|
|
537
|
+
if (!Array.isArray(entries)) throw new Haau3Error("batch() takes a function that returns a list of entries made by the builder it is given.");
|
|
538
|
+
return {
|
|
539
|
+
resourceType: "Bundle",
|
|
540
|
+
type: "batch",
|
|
541
|
+
entry: entries.map((value, index) => {
|
|
542
|
+
const internal = typeof value === "object" && value !== null ? made.get(value) : void 0;
|
|
543
|
+
if (!internal) throw new Haau3Error(`Entry ${index + 1} of the batch was not made by the builder batch() hands you.`);
|
|
544
|
+
return {
|
|
545
|
+
request: {
|
|
546
|
+
method: value.method,
|
|
547
|
+
url: value.url
|
|
548
|
+
},
|
|
549
|
+
...internal.resource !== void 0 ? { resource: internal.resource } : {}
|
|
550
|
+
};
|
|
551
|
+
})
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
/** A batch entry's status: "200", or "200 OK" with its reason phrase, as FHIR allows. */
|
|
555
|
+
function entryStatus(entry) {
|
|
556
|
+
const match = /^(\d{3})(?:\s|$)/.exec(entry?.response?.status ?? "");
|
|
557
|
+
return match ? Number(match[1]) : void 0;
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Reads a batch-response into one result per entry sent. FHIR R4 says a batch-response holds one
|
|
561
|
+
* entry for each entry of the request, in the same order, so each answer is paired with its request
|
|
562
|
+
* by position. An answer that is not a batch-response, or holds another number of entries, cannot be
|
|
563
|
+
* paired at all and is no answer.
|
|
564
|
+
*/
|
|
565
|
+
function readBatch(entries, answer, meta) {
|
|
566
|
+
const { requestId, correlationId, attempts, durationMs, status } = meta;
|
|
567
|
+
const timing = {
|
|
568
|
+
attempts,
|
|
569
|
+
durationMs,
|
|
570
|
+
correlationId
|
|
571
|
+
};
|
|
572
|
+
const answered = answer.entry ?? [];
|
|
573
|
+
if (answer.type !== "batch-response") throw new NoAnswerError(`POST /v1/fhir/r4 answered a Bundle that is not a batch-response.`, {
|
|
574
|
+
reason: "unreadable",
|
|
575
|
+
status,
|
|
576
|
+
requestId,
|
|
577
|
+
...timing
|
|
578
|
+
});
|
|
579
|
+
if (answered.length !== entries.length) throw new NoAnswerError(`POST /v1/fhir/r4 answered ${answered.length} entries for a batch of ${entries.length}.`, {
|
|
580
|
+
reason: "unreadable",
|
|
581
|
+
status,
|
|
582
|
+
requestId,
|
|
583
|
+
...timing
|
|
584
|
+
});
|
|
585
|
+
return entries.map((value, index) => {
|
|
586
|
+
const internal = made.get(value);
|
|
587
|
+
const name = `${internal.label} (entry ${index + 1} of ${entries.length})`;
|
|
588
|
+
const answeredEntry = answered[index];
|
|
589
|
+
const entryCode = entryStatus(answeredEntry);
|
|
590
|
+
if (entryCode === void 0) return {
|
|
591
|
+
ok: false,
|
|
592
|
+
error: new NoAnswerError(`${name} answered with no status.`, {
|
|
593
|
+
reason: "unreadable",
|
|
594
|
+
requestId,
|
|
595
|
+
...timing
|
|
596
|
+
})
|
|
597
|
+
};
|
|
598
|
+
const verdict = judge(name, entryCode, answeredEntry?.resource ?? (entryCode >= 400 ? answeredEntry?.response?.outcome : void 0), {
|
|
599
|
+
requestId,
|
|
600
|
+
correlationId,
|
|
601
|
+
attempts,
|
|
602
|
+
durationMs,
|
|
603
|
+
expects: internal.expects,
|
|
604
|
+
missing: "no resource",
|
|
605
|
+
entry: true
|
|
606
|
+
});
|
|
607
|
+
return verdict.ok ? {
|
|
608
|
+
ok: true,
|
|
609
|
+
data: verdict.data,
|
|
610
|
+
status: entryCode
|
|
611
|
+
} : {
|
|
612
|
+
ok: false,
|
|
613
|
+
error: verdict.error
|
|
614
|
+
};
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
//#endregion
|
|
618
|
+
//#region src/generated/batch.ts
|
|
619
|
+
/**
|
|
620
|
+
* Every operation a batch can carry, each called as on {@link Haau3} and returning an entry for the
|
|
621
|
+
* batch instead of sending. Everything on the FHIR base but the batch itself and
|
|
622
|
+
* `reconcileMedications`.
|
|
623
|
+
*/
|
|
624
|
+
var BatchBuilder = class {
|
|
625
|
+
/**
|
|
626
|
+
* Check providers against a plan's network, as one entry of a batch. Called as `Haau3.checkInsurancePlanNetwork` is.
|
|
627
|
+
*
|
|
628
|
+
* `GET /v1/fhir/r4/InsurancePlan/{id}/$in-network`
|
|
629
|
+
*/
|
|
630
|
+
checkInsurancePlanNetwork(id, params) {
|
|
631
|
+
return entry({
|
|
632
|
+
method: "GET",
|
|
633
|
+
path: "/v1/fhir/r4/InsurancePlan/{id}/$in-network",
|
|
634
|
+
pathParams: { id },
|
|
635
|
+
query: params,
|
|
636
|
+
expects: ["Parameters"]
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Look up a code, as one entry of a batch. Called as `Haau3.codeSystemLookup` is.
|
|
641
|
+
*
|
|
642
|
+
* `GET /v1/fhir/r4/CodeSystem/$lookup`
|
|
643
|
+
*/
|
|
644
|
+
codeSystemLookup(params) {
|
|
645
|
+
return entry({
|
|
646
|
+
method: "GET",
|
|
647
|
+
path: "/v1/fhir/r4/CodeSystem/$lookup",
|
|
648
|
+
query: params,
|
|
649
|
+
expects: ["Parameters"]
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Look up a code, as one entry of a batch. Called as `Haau3.codeSystemLookupPost` is.
|
|
654
|
+
*
|
|
655
|
+
* `POST /v1/fhir/r4/CodeSystem/$lookup`
|
|
656
|
+
*/
|
|
657
|
+
codeSystemLookupPost(body) {
|
|
658
|
+
return entry({
|
|
659
|
+
method: "POST",
|
|
660
|
+
path: "/v1/fhir/r4/CodeSystem/$lookup",
|
|
661
|
+
body,
|
|
662
|
+
expects: ["Parameters"]
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Validate a code in a code system, as one entry of a batch. Called as `Haau3.codeSystemValidateCode` is.
|
|
667
|
+
*
|
|
668
|
+
* `GET /v1/fhir/r4/CodeSystem/$validate-code`
|
|
669
|
+
*/
|
|
670
|
+
codeSystemValidateCode(params) {
|
|
671
|
+
return entry({
|
|
672
|
+
method: "GET",
|
|
673
|
+
path: "/v1/fhir/r4/CodeSystem/$validate-code",
|
|
674
|
+
query: params,
|
|
675
|
+
expects: ["Parameters"]
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Validate a code in a code system, as one entry of a batch. Called as `Haau3.codeSystemValidateCodePost` is.
|
|
680
|
+
*
|
|
681
|
+
* `POST /v1/fhir/r4/CodeSystem/$validate-code`
|
|
682
|
+
*/
|
|
683
|
+
codeSystemValidateCodePost(body) {
|
|
684
|
+
return entry({
|
|
685
|
+
method: "POST",
|
|
686
|
+
path: "/v1/fhir/r4/CodeSystem/$validate-code",
|
|
687
|
+
body,
|
|
688
|
+
expects: ["Parameters"]
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Capability statement, as one entry of a batch. Called as `Haau3.fhirMetadata` is.
|
|
693
|
+
*
|
|
694
|
+
* `GET /v1/fhir/r4/metadata`
|
|
695
|
+
*/
|
|
696
|
+
fhirMetadata(params) {
|
|
697
|
+
return entry({
|
|
698
|
+
method: "GET",
|
|
699
|
+
path: "/v1/fhir/r4/metadata",
|
|
700
|
+
query: params,
|
|
701
|
+
expects: ["CapabilityStatement", "TerminologyCapabilities"]
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* List a state's counties, as one entry of a batch. Called as `Haau3.listInsurancePlanCounties` is.
|
|
706
|
+
*
|
|
707
|
+
* `GET /v1/fhir/r4/InsurancePlan/$counties`
|
|
708
|
+
*/
|
|
709
|
+
listInsurancePlanCounties(params) {
|
|
710
|
+
return entry({
|
|
711
|
+
method: "GET",
|
|
712
|
+
path: "/v1/fhir/r4/InsurancePlan/$counties",
|
|
713
|
+
query: params,
|
|
714
|
+
expects: ["Parameters"]
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Read an Endpoint, as one entry of a batch. Called as `Haau3.readEndpoint` is.
|
|
719
|
+
*
|
|
720
|
+
* `GET /v1/fhir/r4/Endpoint/{id}`
|
|
721
|
+
*/
|
|
722
|
+
readEndpoint(id) {
|
|
723
|
+
return entry({
|
|
724
|
+
method: "GET",
|
|
725
|
+
path: "/v1/fhir/r4/Endpoint/{id}",
|
|
726
|
+
pathParams: { id },
|
|
727
|
+
expects: ["Endpoint"]
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Read a HealthcareService, as one entry of a batch. Called as `Haau3.readHealthcareService` is.
|
|
732
|
+
*
|
|
733
|
+
* `GET /v1/fhir/r4/HealthcareService/{id}`
|
|
734
|
+
*/
|
|
735
|
+
readHealthcareService(id) {
|
|
736
|
+
return entry({
|
|
737
|
+
method: "GET",
|
|
738
|
+
path: "/v1/fhir/r4/HealthcareService/{id}",
|
|
739
|
+
pathParams: { id },
|
|
740
|
+
expects: ["HealthcareService"]
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Read a plan, as one entry of a batch. Called as `Haau3.readInsurancePlan` is.
|
|
745
|
+
*
|
|
746
|
+
* `GET /v1/fhir/r4/InsurancePlan/{id}`
|
|
747
|
+
*/
|
|
748
|
+
readInsurancePlan(id) {
|
|
749
|
+
return entry({
|
|
750
|
+
method: "GET",
|
|
751
|
+
path: "/v1/fhir/r4/InsurancePlan/{id}",
|
|
752
|
+
pathParams: { id },
|
|
753
|
+
expects: ["InsurancePlan"]
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Read a Location, as one entry of a batch. Called as `Haau3.readLocation` is.
|
|
758
|
+
*
|
|
759
|
+
* `GET /v1/fhir/r4/Location/{id}`
|
|
760
|
+
*/
|
|
761
|
+
readLocation(id) {
|
|
762
|
+
return entry({
|
|
763
|
+
method: "GET",
|
|
764
|
+
path: "/v1/fhir/r4/Location/{id}",
|
|
765
|
+
pathParams: { id },
|
|
766
|
+
expects: ["Location"]
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Read an Organization, as one entry of a batch. Called as `Haau3.readOrganization` is.
|
|
771
|
+
*
|
|
772
|
+
* `GET /v1/fhir/r4/Organization/{id}`
|
|
773
|
+
*/
|
|
774
|
+
readOrganization(id) {
|
|
775
|
+
return entry({
|
|
776
|
+
method: "GET",
|
|
777
|
+
path: "/v1/fhir/r4/Organization/{id}",
|
|
778
|
+
pathParams: { id },
|
|
779
|
+
expects: ["Organization"]
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Read an OrganizationAffiliation, as one entry of a batch. Called as `Haau3.readOrganizationAffiliation` is.
|
|
784
|
+
*
|
|
785
|
+
* `GET /v1/fhir/r4/OrganizationAffiliation/{id}`
|
|
786
|
+
*/
|
|
787
|
+
readOrganizationAffiliation(id) {
|
|
788
|
+
return entry({
|
|
789
|
+
method: "GET",
|
|
790
|
+
path: "/v1/fhir/r4/OrganizationAffiliation/{id}",
|
|
791
|
+
pathParams: { id },
|
|
792
|
+
expects: ["OrganizationAffiliation"]
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Read a Practitioner, as one entry of a batch. Called as `Haau3.readPractitioner` is.
|
|
797
|
+
*
|
|
798
|
+
* `GET /v1/fhir/r4/Practitioner/{id}`
|
|
799
|
+
*/
|
|
800
|
+
readPractitioner(id) {
|
|
801
|
+
return entry({
|
|
802
|
+
method: "GET",
|
|
803
|
+
path: "/v1/fhir/r4/Practitioner/{id}",
|
|
804
|
+
pathParams: { id },
|
|
805
|
+
expects: ["Practitioner"]
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
809
|
+
* Read a PractitionerRole, as one entry of a batch. Called as `Haau3.readPractitionerRole` is.
|
|
810
|
+
*
|
|
811
|
+
* `GET /v1/fhir/r4/PractitionerRole/{id}`
|
|
812
|
+
*/
|
|
813
|
+
readPractitionerRole(id) {
|
|
814
|
+
return entry({
|
|
815
|
+
method: "GET",
|
|
816
|
+
path: "/v1/fhir/r4/PractitionerRole/{id}",
|
|
817
|
+
pathParams: { id },
|
|
818
|
+
expects: ["PractitionerRole"]
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Read a questionnaire, as one entry of a batch. Called as `Haau3.readQuestionnaire` is.
|
|
823
|
+
*
|
|
824
|
+
* `GET /v1/fhir/r4/Questionnaire/{id}`
|
|
825
|
+
*/
|
|
826
|
+
readQuestionnaire(id) {
|
|
827
|
+
return entry({
|
|
828
|
+
method: "GET",
|
|
829
|
+
path: "/v1/fhir/r4/Questionnaire/{id}",
|
|
830
|
+
pathParams: { id },
|
|
831
|
+
expects: ["Questionnaire"]
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* Find endpoints, as one entry of a batch. Called as `Haau3.searchEndpoint` is.
|
|
836
|
+
*
|
|
837
|
+
* `GET /v1/fhir/r4/Endpoint`
|
|
838
|
+
*/
|
|
839
|
+
searchEndpoint(params) {
|
|
840
|
+
return entry({
|
|
841
|
+
method: "GET",
|
|
842
|
+
path: "/v1/fhir/r4/Endpoint",
|
|
843
|
+
query: params,
|
|
844
|
+
expects: ["Bundle"]
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Find healthcare services, as one entry of a batch. Called as `Haau3.searchHealthcareService` is.
|
|
849
|
+
*
|
|
850
|
+
* `GET /v1/fhir/r4/HealthcareService`
|
|
851
|
+
*/
|
|
852
|
+
searchHealthcareService(params) {
|
|
853
|
+
return entry({
|
|
854
|
+
method: "GET",
|
|
855
|
+
path: "/v1/fhir/r4/HealthcareService",
|
|
856
|
+
query: params,
|
|
857
|
+
expects: ["Bundle"]
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Find a plan, as one entry of a batch. Called as `Haau3.searchInsurancePlan` is.
|
|
862
|
+
*
|
|
863
|
+
* `GET /v1/fhir/r4/InsurancePlan`
|
|
864
|
+
*/
|
|
865
|
+
searchInsurancePlan(params) {
|
|
866
|
+
return entry({
|
|
867
|
+
method: "GET",
|
|
868
|
+
path: "/v1/fhir/r4/InsurancePlan",
|
|
869
|
+
query: params,
|
|
870
|
+
expects: ["Bundle"]
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* Find practice locations, as one entry of a batch. Called as `Haau3.searchLocation` is.
|
|
875
|
+
*
|
|
876
|
+
* `GET /v1/fhir/r4/Location`
|
|
877
|
+
*/
|
|
878
|
+
searchLocation(params) {
|
|
879
|
+
return entry({
|
|
880
|
+
method: "GET",
|
|
881
|
+
path: "/v1/fhir/r4/Location",
|
|
882
|
+
query: params,
|
|
883
|
+
expects: ["Bundle"]
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* Find organizations, payers and networks, as one entry of a batch. Called as `Haau3.searchOrganization` is.
|
|
888
|
+
*
|
|
889
|
+
* `GET /v1/fhir/r4/Organization`
|
|
890
|
+
*/
|
|
891
|
+
searchOrganization(params) {
|
|
892
|
+
return entry({
|
|
893
|
+
method: "GET",
|
|
894
|
+
path: "/v1/fhir/r4/Organization",
|
|
895
|
+
query: params,
|
|
896
|
+
expects: ["Bundle"]
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
/**
|
|
900
|
+
* Find the organizations in a network, as one entry of a batch. Called as `Haau3.searchOrganizationAffiliation` is.
|
|
901
|
+
*
|
|
902
|
+
* `GET /v1/fhir/r4/OrganizationAffiliation`
|
|
903
|
+
*/
|
|
904
|
+
searchOrganizationAffiliation(params) {
|
|
905
|
+
return entry({
|
|
906
|
+
method: "GET",
|
|
907
|
+
path: "/v1/fhir/r4/OrganizationAffiliation",
|
|
908
|
+
query: params,
|
|
909
|
+
expects: ["Bundle"]
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Find a practitioner by NPI or name, as one entry of a batch. Called as `Haau3.searchPractitioner` is.
|
|
914
|
+
*
|
|
915
|
+
* `GET /v1/fhir/r4/Practitioner`
|
|
916
|
+
*/
|
|
917
|
+
searchPractitioner(params) {
|
|
918
|
+
return entry({
|
|
919
|
+
method: "GET",
|
|
920
|
+
path: "/v1/fhir/r4/Practitioner",
|
|
921
|
+
query: params,
|
|
922
|
+
expects: ["Bundle"]
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* Find practitioner roles, as one entry of a batch. Called as `Haau3.searchPractitionerRole` is.
|
|
927
|
+
*
|
|
928
|
+
* `GET /v1/fhir/r4/PractitionerRole`
|
|
929
|
+
*/
|
|
930
|
+
searchPractitionerRole(params) {
|
|
931
|
+
return entry({
|
|
932
|
+
method: "GET",
|
|
933
|
+
path: "/v1/fhir/r4/PractitionerRole",
|
|
934
|
+
query: params,
|
|
935
|
+
expects: ["Bundle"]
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* List or find a questionnaire, as one entry of a batch. Called as `Haau3.searchQuestionnaire` is.
|
|
940
|
+
*
|
|
941
|
+
* `GET /v1/fhir/r4/Questionnaire`
|
|
942
|
+
*/
|
|
943
|
+
searchQuestionnaire(params) {
|
|
944
|
+
return entry({
|
|
945
|
+
method: "GET",
|
|
946
|
+
path: "/v1/fhir/r4/Questionnaire",
|
|
947
|
+
query: params,
|
|
948
|
+
expects: ["Bundle"]
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Expand a value set, as one entry of a batch. Called as `Haau3.valueSetExpand` is.
|
|
953
|
+
*
|
|
954
|
+
* `GET /v1/fhir/r4/ValueSet/$expand`
|
|
955
|
+
*/
|
|
956
|
+
valueSetExpand(params) {
|
|
957
|
+
return entry({
|
|
958
|
+
method: "GET",
|
|
959
|
+
path: "/v1/fhir/r4/ValueSet/$expand",
|
|
960
|
+
query: params,
|
|
961
|
+
expects: ["ValueSet"]
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* Expand a value set, as one entry of a batch. Called as `Haau3.valueSetExpandPost` is.
|
|
966
|
+
*
|
|
967
|
+
* `POST /v1/fhir/r4/ValueSet/$expand`
|
|
968
|
+
*/
|
|
969
|
+
valueSetExpandPost(body) {
|
|
970
|
+
return entry({
|
|
971
|
+
method: "POST",
|
|
972
|
+
path: "/v1/fhir/r4/ValueSet/$expand",
|
|
973
|
+
body,
|
|
974
|
+
expects: ["ValueSet"]
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* Validate a code against a value set, as one entry of a batch. Called as `Haau3.valueSetValidateCode` is.
|
|
979
|
+
*
|
|
980
|
+
* `GET /v1/fhir/r4/ValueSet/$validate-code`
|
|
981
|
+
*/
|
|
982
|
+
valueSetValidateCode(params) {
|
|
983
|
+
return entry({
|
|
984
|
+
method: "GET",
|
|
985
|
+
path: "/v1/fhir/r4/ValueSet/$validate-code",
|
|
986
|
+
query: params,
|
|
987
|
+
expects: ["Parameters"]
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Validate a code against a value set, as one entry of a batch. Called as `Haau3.valueSetValidateCodePost` is.
|
|
992
|
+
*
|
|
993
|
+
* `POST /v1/fhir/r4/ValueSet/$validate-code`
|
|
994
|
+
*/
|
|
995
|
+
valueSetValidateCodePost(body) {
|
|
996
|
+
return entry({
|
|
997
|
+
method: "POST",
|
|
998
|
+
path: "/v1/fhir/r4/ValueSet/$validate-code",
|
|
999
|
+
body,
|
|
1000
|
+
expects: ["Parameters"]
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
//#endregion
|
|
423
1005
|
//#region src/generated/methods.ts
|
|
424
1006
|
/** Every operation of the haau3 platform API. {@link Haau3} is the class to construct. */
|
|
425
1007
|
var Operations = class extends Transport {
|
|
@@ -989,6 +1571,8 @@ var Operations = class extends Transport {
|
|
|
989
1571
|
};
|
|
990
1572
|
//#endregion
|
|
991
1573
|
//#region src/client.ts
|
|
1574
|
+
/** The builder every batch is handed. It holds nothing, so one serves every call. */
|
|
1575
|
+
const builder = new BatchBuilder();
|
|
992
1576
|
/**
|
|
993
1577
|
* The haau3 platform API client.
|
|
994
1578
|
*
|
|
@@ -1028,6 +1612,45 @@ var Haau3 = class extends Operations {
|
|
|
1028
1612
|
page = await this.answer("GET", url, void 0, options, url.pathname, ["Bundle"]);
|
|
1029
1613
|
}
|
|
1030
1614
|
}
|
|
1615
|
+
/**
|
|
1616
|
+
* Several operations of the FHIR base in one request, each with its own answer or error, in the
|
|
1617
|
+
* order given. The function you pass gets a builder with every operation a batch can carry, called
|
|
1618
|
+
* as on this client; what it returns is sent.
|
|
1619
|
+
*
|
|
1620
|
+
* ```ts
|
|
1621
|
+
* const [plan, counties] = await haau3.batch((b) => [
|
|
1622
|
+
* b.readInsurancePlan("H2406-013-000"),
|
|
1623
|
+
* b.listInsurancePlanCounties({ state: "NC" }),
|
|
1624
|
+
* ]);
|
|
1625
|
+
* if (plan.ok) plan.data; // fhir4.InsurancePlan
|
|
1626
|
+
* else plan.error; // RefusedError or NoAnswerError, as the call alone would have thrown
|
|
1627
|
+
* ```
|
|
1628
|
+
*
|
|
1629
|
+
* Each entry is checked as the call alone is, and fails alone: its result is `{ ok: false, error }`
|
|
1630
|
+
* and the others still answer. An entry that fails is not retried. The batch itself is retried,
|
|
1631
|
+
* and throws, as any call does: an {@link AuthError}, a {@link NoAnswerError} when no answer came
|
|
1632
|
+
* back, a {@link RefusedError} when the API refused the whole batch. The API takes up to 100
|
|
1633
|
+
* entries in up to 1 MiB, and gives a batch 60 seconds; a larger batch is refused, so send several.
|
|
1634
|
+
* `reconcileMedications` cannot go in a batch.
|
|
1635
|
+
*/
|
|
1636
|
+
batch(build, options = {}) {
|
|
1637
|
+
let entries;
|
|
1638
|
+
let bundle;
|
|
1639
|
+
try {
|
|
1640
|
+
entries = build(builder);
|
|
1641
|
+
bundle = batchBundle(entries);
|
|
1642
|
+
} catch (error) {
|
|
1643
|
+
return new APIPromise(Promise.reject(error));
|
|
1644
|
+
}
|
|
1645
|
+
return new APIPromise(this.#sendBatch(entries, bundle, options));
|
|
1646
|
+
}
|
|
1647
|
+
async #sendBatch(entries, bundle, options) {
|
|
1648
|
+
const { data, ...meta } = await this.respond("POST", this.url("/v1/fhir/r4"), bundle, options, "/v1/fhir/r4", ["Bundle"]);
|
|
1649
|
+
return {
|
|
1650
|
+
...meta,
|
|
1651
|
+
data: readBatch(entries, data, meta)
|
|
1652
|
+
};
|
|
1653
|
+
}
|
|
1031
1654
|
};
|
|
1032
1655
|
//#endregion
|
|
1033
1656
|
export { APIPromise, AuthError, Haau3, Haau3Error, NoAnswerError, RefusedError, VERSION };
|