# @babelfhir-ts/client-r5

[![npm](https://img.shields.io/npm/v/@babelfhir-ts/client-r5.svg)](https://www.npmjs.com/package/@babelfhir-ts/client-r5)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)

Typed FHIR R5 client with read/write/search methods for all 157 base resource types, SMART on FHIR auth, and bundle parsing.

## Installation

```bash
npm install @babelfhir-ts/client-r5
```

Peer dependency: `@types/fhir`

## Usage

### Read Client

```ts
import { FhirReadClient } from '@babelfhir-ts/client-r5';

const client = new FhirReadClient('https://hapi.fhir.org/baseR5');

// Typed read — returns fhir5.Patient
const patient = await client.patient().read('example');

// Search with parameters
const results = await client.observation().search({ subject: 'Patient/example' });

// Get first match
const condition = await client.condition().searchOne({ code: '73211009' });
```

### Write Client

```ts
import { FhirWriteClient } from '@babelfhir-ts/client-r5';

const client = new FhirWriteClient('https://hapi.fhir.org/baseR5');

await client.patient().create({ resourceType: 'Patient', name: [{ family: 'Smith' }] });
await client.patient().update({ resourceType: 'Patient', id: '123', active: true });
await client.patient().delete('123');
```

### Combined Client

```ts
import { FhirClient } from '@babelfhir-ts/client-r5';

const client = new FhirClient('https://hapi.fhir.org/baseR5');
// Has both read and write methods for all 157 resource types
```

### SMART on FHIR

```ts
import { SmartFhirClient } from '@babelfhir-ts/client-r5';

const client = new SmartFhirClient({
  clientId: 'my-app',
  redirectUri: 'http://localhost:3000/callback',
  scope: 'openid fhirUser patient/*.read',
  fhirBaseUrl: 'https://launch.smarthealthit.org/v/r5/fhir',
});

await client.authorize();
const patient = await client.patient().read('example');
```

### Bundle Parsing

```ts
import { BundleParser, hasId } from '@babelfhir-ts/client-r5';

// A searchset keeps the type the reader already knew.
const searchset = await client.read().patient().search({ name: 'Smith' }); // Bundle<WithId<fhir5.Patient>>
const all = BundleParser.getAllResources(searchset); // WithId<fhir5.Patient>[]

// On a mixed bundle the return type follows the resourceType argument — no type argument, no cast.
const patients = BundleParser.getResourcesByType(bundle, 'Patient'); // fhir5.Patient[]
const first = BundleParser.getFirstResourceByType(bundle, 'Observation'); // fhir5.Observation | undefined

// `id` is optional in FHIR, so narrow to it explicitly where it is required.
const identified = patients.filter(hasId); // WithId<fhir5.Patient>[]

// References resolve to the bundle's element type, or to a checked resourceType.
const subject = BundleParser.resolveReferenceOfType(obs.subject, bundle, 'Patient');
```

Pass an explicit type argument for profile types from other generated packages —
`resourceType` is then constrained to that type's own discriminant:

```ts
BundleParser.getResourcesByType<MyPatientProfile>(bundle, 'Patient');
```

### Migrating to 0.3

`BundleParser` no longer returns types it has not checked, so code written against
0.2 can see new compile errors:

- `getResourcesByType` and `getFirstResourceByType` return `T` instead of
  `WithId<T>`. `id` is optional in FHIR and was never verified, so add
  `.filter(hasId)` where the guarantee is needed.
- `resourceType` is checked against the FHIR resource type union, which turns a
  typo into a compile error. A value chosen at runtime should be typed
  `FhirResourceType` rather than `string`.
- `resolveReference` takes its return type from the bundle. To narrow a mixed
  bundle, call `resolveReferenceOfType(ref, bundle, 'Patient')`, which returns
  `undefined` when the reference resolves to another resource type.

## API

| Export | Description |
|---|---|
| `FhirReadClient` | 157 typed read/search accessors |
| `FhirWriteClient` | 157 typed create/update/delete accessors |
| `FhirClient` | Combined read + write client |
| `SmartFhirClient` | SMART-authenticated FHIR client |
| `BundleParser` | Static bundle extraction helpers |
| `hasId` | Type guard narrowing a resource to `WithId<T>` |
| `FhirResourceType` / `ResourceOfType` | The `resourceType` union, and the resource behind one of its members |
| `SmartAuth` | SMART on FHIR v2 authorization (re-exported from `@babelfhir-ts/smart-auth`) |
| `discoverEndpoints` | SMART endpoint discovery |

## Part of BabelFHIR-TS

This package is the R5 variant of the base client that [BabelFHIR-TS](https://github.com/Max-Health-Inc/BabelFHIR-TS)-generated profile clients extend. See also [@babelfhir-ts/client-r4](https://www.npmjs.com/package/@babelfhir-ts/client-r4) and [@babelfhir-ts/client-r4b](https://www.npmjs.com/package/@babelfhir-ts/client-r4b).

## License

MIT
