# Installation stores

> Where your app keeps each shop’s tokens and secrets.

Source: https://storeware.ai/docs/sdk/installations

```ts
import { ... } from '@storeware/plugin-sdk';
```

### installationFrom

A store's record from a fresh token response, keeping secrets it already held.

```ts
function installationFrom(tokens: StorewareTokens, previous: StoredInstallation | null, now?: number): StoredInstallation
```

### memoryInstallationStore

In memory, for tests and for trying things out. Gone when the process ends.

```ts
function memoryInstallationStore(): InstallationStore & { all(): StoredInstallation[]; }
```

### kvInstallationStore

One key per shop in a key-value store, such as Cloudflare KV.

```ts
function kvInstallationStore(kv: KeyValue, prefix?: string): InstallationStore
```

### StoredInstallation

| Name | Type | Description |
| --- | --- | --- |
| `storeId` | `string` |  |
| `installationId` | `string` |  |
| `accessToken` | `string` |  |
| `refreshToken` | `string` |  |
| `accessTokenExpiresAt` | `number` | Milliseconds since the epoch. |
| `scopes` | `string[]` |  |
| `webhookSecret` | `string` |  |
| `sessionSecret` | `string` |  |
| `installedAt` | `string` |  |
| `uninstalledAt?` | `string` | Set when `app.uninstalled.v1` arrives. The secrets stay for later privacy requests. |
| `lastGrant?` | `string` | The install grant last traded, so a redelivered `app.installed.v1` is not traded twice. |

### InstallationStore

| Name | Type | Description |
| --- | --- | --- |
| `get` | `(storeId: string) => Promise<StoredInstallation \| null>` |  |
| `save` | `(installation: StoredInstallation) => Promise<void>` |  |
| `delete` | `(storeId: string) => Promise<void>` |  |

### KeyValue

The part of a key-value store this needs. Cloudflare KV fits as it is.

| Name | Type | Description |
| --- | --- | --- |
| `get` | `(key: string) => Promise<string \| null>` |  |
| `put` | `(key: string, value: string) => Promise<void>` |  |
| `delete` | `(key: string) => Promise<void>` |  |
