@emulates/caretalk 0.0.0-stage → 3.0.0
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/CHANGELOG.md +19 -0
- package/DISCOVERY.md +55 -0
- package/README.md +125 -2
- package/SUPPORT.md +19 -0
- package/dist/chunk-GGJSTUWM.js +4118 -0
- package/dist/chunk-GGJSTUWM.js.map +7 -0
- package/dist/chunk-PD6GHEG3.js +848 -0
- package/dist/chunk-PD6GHEG3.js.map +7 -0
- package/dist/cli.js +19 -0
- package/dist/cli.js.map +7 -0
- package/dist/index.d.ts +1110 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +7 -0
- package/dist/server.d.ts +1520 -0
- package/dist/server.js +12 -0
- package/dist/server.js.map +7 -0
- package/openapi.yaml +1191 -0
- package/package.json +115 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelog — @emulates/caretalk
|
|
2
|
+
|
|
3
|
+
## 3.0.0 (2026-10-07)
|
|
4
|
+
|
|
5
|
+
### ⚠️ Breaking changes
|
|
6
|
+
|
|
7
|
+
- point the repo at crvouga/emulates ([cdb5e53](https://github.com/crvouga/emulates/commit/cdb5e536ed8c1f52345e3984f089001c25fdb08a))
|
|
8
|
+
|
|
9
|
+
### Fixes and improvements
|
|
10
|
+
|
|
11
|
+
- format the emulates records query ([8698872](https://github.com/crvouga/emulates/commit/8698872509d06002be5a8fcdc85d79f8462320c3))
|
|
12
|
+
|
|
13
|
+
### Dependencies
|
|
14
|
+
|
|
15
|
+
- `@emulates/sqlite`
|
|
16
|
+
|
|
17
|
+
## 2.3.1 (2026-10-06)
|
|
18
|
+
|
|
19
|
+
Initial release.
|
package/DISCOVERY.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# @emulates/caretalk discovery
|
|
2
|
+
|
|
3
|
+
This is the installed-package index for coding agents and tooling. All relative links resolve
|
|
4
|
+
inside `node_modules/@emulates/caretalk/`; no repository checkout is needed to discover the emulator's
|
|
5
|
+
supported surface or documented behavior.
|
|
6
|
+
|
|
7
|
+
## Capability and behavior sources
|
|
8
|
+
|
|
9
|
+
| Question | Authoritative file | What it contains |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| Behaviour and integration | [`README.md`](README.md) | Routes, state transitions, auth, webhooks, controls, presets and deliberate omissions. |
|
|
12
|
+
| Exact capabilities | [`SUPPORT.md`](SUPPORT.md) | Supported, unsupported and parity-covered operations or commands, including reasons for gaps. |
|
|
13
|
+
| Wire contract | [`openapi.yaml`](openapi.yaml) | Machine-readable paths, methods, schemas, responses and parity annotations. |
|
|
14
|
+
| Public API | [`dist/index.d.ts`](dist/index.d.ts) | The installed package's exact TypeScript exports and signatures. |
|
|
15
|
+
| Package metadata | [`package.json`](package.json) | Runtime/entry-point claims, vendor links, parity scope/tier and `emulates.discovery`. |
|
|
16
|
+
|
|
17
|
+
Read these together: the contract/capability matrix says *what* is available, while the README
|
|
18
|
+
defines stateful behavior, lifecycle rules, test controls, and intentional oracle differences.
|
|
19
|
+
If prose and an executable surface disagree, report a parity mismatch instead of adding a
|
|
20
|
+
consumer-side workaround.
|
|
21
|
+
|
|
22
|
+
## Parity and oracle
|
|
23
|
+
|
|
24
|
+
- Declared parity surface: **Forms, patients, and appointments**.
|
|
25
|
+
- Parity tier: **cold** (the repository controls when live checks run).
|
|
26
|
+
- Oracle: **Live vendor API or sandbox**.
|
|
27
|
+
- Repository command: `bun run parity:service -- caretalk`.
|
|
28
|
+
- Evidence model: Run from an Emulates checkout; credentials come only from .env.local or GitHub Actions secrets. Missing credentials exit 2.
|
|
29
|
+
|
|
30
|
+
The npm package contains evidence summaries and the exact contract, not credentials or the
|
|
31
|
+
repository-only parity harness. Self-parity/property and acceptance tests run in the Emulates
|
|
32
|
+
repository; live parity is an additional oracle check, not a substitute for the packaged matrix.
|
|
33
|
+
|
|
34
|
+
## Runtime introspection
|
|
35
|
+
|
|
36
|
+
- `GET /__admin/health`
|
|
37
|
+
- `GET /__admin`
|
|
38
|
+
- `GET /__admin/state`
|
|
39
|
+
- `GET /__admin/requests`
|
|
40
|
+
- `GET /__admin/metrics`
|
|
41
|
+
- `GET /__admin/faults/presets`
|
|
42
|
+
- `GET /__admin/ui`
|
|
43
|
+
|
|
44
|
+
For HTTP services, use `x-emulates-namespace` (or the documented credential/path carrier) so
|
|
45
|
+
parallel tests do not share state. Admin state, journal, metrics and fault-preset endpoints are
|
|
46
|
+
designed for assertions and diagnosis by consuming test suites.
|
|
47
|
+
|
|
48
|
+
## Report a mismatch or missing capability
|
|
49
|
+
|
|
50
|
+
Follow the [agent reporting contract](https://github.com/crvouga/emulates/blob/main/docs/REPORTING_ISSUES.md). Include package version,
|
|
51
|
+
operation/command, a minimal redacted request, actual emulator result, expected oracle result or vendor
|
|
52
|
+
documentation, and whether the mismatch appears in the matrix. Never include keys, tokens,
|
|
53
|
+
customer data, prompts, PHI, card data, or unredacted recordings.
|
|
54
|
+
|
|
55
|
+
Service key: `caretalk`.
|
package/README.md
CHANGED
|
@@ -1,3 +1,126 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @emulates/caretalk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Part of [Emulates](https://github.com/crvouga/emulates): high-fidelity, in-process emulators for APIs and databases.
|
|
4
|
+
|
|
5
|
+
Stateful emulator of **CareTalk**'s external API (`/externalapi`) for test suites: client login,
|
|
6
|
+
form definitions (`GetForm`) and saved form rounds (`SavePatientForm`, the form-submission
|
|
7
|
+
queue's call), patient search and insert (the account backfill), states, free slots and
|
|
8
|
+
appointments. The backend requires CareTalk keys at boot, so the emulator lets a stack boot and run
|
|
9
|
+
the CareTalk paths without the beta environment.
|
|
10
|
+
|
|
11
|
+
- Operation coverage: [SUPPORT.md](https://github.com/crvouga/emulates/blob/main/packages/service/caretalk/SUPPORT.md)
|
|
12
|
+
- The vendor publishes no spec: the contract (`openapi.yaml`) is hand-authored from the
|
|
13
|
+
consumer's zod schemas and interfaces (`caretalk.types.ts`, `caretalk-forms.type.ts`).
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -D @emulates/caretalk
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
ESM only. Node >= 22 or Bun >= 1.2. No native dependencies. Serve it with
|
|
22
|
+
`npx emulates-caretalk serve`, `createServer` from `./server` (Node), or `createRuntime`
|
|
23
|
+
with any Fetch server.
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
Point `CARETALK_API_URL` at the emulator (the backend validates it as **https-only**, so relax that
|
|
28
|
+
for loopback or front the emulator with TLS). `getFormData` hardcodes
|
|
29
|
+
`https://api.caretalkbeta.com` (seam **G-Y1**). `CARETALK_USERNAME`, `CARETALK_PASSWORD` and
|
|
30
|
+
`CARETALK_API_KEY` can be any values unless `--api-user` / `--api-key` pin them.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx emulates-caretalk serve --port 8823 --api-user "$CARETALK_USERNAME:$CARETALK_PASSWORD" --api-key "$CARETALK_API_KEY"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { createRuntime } from "@emulates/caretalk"
|
|
38
|
+
|
|
39
|
+
const caretalk = createRuntime()
|
|
40
|
+
const call = (path: string, init: RequestInit = {}) =>
|
|
41
|
+
caretalk.fetch(new Request(`http://caretalk.test${path}`, init))
|
|
42
|
+
|
|
43
|
+
const { token } = (await (
|
|
44
|
+
await call("/externalapi/Auth/client-login", {
|
|
45
|
+
method: "POST",
|
|
46
|
+
headers: { "content-type": "application/json" },
|
|
47
|
+
// Any credentials log in unless --api-user pins them.
|
|
48
|
+
body: JSON.stringify({ userName: "acme-api", password: crypto.randomUUID() }),
|
|
49
|
+
})
|
|
50
|
+
).json()) as { token: string }
|
|
51
|
+
const [form] = (await (
|
|
52
|
+
await call("/externalapi/Forms/GetForm/health-history", {
|
|
53
|
+
headers: { authorization: `Bearer ${token}` },
|
|
54
|
+
})
|
|
55
|
+
).json()) as { fullFormDto: { id: number } }[]
|
|
56
|
+
// After the app's form-submission queue runs, assert what reached CareTalk:
|
|
57
|
+
const { submissions } = (await (await call("/__admin/form-submissions")).json()) as {
|
|
58
|
+
submissions: unknown[]
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Routes
|
|
63
|
+
|
|
64
|
+
| Route | Behaviour |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| `POST /externalapi/Auth/client-login` | `{userName, password}` → `{token, expiration}`. Tokens last `tokenTtlSeconds` (default 3600, what our client caches for) on the emulator clock. |
|
|
67
|
+
| `GET /externalapi/Forms/GetForm/{formName}` | By name or slug, case-insensitive: `[{formRoundId, patientAppointmentId, submitDate, fullFormDto}]`; an unknown form is `[]`. With `PatientId` (and `AppointmentId`), the patient's latest saved round: chosen answers `isChecked`, free text echoed. Accepts a login token or a static API key. |
|
|
68
|
+
| `POST /externalapi/Forms/SavePatientForm?patientId=&patientAppointmentId=` | The submission (`fullFormDto.groups[].groupQuestions[]`). Question ids must belong to the form, answer ids to the question (text questions take `id: 0` with the typed value), single-choice questions one answer; violations are 400 ProblemDetails, an unknown patient or form 404. → `{success: true, message}`. |
|
|
69
|
+
| `GET /externalapi/Patients/SearchForPatient?FirstName&LastName&zipCode&DateOfBirth` | Case-insensitive names, ZIP, and the date in any of `YYYY-MM-DD`, `MM/DD/YYYY`, ISO → `{isExists: true, eligibleId, programId}`; no match is **400** `{isExists: false, message}` (our client reads 400 as "no such patient"). |
|
|
70
|
+
| `GET /externalapi/States` | 51 states `{id, stateUid, name, abbreviation, …}` (UT is 45). |
|
|
71
|
+
| `POST /externalapi/Patients` | Creates a patient and echoes CareTalk's full record (`id`, `eligibilityId` = `id`, `userState`, `formattedUserMobile`, `clientId`, …). |
|
|
72
|
+
| `GET /externalapi/PatientAppointments/GetFreeSlots?date&programId&eligibleId` | Half-hour slots 09:00–16:30 for two physicians, minus booked ones. |
|
|
73
|
+
| `POST /externalapi/PatientAppointments` | `{doctorId, patientId (the eligible id), from, to}` → `{id, patientId: null, eligibilityId, appointmentStatus: 1, physicianId}`; a taken or unknown slot is 400. |
|
|
74
|
+
| `GET /externalapi/PatientAppointments/GetPatientAppointmentsByEligibleId/{id}` | That patient's appointments. |
|
|
75
|
+
|
|
76
|
+
Unauthenticated or expired calls are an empty 401 with `WWW-Authenticate: Bearer` (our client
|
|
77
|
+
logs in again once and retries). Validation errors are ASP.NET ProblemDetails
|
|
78
|
+
`{type, title, status, errors, traceId}`.
|
|
79
|
+
|
|
80
|
+
### Admin (beyond the standard contract)
|
|
81
|
+
|
|
82
|
+
| Route | Effect |
|
|
83
|
+
| --- | --- |
|
|
84
|
+
| `GET /__admin/form-submissions[?patientId=]` | Saved rounds: `{formRoundId, formId, patientId, patientAppointmentId, submitDate, answers: [{questionId, answerIds, freeAnswerText}]}`. |
|
|
85
|
+
| `GET` / `POST /__admin/patients` | List patients, or create one directly (the Patients POST body) so a search finds it. |
|
|
86
|
+
| `GET /__admin/forms`, `PUT /__admin/forms/:id` | List or add/replace a form definition (`fullFormDto` shape). |
|
|
87
|
+
| `POST /__admin/appointments/:id/status` | `{appointmentStatus}`: change an appointment's status code. |
|
|
88
|
+
| `GET/PUT /__admin/settings` | `{tokenTtlSeconds?, users?: [{userName, password}], apiKeys?, programId?}`. |
|
|
89
|
+
|
|
90
|
+
Fault presets (`POST /__admin/faults {"preset": "<name>", "count"?: n}`): `login_failure`,
|
|
91
|
+
`invalid_credentials`, `token_expired` (count applies per operation), `server_error`,
|
|
92
|
+
`gateway_html`, `form_not_found`, `patient_not_found`, `save_rejected`, `connection_drop`,
|
|
93
|
+
`slow`.
|
|
94
|
+
|
|
95
|
+
### Namespaces
|
|
96
|
+
|
|
97
|
+
`x-emulates-namespace`, a `/__admin/ns/<name>` prefix on `CARETALK_API_URL`, or by credential: tokens
|
|
98
|
+
carry the API user they were issued to, so `PUT /__admin/credentials {"credentials":
|
|
99
|
+
{"<CARETALK_USERNAME>": "<ns>", "<CARETALK_API_KEY>": "<ns>"}}` routes both auth styles.
|
|
100
|
+
|
|
101
|
+
### Deliberately not modelled
|
|
102
|
+
|
|
103
|
+
- CareTalk's clinical workflows behind the forms (reviews, form rounds created by staff),
|
|
104
|
+
eligibility files, Health Gorilla retrieval, medications and diagnostics.
|
|
105
|
+
- Real physician calendars: slots are synthesised; time zones are fixed to Mountain.
|
|
106
|
+
- The live form catalogue: `DEFAULT_FORMS` is synthesised in CareTalk's shape (the live-parity
|
|
107
|
+
script seeds the emulator from the beta environment's forms instead).
|
|
108
|
+
|
|
109
|
+
## API
|
|
110
|
+
|
|
111
|
+
| Export | Kind | Description |
|
|
112
|
+
| --- | --- | --- |
|
|
113
|
+
| `CareTalkAPI` | class | The in-process emulator: `fetch(request)`, `reset()`, `addPatient(body)`, `slots(date)`, `setAppointmentStatus(id, status)`, `upsertForm(form)`, `rounds()`, `patients()`. Options: `sqlite`, `now`, `namespace`, `forms`, `settings`. |
|
|
114
|
+
| `createRuntime` | function | The emulator with the full service contract (health, admin, namespaces, credentials, presets). Options: `forms`, `settings`, `clock`, `seed`, `adminKey`, `onLog`, `sqlite`. |
|
|
115
|
+
| `CARETALK_PRESETS` | object | Every named fault preset. |
|
|
116
|
+
| `CARETALK_NAMESPACE` | string | The service name, `"caretalk"`. |
|
|
117
|
+
| `DEFAULT_FORMS` | array | The seeded form definitions (Health History 101, AOE Questions 102). |
|
|
118
|
+
| `DEFAULT_DOCTORS` | array | The physicians free slots are generated for. |
|
|
119
|
+
| `US_STATES` | array | The `/externalapi/States` rows. |
|
|
120
|
+
| `tokenCredential` | function | The API user a token was issued to, or the static key (how credentials map to namespaces). |
|
|
121
|
+
| `normalizeDate` | function | `YYYY-MM-DD` from ISO, `YYYY-MM-DD` or `MM/DD/YYYY`. |
|
|
122
|
+
| `problem` | function | Build an ASP.NET ProblemDetails response. |
|
|
123
|
+
| `document`, `operationIds`, `supportedOperationIds` | values | The OpenAPI contract and its operation ids. |
|
|
124
|
+
| `createServer`, `serveTarget`, `DEFAULT_PORT` (`./server`) | Node | Serve over `node:http`; the `serve` CLI target (`--api-user`, `--api-key`); port 8823. |
|
|
125
|
+
|
|
126
|
+
Part of [Emulates](https://github.com/crvouga/emulates).
|
package/SUPPORT.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# CareTalk external API (Emulates subset) — operation support
|
|
2
|
+
|
|
3
|
+
Generated from `openapi.yaml`; do not edit by hand.
|
|
4
|
+
|
|
5
|
+
- operations in spec: **9**
|
|
6
|
+
- supported by the emulator: **9**
|
|
7
|
+
- parity enabled: **9**
|
|
8
|
+
|
|
9
|
+
| operationId | route | emulator | parity | notes |
|
|
10
|
+
| --- | --- | --- | --- | --- |
|
|
11
|
+
| `ClientLogin` | `POST /externalapi/Auth/client-login` | ✅ supported | ✅ | |
|
|
12
|
+
| `GetForm` | `GET /externalapi/Forms/GetForm/{formName}` | ✅ supported | ✅ | |
|
|
13
|
+
| `SavePatientForm` | `POST /externalapi/Forms/SavePatientForm` | ✅ supported | ⚠️ unsafe (opt-in) | |
|
|
14
|
+
| `SearchForPatient` | `GET /externalapi/Patients/SearchForPatient` | ✅ supported | ✅ | |
|
|
15
|
+
| `ListStates` | `GET /externalapi/States` | ✅ supported | ✅ | |
|
|
16
|
+
| `InsertPatient` | `POST /externalapi/Patients` | ✅ supported | ⚠️ unsafe (opt-in) | |
|
|
17
|
+
| `GetFreeSlots` | `GET /externalapi/PatientAppointments/GetFreeSlots` | ✅ supported | ✅ | |
|
|
18
|
+
| `ScheduleAppointment` | `POST /externalapi/PatientAppointments` | ✅ supported | ⚠️ unsafe (opt-in) | |
|
|
19
|
+
| `GetPatientAppointments` | `GET /externalapi/PatientAppointments/GetPatientAppointmentsByEligibleId/{eligibleId}` | ✅ supported | ✅ | |
|