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