@grammyjs/conversations
Version:
Conversational interfaces for grammY
170 lines (169 loc) • 6.22 kB
TypeScript
import type { Context } from "./deps.node.js";
/** Current data version of this plugin */
export declare const PLUGIN_DATA_VERSION = 0;
/**
* A value with a version.
*
* The version consists of two pieces.
*
* The first piece is a number that is defined by the plugin internally and
* cannot be changed. When the plugin is updated and it changes its internal
* data format, then it can use this part of the version to detect and
* automatically migrate the versioned state as necessary.
*
* The second piece is a number or a string and can be set by the developer. It
* should be changed whenever the application code changes in a way that
* invalidates the state. The plugin can then discard and re-create the state as
* necesarry.
*
* Versioned states are typically created via the {@link pinVersion} function.
*
* @typeParam S The type of the state to be versioned
*/
export interface VersionedState<S> {
/** The version of the state */
version: [typeof PLUGIN_DATA_VERSION, string | number];
/** The state to be versioned */
state: S;
}
/**
* A container for two functions that are pinned to a specific version. The two
* functions can be used to add the bound version to data, and to unpack the
* data again. This container is typically created using {@link pinVersion}.
*/
export interface PinnedVersion {
/**
* Adds a version to some data.
*
* @param state Some data
*/
versionify<S>(state: S): VersionedState<S>;
/**
* Unpacks some versioned data. Returns the original data if the data is
* correct, and `undefined` otherwise. If `undefined` is passed, then
* `undefined` will be returned.
*
* @param data Some versioned data or `undefined`
*/
unpack<S>(data?: VersionedState<S>): S | undefined;
}
/**
* Takes a version number and state management functions that are pinned to this
* version.
*
* The two functions it returns are `versionify` and `unpack`. The former can be
* used to add a version to some data. The latter can be used to unpack the data
* again, validating the version on the fly.
*
* ```ts
* import { assert } from "jsr:@std/assert";
*
* const { versionify, unpack } = pinVersion(42);
*
* const data = { prop: "pizza" };
* const versioned = versionify(data);
* const unpacked = unpack(versioned);
* assert(data === unpacked);
* ```
*
* @param version the version to use for pinning
*/
export declare function pinVersion(version: string | number): PinnedVersion;
/**
* A value or a promise of a value.
*
* @typeParam T The type of value
*/
export type MaybePromise<T> = T | Promise<T>;
/**
* A storage for versioned state.
*
* Specify this to define how to persist data.
*
* This type is a union of three types, each representing a different way to
* store data.
*
* 1. A {@link VersionedStateStorage} directly provides definitions for reading,
* writing, and deleting data based on `ctx.chatId`. No versions can be
* specified and the storage key function cannot be changed.
* 2. A {@link ConversationKeyStorage}, disambiguated via `{ type: "key" }`, is
* more general. It supports versioning the data and changing the storage key
* function.
* 3. A {@link ConversationContextStorage}, disambiguated via `{ type: "context"
* }`, is even more general. It no longer needs a storage key function.
* Instead, it provides read, write, and delete operations for data based on
* the context object directly. It also supports versioning data.
*
* @typeParam C A custom context type
* @typeParam S A type for the state to version and store
*/
export type ConversationStorage<C extends Context, S> = {
type?: never;
version?: never;
} & VersionedStateStorage<string, S> | ConversationContextStorage<C, S> | ConversationKeyStorage<C, S>;
/**
* An object that defines how to read, write, and delete versioned data based on
* a key.
*
* @typeParam K The type of key to use
* @typeParam S The type of data to store
*/
export interface VersionedStateStorage<K, S> {
/**
* Reads the data for a given key.
*
* @param key A key to identify the data
*/
read(key: K): MaybePromise<VersionedState<S> | undefined>;
/**
* Writes some data to the storage for a given key.
*
* @param key A key to identify the data
* @param state The data to write
*/
write(key: K, state: VersionedState<S>): MaybePromise<void>;
/**
* Deletes some data from the storage for a given key.
*
* @param key A key to identify the data
*/
delete(key: K): MaybePromise<void>;
}
/**
* An object that defines how to read, write, or delete versioned data based on
* a context object.
*/
export interface ConversationContextStorage<C extends Context, S> {
/** The type of storage, always `"context"` */
type: "context";
/** An optional version for the data, defaults to `0` */
version?: string | number;
/** The underlying storage that defines how to read and write raw data */
adapter: VersionedStateStorage<C, S>;
}
export interface ConversationKeyStorage<C extends Context, S> {
/** The type of storage, always `"key"` */
type: "key";
/** An optional version for the data, defaults to `0` */
version?: string | number;
/** An optional prefix to prepend to the storage key */
prefix?: string;
/** An optional storage key function, defaults to `ctx.chatId` */
getStorageKey?(ctx: C): string | undefined;
/** The underlying storage that defines how to read and write raw data */
adapter: VersionedStateStorage<string, S>;
}
/**
* Coerces different storages to a single uniform abstraction.
*
* This function takes a {@link ConversationStorage} object and unifies its
* union members behind a common abstraction that simply exposes a read, write,
* and delete method for a given context object.
*
* @param storage An object defining how to store data
*/
export declare function uniformStorage<C extends Context, S>(storage?: ConversationStorage<C, S>): (ctx: C) => {
read: () => MaybePromise<S | undefined>;
write: (state: S) => MaybePromise<void>;
delete: () => MaybePromise<void>;
};