npm package: @loqate/compose
Description: Loqate Compose SDK — high-level flows that compose base API clients into easy-to-use sessions.
Author: GBG Loqate
Latest version: 0.0.1-beta.19

# IN ALPHA - NOT CURRENTLY FOR RELEASE

<div align="left">
    <a href="https://opensource.org/licenses/MIT">
        <img src="https://img.shields.io/badge/License-MIT-blue.svg" style="width: 100px; height: 28px;" />
    </a>
</div>

# @loqate/compose

Compose is the "workflow" layer of Loqate: it strings together the repetitive steps you build every time (capture → select → verify) into simple, stateful sessions. Use it when you want a friendly, opinionated API that handles the plumbing so you can focus on your UX.

Sessions at a glance:
- **AddressSession**: capture suggestions, select an address, then verify it with AVC rules.
- **EmailSession**: validate individual emails or batches with a simple stateful API.
- **PhoneSession**: validate phone numbers with a lightweight, event-driven flow.
- **StoreFinderSession**: typeahead locations, retrieve details, and run nearby searches.

How it differs:
- **Core SDK**: low-level, request/response building blocks. Compose sits on top and coordinates them for you.
- **React SDK**: UI components/hooks. Compose is framework-agnostic and can be used in React, Vue, vanilla JS, or server-side flows.

Exports overview:
- Main package exports (`@loqate/compose`) are the session-based APIs that do the work.
- Utils exports (`@loqate/compose/utils`) are lightweight helpers (parsing, formatting, highlighting).
- These utilities are optional and can be combined with direct calls from the Core SDK.

---

## Install

```bash
npm i @loqate/compose
# or
pnpm add @loqate/compose
```

> Node 18+ (or modern bundlers/browsers) recommended.

## Quick start

### AddressSession

```ts
import { AddressSession } from "@loqate/compose";
import { avcParser } from "@loqate/compose/utils";

const session = new AddressSession({
  apiKey: process.env.LOQATE_API_KEY ?? "",
  language: "en",
});

// Event handler: react to suggestion updates
const unsubscribe = session.on("find:response", ({ items }) => {
  console.log("Suggestion count:", items.length);
});

// State slice subscription: keep a small UI model in sync
const unsubscribeSlice = session.subscribe(
  (state) => ({
    searchText: state.capture.find.searchText,
    lastItems: state.capture.find.items ?? [],
  }),
  (slice) => {
    console.log("Slice update:", slice);
  }
);

const suggestions = await session.find("10 downing st, london");
await session.select(suggestions[0]);

const verified = await session.verify();
console.log(verified?.composed?.[0]?.evaluation);

// Cleanup when done
unsubscribe();
unsubscribeSlice();
```

### EmailSession

```ts
import { EmailSession } from "@loqate/compose";

const session = new EmailSession({
  apiKey: process.env.LOQATE_API_KEY ?? "",
});

const unsubscribe = session.on("validate:response", ({ response }) => {
  console.log("Email checks:", response.length);
});

const results = await session.validate("user@example.com");
console.log(results[0]);

unsubscribe();
```

### PhoneSession

```ts
import { PhoneSession } from "@loqate/compose";

const session = new PhoneSession({
  apiKey: process.env.LOQATE_API_KEY ?? "",
});

const unsubscribe = session.on("validate:response", ({ response }) => {
  console.log("Phone checks:", response.length);
});

const results = await session.validate("+44 20 7946 0018");
console.log(results[0]);

unsubscribe();
```

### StoreFinderSession

```ts
import { StoreFinderSession } from "@loqate/compose";

const session = new StoreFinderSession({
  apiKey: process.env.LOQATE_API_KEY ?? "",
  nearby: {
    request: { locationListId: "YOUR_LOCATION_LIST_ID" },
  },
});

session.updateLocation(51.5033, -0.1195);

const unsubscribe = session.on("nearby:response", ({ response }) => {
  console.log("Nearby stores:", response?.destinationLocations?.length ?? 0);
});

await session.nearby();

unsubscribe();
```

---

### Utils

```ts
import { avcParser } from "@loqate/compose/utils";

const parsed = avcParser("AVC=R;DPV=Y;...");
// => structured object; tolerant to unknown tokens
```

## Design

- **AddressSession**: a lightweight stateful orchestrator exposing a friendly API.
- **Transport‑agnostic**: bring your own `fetch` if needed.
- **Tree‑shakeable**: `sideEffects: false`, ESM first with CJS fallback.
- **Typed**: full d.ts output.

You can inject real, generated clients later:

```ts
new AddressSession({ clients: { capture, verify } });
```

## License

MIT