@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 CHANGED
@@ -1,7 +1,15 @@
1
1
  # @haau3/sdk
2
2
 
3
- The TypeScript SDK for the [haau3 platform API](https://docs.haau3.com): scheduling, the provider
4
- directory, terminology, questionnaires, plan benefits and MedList, as typed calls.
3
+ The TypeScript SDK for the [haau3 platform API](https://docs.haau3.com), as typed calls:
4
+
5
+ - **Scheduling:** open appointment slots from many SMART Scheduling Links publishers, in one search.
6
+ - **Plan Benefits:** Medicare Advantage and ACA Marketplace plans as FHIR `InsurancePlan`,
7
+ searchable by state or county, and which providers are in a plan's network.
8
+ - **MedList:** one reconciled medication list from one patient's FHIR medication records.
9
+
10
+ On the same key and FHIR base: RxNorm and LOINC lookups, value sets and code validation
11
+ (Terminology), practitioners and organizations from CMS's National Provider Directory (Provider
12
+ directory), and standard FHIR Questionnaires such as the PHQ-9.
5
13
 
6
14
  The haau3 platform API is in preview: it may change as we build, usually to add features or improve performance.
7
15
 
@@ -63,6 +71,14 @@ Every method, grouped by service, with its request and a link to its page on doc
63
71
  [api.md](https://github.com/haau3/haau3-node/blob/main/api.md). Each is named by its operationId,
64
72
  with its parameters and its answer typed from the published spec.
65
73
 
74
+ ## With an AI coding agent
75
+
76
+ An agent can read the docs directly:
77
+
78
+ - [docs.haau3.com/llms.txt](https://docs.haau3.com/llms.txt) lists every docs page as Markdown.
79
+ - `https://docs.haau3.com/mcp` is an MCP server that searches the docs. In Claude Code:
80
+ `claude mcp add --transport http haau3 https://docs.haau3.com/mcp`.
81
+
66
82
  ## Options
67
83
 
68
84
  | Option | Default | |
@@ -74,8 +90,8 @@ with its parameters and its answer typed from the published spec.
74
90
  | `fetch` | the global `fetch` | The fetch to send requests with. |
75
91
  | `fetchOptions` | `{ cache: "no-store" }` | Passed on to `fetch` with every request, for any runtime. |
76
92
 
77
- Each call takes `{ timeout, maxRetries, signal, headers, fetchOptions }` as its last argument, for
78
- that call only:
93
+ Each call takes `{ timeout, maxRetries, signal, correlationId, headers, fetchOptions }` as its last
94
+ argument, for that call only:
79
95
 
80
96
  ```ts
81
97
  await haau3.searchSlots({ state: "MA" }, { timeout: 10_000, maxRetries: 0 });
@@ -129,8 +145,13 @@ never printed when the error is logged. Every error the API answered carries `at
129
145
  `durationMs` too.
130
146
 
131
147
  A FHIR answer is checked against the resource types its operation answers with. Anything else, a
132
- `Bundle` where an `InsurancePlan` was asked for, say, is a `NoAnswerError` with reason `"unreadable"`,
133
- so what a method returns is always the type it says.
148
+ `Bundle` where an `InsurancePlan` was asked for, say, is a `NoAnswerError` with reason
149
+ `"unreadable"`. The check is of the resource type, not of every element inside it: those are typed
150
+ as FHIR R4 declares them, and the SDK does not validate each one.
151
+
152
+ `error.toJSON()` gives an error as a plain object that is safe to log: its name, its message and the
153
+ fields above that are set, and never the body or the `cause`. `JSON.stringify(error)` prints the
154
+ same.
134
155
 
135
156
  ## Request ids and timing
136
157
 
@@ -143,6 +164,15 @@ const { data: plan, requestId, durationMs, attempts } = await haau3.readInsuranc
143
164
 
144
165
  Quote the `requestId` when you ask for help: it finds the request in the API's own logs.
145
166
 
167
+ To find a request by an id of your own, such as your job's or your trace's, pass it as
168
+ `correlationId`. It must be a UUID, which is all the API keeps; anything else is refused before it
169
+ is sent. The API keeps it with its record of the request, and it comes back on the answer and on
170
+ every error the API answered:
171
+
172
+ ```ts
173
+ const { data, correlationId } = await haau3.readInsurancePlan(id, { correlationId: jobId }).withResponse();
174
+ ```
175
+
146
176
  ## Paging
147
177
 
148
178
  `pages()` yields a FHIR search's first page and every page after it:
@@ -158,17 +188,40 @@ Scheduling's searches page with `limit` and `offset`, and answer with a `total`.
158
188
 
159
189
  ## Several requests in one
160
190
 
191
+ `batch()` sends several operations of the FHIR base as one request. The function you pass gets a
192
+ builder with the client's own methods, called the same way, which make entries instead of sending.
193
+ Each entry gets its own result, in the order given:
194
+
161
195
  ```ts
162
- const answers = await haau3.fhirBatch({
163
- resourceType: "Bundle",
164
- type: "batch",
165
- entry: [
166
- { request: { method: "GET", url: "CodeSystem/$lookup?system=http://loinc.org&code=2345-7" } },
167
- { request: { method: "GET", url: "InsurancePlan/$counties?state=NC" } },
168
- ],
169
- });
196
+ const [plan, counties] = await haau3.batch((b) => [
197
+ b.readInsurancePlan("H2406-013-000"),
198
+ b.listInsurancePlanCounties({ state: "NC" }),
199
+ ]);
200
+
201
+ if (plan.ok) {
202
+ plan.data; // fhir4.InsurancePlan
203
+ } else {
204
+ plan.error; // a RefusedError or a NoAnswerError, as readInsurancePlan alone would have thrown
205
+ }
170
206
  ```
171
207
 
208
+ A list built in code works the same way:
209
+
210
+ ```ts
211
+ const lookups = await haau3.batch((b) =>
212
+ codes.map((code) => b.codeSystemLookup({ system: "http://loinc.org", code, property: "CLASSTYPE" })),
213
+ );
214
+ ```
215
+
216
+ Each entry is checked as the call alone is, and fails alone while the others answer. An entry that
217
+ fails is not retried. The batch itself is retried, and throws, as any call does, and
218
+ `.withResponse()` gives its request id. The API takes up to 100 entries in up to 1 MiB and gives a
219
+ batch 60 seconds, so send a longer list as several batches. Every operation on the FHIR base can go
220
+ in a batch except `reconcileMedications`.
221
+
222
+ To send a batch `Bundle` you built yourself, `fhirBatch()` takes it and returns the
223
+ `batch-response` as it is.
224
+
172
225
  ## Any request
173
226
 
174
227
  `request()` sends a request as you give it and returns what the API answered, whatever the