UNPKG

@valkey/valkey-glide

Version:

General Language Independent Driver for the Enterprise (GLIDE) for Valkey

1,116 lines 323 kB
/** * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */ import * as net from "net"; import { Buffer, Writer } from "protobufjs/minimal"; import { AggregationType, BaseScanOptions, BitFieldGet, // eslint-disable-line @typescript-eslint/no-unused-vars BitFieldSubCommands, // eslint-disable-line @typescript-eslint/no-unused-vars BitOffsetOptions, BitwiseOperation, Boundary, ClientSideCache, CompressionConfiguration, ConnectionError, ExpireOptions, GeoAddOptions, // eslint-disable-line @typescript-eslint/no-unused-vars GeoSearchResultOptions, GeoSearchShape, GeoSearchStoreResultOptions, GeoUnit, GeospatialData, GlideClientConfiguration, GlideClusterClientConfiguration, HExpireOptions, HGetExOptions, HScanOptions, HSetExOptions, InsertPosition, KeyWeight, LPosOptions, ListDirection, RangeByIndex, RangeByLex, RangeByScore, RequestError, RestoreOptions, Routes, ScoreFilter, Script, SearchOrigin, SetOptions, SortOptions, StreamAddOptions, StreamClaimOptions, StreamGroupOptions, StreamPendingOptions, StreamReadGroupOptions, StreamReadOptions, StreamTrimOptions, TimeUnit, ValkeyError, ZAddOptions, ZScanOptions } from "."; import { command_request, connection_request, response } from "../build-ts/ProtobufMessage"; type PromiseFunction = (value?: any) => void; type ErrorFunction = (error: ValkeyError) => void; export type ReturnTypeRecord = { [key: string]: GlideReturnType; }; export type ReturnTypeMap = Map<string, GlideReturnType>; export interface ReturnTypeAttribute { value: GlideReturnType; attributes: ReturnTypeRecord; } export declare enum ProtocolVersion { /** Use RESP2 to communicate with the server nodes. */ RESP2 = 1, /** Use RESP3 to communicate with the server nodes. */ RESP3 = 0 } export type GlideReturnType = "OK" | string | number | null | boolean | bigint | Buffer | Set<GlideReturnType> | ReturnTypeRecord | ReturnTypeMap | ReturnTypeAttribute | RequestError | GlideReturnType[]; /** * Union type that can store either a valid UTF-8 string or array of bytes. */ export type GlideString = string | Buffer; /** * Enum representing the different types of decoders. */ export declare enum Decoder { /** * Decodes the response into a buffer array. */ Bytes = 0, /** * Decodes the response into a string. */ String = 1 } /** * An extension to command option types with {@link Decoder}. * * WARNING: * * Be aware that if decoding fails during a command execution (due to * invalid inputs, incorrect decoder), data COULD BE UNRECOVERABLY LOST. * * Use with caution. */ export interface DecoderOption { /** * {@link Decoder} type which defines how to handle the response. * If not set, the {@link BaseClientConfiguration.defaultDecoder|default decoder} will be used. */ decoder?: Decoder; } /** A replacement for `Record<GlideString, T>` - array of key-value pairs. */ export type GlideRecord<T> = { /** The value name. */ key: GlideString; /** The value itself. */ value: T; }[]; /** * Data type which represents sorted sets data, including elements and their respective scores. * Similar to `Record<GlideString, number>` - see {@link GlideRecord}. */ export type SortedSetDataType = { /** The sorted set element name. */ element: GlideString; /** The element score. */ score: number; }[]; /** * Data type which represents how data are returned from hashes or insterted there. * Similar to `Record<GlideString, GlideString>` - see {@link GlideRecord}. */ export type HashDataType = { /** The hash element name. */ field: GlideString; /** The hash element value. */ value: GlideString; }[]; /** * Data type which reflects now stream entries are returned. * The keys of the record are stream entry IDs, which are mapped to key-value pairs of the data. */ export type StreamEntryDataType = Record<string, [GlideString, GlideString][]>; /** * Union type that can store either a number or positive/negative infinity. */ export type Score = number | "+inf" | "-inf"; /** * Constant representing "all channels" for unsubscribe operations. * Use this to unsubscribe from all channel subscriptions at once. * * @example * ```typescript * await client.unsubscribeLazy(ALL_CHANNELS); * ``` */ export declare const ALL_CHANNELS: null; /** * Constant representing "all patterns" for punsubscribe operations. * Use this to unsubscribe from all pattern subscriptions at once. * * @example * ```typescript * await client.punsubscribeLazy(ALL_PATTERNS); * ``` */ export declare const ALL_PATTERNS: null; /** * Data type which represents sorted sets data for input parameter of ZADD command, * including element and its respective score. */ export type ElementAndScore = { /** The sorted set element name. */ element: GlideString; /** The element score. */ score: Score; }; /** Represents the return type of {@link xinfoStream} command. */ export type ReturnTypeXinfoStream = Record<string, StreamEntries | Record<string, StreamEntries | Record<string, StreamEntries>[]>[]>; /** * Represents an array of Stream Entires in the response of {@link xinfoStream} command. * See {@link ReturnTypeXinfoStream}. */ export type StreamEntries = GlideString | number | (GlideString | number | GlideString[])[][]; /** Represents the types of services that can be used for IAM authentication. */ export declare enum ServiceType { Elasticache = "Elasticache", MemoryDB = "MemoryDB" } /** Configuration settings for IAM authentication. */ export interface IamAuthConfig { /** The name of the ElastiCache/MemoryDB cluster. */ clusterName: string; /** The type of service being used (ElastiCache or MemoryDB). */ service: ServiceType; /** The AWS region where the ElastiCache/MemoryDB cluster is located. */ region: string; /** * Optional refresh interval in seconds for renewing IAM authentication tokens. * If not provided, defaults to 300 seconds (5 min). */ refreshIntervalSeconds?: number; } /** Represents the credentials for connecting to a server. */ export type ServerCredentials = { /** * The username that will be used for authenticating connections to the Valkey servers. * If not supplied, "default" will be used. */ username?: string; /** * The password that will be used for authenticating connections to the Valkey servers. * (mutually exclusive with iamConfig). */ password: string; } | { /** Username is REQUIRED for IAM (Valkey AUTH <username> <token>). */ username: string; /** * IAM config (mutually exclusive with password). * The client will automatically generate and refresh the authentication token based on the provided configuration. */ iamConfig: IamAuthConfig; }; /** Represents the client's read from strategy. */ export type ReadFrom = /** Always get from primary, in order to get the freshest data.*/ "primary" /** Spread the requests between all replicas in a round robin manner. If no replica is available, route the requests to the primary.*/ | "preferReplica" /** Spread the requests between replicas in the same client's Aviliablity zone in a round robin manner. If no replica is available, route the requests to the primary.*/ | "AZAffinity" /** Spread the read requests among all nodes within the client's Availability Zone (AZ) in a round robin manner, prioritizing local replicas, then the local primary, and falling back to any replica or the primary if needed.*/ | "AZAffinityReplicasAndPrimary" /** Spread the read requests between all nodes (primary and replicas) in a round robin manner.*/ | "allNodes"; /** * Controls how the client discovers node roles and topology in standalone mode. */ export declare enum NodeDiscoveryMode { /** Default: verify node roles via INFO REPLICATION, use only provided addresses. */ Standard = 0, /** Skip role detection entirely. Trust provided addresses as-is; first address is primary. * Use when connecting through a proxy (e.g., Envoy) or when the topology is known and static. * Note: Do not set `clientName` when using this mode with a proxy. */ Static = 1, /** Discover full topology (primary + all replicas) from any starting node. * Provide any single node address and the client will find and connect to all other nodes. */ DiscoverAll = 2 } /** * Configuration settings for creating a client. Shared settings for standalone and cluster clients. * * @remarks * The `BaseClientConfiguration` interface defines the foundational configuration options used when creating a client to connect to a Valkey server or cluster. It includes connection details, authentication, communication protocols, and various settings that influence the client's behavior and interaction with the server. * * ### Connection Details * * - **Addresses**: Use the `addresses` property to specify the hostnames and ports of the server(s) to connect to. * - **Cluster Mode**: In cluster mode, the client will discover other nodes based on the provided addresses. * - **Standalone Mode**: In standalone mode, only the provided nodes will be used. * - **Lazy Connect**: Set `lazyConnect` to `true` to defer connection establishment until the first command is sent. * * ### Database Selection * * - **Database ID**: Use `databaseId` to specify which logical database to connect to (0-15 by default). * - **Cluster Mode**: Requires Valkey 9.0+ with multi-database cluster mode enabled. * - **Standalone Mode**: Works with all Valkey versions. * - **Reconnection**: Database selection persists across reconnections. * * ### Security Settings * * - **TLS**: Enable secure communication using `useTLS`. * Should match the TLS configuration of the server/cluster, otherwise the connection attempt will fail. * For advanced tls configuration, , see {@link AdvancedBaseClientConfiguration}. * - **Authentication**: Provide `credentials` to authenticate with the server. * * ### Communication Settings * * - **Request Timeout**: Set `requestTimeout` to specify how long the client should wait for a request to complete. * - **Protocol Version**: Choose the serialization protocol using `protocol`. * * ### Client Identification * * - **Client Name**: Set `clientName` to identify the client connection. * * ### Read Strategy * * - Use `readFrom` to specify the client's read strategy (e.g., primary, preferReplica, AZAffinity, AZAffinityReplicasAndPrimary). * * ### Availability Zone * * - Use `clientAz` to specify the client's availability zone, which can influence read operations when using `readFrom: 'AZAffinity'or `readFrom: 'AZAffinityReplicasAndPrimary'`. * * ### Decoder Settings * * - **Default Decoder**: Set `defaultDecoder` to specify how responses are decoded by default. * * ### Concurrency Control * * - **Inflight Requests Limit**: Control the number of concurrent requests using `inflightRequestsLimit`. * * ### Reconnection Strategy * - **Reconnection Strategy**: Customize how the client should attempt reconnections using `connectionBackoff`. * - `numberOfRetries`: The maximum number of retry attempts with increasing delays. * - After this limit is reached, the retry interval becomes constant. * - `factor`: A multiplier applied to the base delay between retries, specified in milliseconds (e.g., `500` means a 500ms base delay). * - `exponentBase`: The exponential growth factor for delays (e.g., `2` means the delay doubles with each retry). * - `jitterPercent`: An optional percentage of jitter to add to the delay (e.g., `30` means the final delay will vary randomly between 70% and 130% of the calculated delay). * * @example * ```typescript * const config: BaseClientConfiguration = { * addresses: [ * { host: 'redis-node-1.example.com', port: 6379 }, * { host: 'redis-node-2.example.com' }, // Defaults to port 6379 * ], * databaseId: 5, // Connect to database 5 * useTLS: true, * credentials: { * username: 'myUser', * password: 'myPassword', * }, * requestTimeout: 5000, // 5 seconds * protocol: ProtocolVersion.RESP3, * clientName: 'myValkeyClient', * readFrom: ReadFrom.AZAffinity, * clientAz: 'us-east-1a', * defaultDecoder: Decoder.String, * inflightRequestsLimit: 1000, * connectionBackoff: { * numberOfRetries: 10, // Maximum retries before delay becomes constant * factor: 500, // Base delay in milliseconds * exponentBase: 2, // Delay doubles with each retry (2^N) * jitterPercent: 20, // Optional jitter percentage * }, * lazyConnect: true, * }; * ``` */ export interface BaseClientConfiguration { /** * DNS Addresses and ports of known nodes in the cluster. * If the server is in cluster mode the list can be partial, as the client will attempt to map out the cluster and find all nodes. * If the server is in standalone mode, only nodes whose addresses were provided will be used by the client. * * @example * ```typescript * configuration.addresses = * [ * { address: sample-address-0001.use1.cache.amazonaws.com, port:6378 }, * { address: sample-address-0002.use2.cache.amazonaws.com } * { address: sample-address-0003.use2.cache.amazonaws.com, port:6380 } * ] * ``` */ addresses: { host: string; /** * If port isn't supplied, 6379 will be used */ port?: number; }[]; /** * Index of the logical database to connect to. * * @remarks * - **Standalone Mode**: Works with all Valkey versions. * - **Cluster Mode**: Requires Valkey 9.0+ with multi-database cluster mode enabled. * - **Reconnection**: Database selection persists across reconnections. * - **Default**: If not specified, defaults to database 0. * - **Range**: Must be non-negative. The server will validate the upper limit based on its configuration. * - **Server Validation**: The server determines the maximum database ID based on its `databases` configuration (standalone) or `cluster-databases` configuration (cluster mode). * * @example * ```typescript * // Connect to database 5 * const config: BaseClientConfiguration = { * addresses: [{ host: 'localhost', port: 6379 }], * databaseId: 5 * }; * * // Connect to a higher database ID (server will validate the limit) * const configHighDb: BaseClientConfiguration = { * addresses: [{ host: 'localhost', port: 6379 }], * databaseId: 100 * }; * ``` */ databaseId?: number; /** * True if communication with the cluster should use Transport Level Security. * Should match the TLS configuration of the server/cluster, * otherwise the connection attempt will fail. */ useTLS?: boolean; /** * Credentials for authentication process. * If none are set, the client will not authenticate itself with the server. */ credentials?: ServerCredentials; /** * The duration in milliseconds that the client should wait for a request to complete. * This duration encompasses sending the request, awaiting for a response from the server, and any required reconnection or retries. * If the specified timeout is exceeded for a pending request, it will result in a timeout error. * If not explicitly set, a default value of 250 milliseconds will be used. * Value must be an integer. */ requestTimeout?: number; /** * The client's read from strategy. * If not set, `Primary` will be used. */ readFrom?: ReadFrom; /** * Serialization protocol to be used. * If not set, `RESP3` will be used. */ protocol?: ProtocolVersion; /** * Client name to be used for the client. Will be used with CLIENT SETNAME command during connection establishment. */ clientName?: string; /** * Default decoder when decoder is not set per command. * If not set, 'Decoder.String' will be used. */ defaultDecoder?: Decoder; /** * The maximum number of concurrent requests allowed to be in-flight (sent but not yet completed). * This limit is used to control the memory usage and prevent the client from overwhelming the * server or getting stuck in case of a queue backlog. If not set, a default value of 1000 will be * used. */ inflightRequestsLimit?: number; /** * Availability Zone of the client. * If ReadFrom strategy is AZAffinity or AZAffinityReplicasAndPrimary, this setting ensures that readonly commands are directed to nodes within the specified AZ if they exist. * * @example * ```typescript * // Example configuration for setting client availability zone and read strategy * configuration.clientAz = 'us-east-1a'; // Sets the client's availability zone * configuration.readFrom = 'AZAffinity'; // Directs read operations to nodes within the same AZ * Or * configuration.readFrom = 'AZAffinityReplicasAndPrimary'; // Directs read operations to any node (primary or replica) within the same AZ * ``` */ clientAz?: string; /** * Strategy used to determine how and when to reconnect, in case of connection failures. * The time between attempts grows exponentially, following the formula rand(0 ... factor * (exponentBase ^ N)), where N is the number of failed attempts, * and rand(...) applies a jitter of up to `jitterPercent`% to introduce randomness and reduce retry storms. * The client will attempt to reconnect indefinitely. Once the maximum value is reached, that will remain the time between retry attempts until a * reconnect attempt is successful. * If not set, a default backoff strategy will be used. */ connectionBackoff?: { /** * Number of retry attempts that the client should perform when disconnected from the server, where the time between retries increases. * Once the retries have reached the maximum value, the time between retries will remain constant until a reconnect attempt is succesful. * Value must be an integer. */ numberOfRetries: number; /** * The multiplier that will be applied to the waiting time between each retry. * This value is specified in milliseconds. * Value must be an integer. */ factor: number; /** * The exponent base configured for the strategy. * Value must be an integer. */ exponentBase: number; /** The Jitter percent on the calculated duration. * If not set, a default value will be used. * Value is optional, and must be an integer. */ jitterPercent?: number; }; /** * Enables lazy connection mode, where physical connections to the server(s) are deferred * until the first command is sent. This can reduce startup latency and allow for client * creation in disconnected environments. * * - **Default**: `false` – connections are established immediately during client creation. * * @remarks * When `lazyConnect` is set to `true`, the client will not attempt to connect to the specified * nodes during initialization. Instead, connections will be established only when a command is * actually executed. * * Note that the first command executed with lazy connections may experience additional latency * as it needs to establish the connection first. During this initial connection, the standard * request timeout does not apply yet - instead, the connection establishment is governed by * `AdvancedBaseClientConfiguration::connectionTimeout`. The request timeout (`requestTimeout`) * only begins counting after the connection has been successfully established. This behavior * can effectively increase the total time needed for the first command to complete. * * This setting applies to both standalone and cluster modes. Note that if an operation is * attempted and connection fails (e.g., unreachable nodes), errors will surface at that point. * * @example * ```typescript * const client = await GlideClient.createClient({ * addresses: [{ host: "localhost", port: 6379 }], * lazyConnect: true * }); * * // No connection is made yet * await client.ping(); // Now the client connects and sends the command * ``` */ lazyConnect?: boolean; /** * Configuration for automatic compression of values. * When enabled, values that meet the minimum size threshold will be * automatically compressed before being sent to the server and * decompressed when retrieved. * * @example * ```typescript * const client = await GlideClient.createClient({ * addresses: [{ host: "localhost", port: 6379 }], * compression: { enabled: true }, * }); * ``` */ compression?: CompressionConfiguration; /** * Client-side cache configuration. * * @remarks * When provided, enables client-side caching for cacheable commands (GET, HGETALL, SMEMBERS). * The cache reduces network round-trips and server load by storing frequently accessed data locally. * * - **Memory Management**: The cache respects the configured memory limit and evicts entries based on the specified policy. * - **TTL Support**: Entries can have optional time-to-live values for automatic expiration. * - **Shared Caches**: Multiple clients can share the same cache instance using the same cache ID. * - **Metrics**: Optional metrics collection provides insights into cache performance. * * @example * ```typescript * // Simple cache configuration * const config: BaseClientConfiguration = { * addresses: [{ host: 'localhost', port: 6379 }], * clientSideCache: ClientSideCache.create(1024, 0), // 1MB cache, no TTL * }; * * // Advanced cache configuration * const advancedConfig: BaseClientConfiguration = { * addresses: [{ host: 'localhost', port: 6379 }], * clientSideCache: new ClientSideCache({ * maxCacheKb: 2048, * entryTtlMs: 300000, * evictionPolicy: EvictionPolicy.LFU, * enableMetrics: true, * }), * }; * ``` */ clientSideCache?: ClientSideCache; } /** * Represents advanced configuration settings for a client, including connection-related options. * * @remarks * The `AdvancedBaseClientConfiguration` interface defines advanced configuration settings for managing the client's connection behavior. * * ### Connection Timeout * * - **Connection Timeout**: The `connectionTimeout` property specifies the duration (in milliseconds) the client should wait for a connection to be established. * * ### TLS config * * - **TLS Configuration**: The `tlsAdvancedConfiguration` property allows for advanced TLS settings, such as enabling insecure mode. * * @example * ```typescript * const config: AdvancedBaseClientConfiguration = { * connectionTimeout: 5000, // 5 seconds * }; * ``` */ export interface AdvancedBaseClientConfiguration { /** * The duration in milliseconds to wait for a TCP/TLS connection to complete. * This applies both during initial client creation and any reconnection that may occur during request processing. * **Note**: A high connection timeout may lead to prolonged blocking of the entire command pipeline. * If not explicitly set, a default value of 2000 milliseconds will be used. */ connectionTimeout?: number; /** * The advanced TLS configuration settings. This allows for more granular control of TLS behavior, * such as enabling an insecure mode that bypasses certificate validation. */ tlsAdvancedConfiguration?: { /** * Whether to bypass TLS certificate verification. * * - When set to `true`, the client skips certificate validation. * This is useful when connecting to servers or clusters using self-signed certificates, * or when DNS entries (e.g., CNAMEs) don't match certificate hostnames. * * - This setting is typically used in development or testing environments. * **It is strongly discouraged in production**, as it introduces security risks such as man-in-the-middle attacks. * * - Only valid if TLS is already enabled in the base client configuration. * Enabling it without TLS will result in a `ConfigurationError`. * * - Default: false (verification is enforced). */ insecure?: boolean; /** * Custom root certificate data for TLS connections. * * - When provided, these certificates will be used instead of the system's default trust store. * If not provided, the system's default certificate trust store will be used. * * - The certificate data should be in PEM format as a string or Buffer. * * - This is useful when connecting to servers with self-signed certificates or custom certificate authorities. */ rootCertificates?: string | Buffer; }; /** * Controls TCP_NODELAY socket option (Nagle's algorithm). * * - When `true`, disables Nagle's algorithm for lower latency by sending packets immediately without buffering. * This is optimal for Redis/Valkey workloads with many small requests. * * - When `false`, enables Nagle's algorithm to reduce network overhead by buffering small packets. * This may increase latency by up to 200ms but reduces the number of packets sent. * * - If not explicitly set, a default value of `true` will be used by the Rust core. */ tcpNoDelay?: boolean; /** * The interval in milliseconds between PubSub subscription reconciliation attempts. * * The reconciliation process ensures that the client's desired subscriptions match * the actual subscriptions on the server. This is useful when subscriptions may have * been lost due to network issues or server restarts. * * If not explicitly set, the Rust core will use its default reconciliation interval. * * @remarks * - Must be a positive integer representing milliseconds. * - The reconciliation process runs automatically in the background. * - A lower interval provides faster recovery from subscription issues but increases overhead. * - A higher interval reduces overhead but may delay recovery from subscription issues. * * @example * ```typescript * const config: GlideClientConfiguration = { * addresses: [{ host: "localhost", port: 6379 }], * advancedConfiguration: { * pubsubReconciliationIntervalMs: 5000 // Reconcile every 5 seconds * } * }; * ``` */ pubsubReconciliationIntervalMs?: number; } /** * Enum of Valkey data types * `STRING` * `LIST` * `SET` * `ZSET` * `HASH` * `STREAM` */ export declare enum ObjectType { STRING = "String", LIST = "List", SET = "Set", ZSET = "ZSet", HASH = "Hash", STREAM = "Stream" } export interface PubSubMsg { message: GlideString; channel: GlideString; pattern?: GlideString | null; } /** * Base client interface for GLIDE */ export declare class BaseClient { private socket; protected readonly promiseCallbackFunctions: [PromiseFunction, ErrorFunction, Decoder | undefined][] | [PromiseFunction, ErrorFunction][]; private readonly availableCallbackSlots; private requestWriter; private writeInProgress; private remainingReadData; private readonly requestTimeout; protected isClosed: boolean; protected defaultDecoder: Decoder; private readonly pubsubFutures; private pendingPushNotification; private readonly inflightRequestsLimit; private config; protected configurePubsub(options: GlideClusterClientConfiguration | GlideClientConfiguration, configuration: connection_request.IConnectionRequest): void; private handleReadData; protected toProtobufRoute(route: Routes | undefined): command_request.Routes | undefined; private dropCommandSpan; processResponse(message: response.Response): void; processPush(response: response.Response): void; protected constructor(socket: net.Socket, options?: BaseClientConfiguration); protected getCallbackIndex(): number; private writeBufferedRequestsToSocket; protected ensureClientIsOpen(): void; protected createUpdateConnectionPasswordPromise(command: command_request.UpdateConnectionPassword): Promise<GlideString>; protected createRefreshIamTokenPromise(command: command_request.RefreshIamToken): Promise<GlideString>; protected createGetCacheMetricsPromise(command: command_request.GetCacheMetrics): Promise<number>; protected createScriptInvocationPromise<T = GlideString>(command: command_request.ScriptInvocation, options?: { keys?: GlideString[]; args?: GlideString[]; } & DecoderOption): Promise<T>; protected writeOrBufferRequest<TRequest>(message: TRequest, encodeDelimited: (message: TRequest, writer: Writer) => void): void; cancelPubSubFuturesWithExceptionSafe(exception: ConnectionError): void; isPubsubConfigured(config: GlideClientConfiguration | GlideClusterClientConfiguration): boolean; getPubsubCallbackAndContext(config: GlideClientConfiguration | GlideClusterClientConfiguration): [((msg: PubSubMsg, context: any) => void) | null | undefined, any]; getPubSubMessage(): Promise<PubSubMsg>; tryGetPubSubMessage(decoder?: Decoder): PubSubMsg | null; notificationToPubSubMessageSafe(pushNotification: response.Response, decoder?: Decoder): PubSubMsg | null; completePubSubFuturesSafe(): void; /** Get the value associated with the given `key`, or `null` if no such `key` exists. * * @see {@link https://valkey.io/commands/get/|valkey.io} for details. * * @param key - The `key` to retrieve from the database. * @param options - (Optional) See {@link DecoderOption}. * @returns If `key` exists, returns the value of `key`. Otherwise, return `null`. * * @example * ```typescript * // Example usage of get method to retrieve the value of a key * const result = await client.get("key"); * console.log(result); * // Output: 'value' * * // Example usage of get method to retrieve the value of a key with Bytes decoder * const result = await client.get("key", { decoder: Decoder.Bytes }); * console.log(result); * // Output: <Buffer 76 61 6c 75 65> * ``` */ get(key: GlideString, options?: DecoderOption): Promise<GlideString | null>; /** * Get the value of `key` and optionally set its expiration. `GETEX` is similar to {@link get}. * * @see {@link https://valkey.io/commands/getex/|valkey.op} for more details. * @remarks Since Valkey version 6.2.0. * * @param key - The key to retrieve from the database. * @param options - (Optional) Additional Parameters: * - (Optional) `expiry`: expiriation to the given key: * `"persist"` will retain the time to live associated with the key. Equivalent to `PERSIST` in the VALKEY API. * Otherwise, a {@link TimeUnit} and duration of the expire time should be specified. * - (Optional) `decoder`: see {@link DecoderOption}. * @returns If `key` exists, returns the value of `key` as a `string`. Otherwise, return `null`. * * @example * ```typescript * const result = await client.getex("key", {expiry: { type: TimeUnit.Seconds, count: 5 }}); * console.log(result); * // Output: 'value' * ``` */ getex(key: GlideString, options?: { expiry: "persist" | { type: TimeUnit; duration: number; }; } & DecoderOption): Promise<GlideString | null>; /** * Gets a string value associated with the given `key`and deletes the key. * * @see {@link https://valkey.io/commands/getdel/|valkey.io} for details. * * @param key - The key to retrieve from the database. * @param options - (Optional) See {@link DecoderOption}. * @returns If `key` exists, returns the `value` of `key`. Otherwise, return `null`. * * @example * ```typescript * const result = client.getdel("key"); * console.log(result); * // Output: 'value' * * const value = client.getdel("key"); // value is null * ``` */ getdel(key: GlideString, options?: DecoderOption): Promise<GlideString | null>; /** * Returns the substring of the string value stored at `key`, determined by the byte offsets * `start` and `end` (both are inclusive). Negative offsets can be used in order to provide * an offset starting from the end of the string. So `-1` means the last character, `-2` the * penultimate and so forth. If `key` does not exist, an empty string is returned. If `start` * or `end` are out of range, returns the substring within the valid range of the string. * * @see {@link https://valkey.io/commands/getrange/|valkey.io} for details. * * @param key - The key of the string. * @param start - The starting byte offset. * @param end - The ending byte offset. * @param options - (Optional) See {@link DecoderOption}. * @returns A substring extracted from the value stored at `key`. * * @example * ```typescript * await client.set("mykey", "This is a string") * let result = await client.getrange("mykey", 0, 3) * console.log(result); * // Output: "This" * * result = await client.getrange("mykey", -3, -1) * console.log(result); * // Output: "ing" * // extracted last 3 characters of a string * * result = await client.getrange("mykey", 0, 100) * console.log(result); * // Output: "This is a string" * * result = await client.getrange("mykey", 5, 6) * console.log(result); * // Output: "" * ``` */ getrange(key: GlideString, start: number, end: number, options?: DecoderOption): Promise<GlideString | null>; /** Set the given key with the given value. Return value is dependent on the passed options. * * @see {@link https://valkey.io/commands/set/|valkey.io} for details. * * @param key - The key to store. * @param value - The value to store with the given key. * @param options - (Optional) See {@link SetOptions} and {@link DecoderOption}. * @returns - If the value is successfully set, return OK. * If `conditional` in `options` is not set, the value will be set regardless of prior value existence. * If value isn't set because of `onlyIfExists` or `onlyIfDoesNotExist` or `onlyIfEqual` conditions, return `null`. * If `returnOldValue` is set, return the old value as a string. * * @example * ```typescript * // Example usage of set method to set a key-value pair * const result = await client.set("my_key", "my_value"); * console.log(result); // Output: 'OK' * * // Example usage of set method with conditional options and expiration * const result2 = await client.set("key", "new_value", {conditionalSet: "onlyIfExists", expiry: { type: TimeUnit.Seconds, count: 5 }}); * console.log(result2); * // Output: 'OK' * // Set "new_value" to `key" only if `key` already exists, and set the key expiration to 5 seconds. * * // Example usage of set method with conditional options and returning old value * const result3 = await client.set("key", "value", {conditionalSet: "onlyIfDoesNotExist", returnOldValue: true}); * console.log(result3); * // Output: 'new_value' * // Returns the old value of `key`. * * // Example usage of get method to retrieve the value of a key * const result4 = await client.get("key"); * console.log(result4); * // Output: 'new_value' * // Value wasn't modified back to being "value" because of "NX" flag. * * // Example usage of set method with conditional option IFEQ * await client.set("key", "value we will compare to"); * const result5 = await client.set("key", "new_value", {conditionalSet: "onlyIfEqual", comparisonValue: "value we will compare to"}); * console.log(result5); * // Output: 'OK' * // Set "new_value" to "key" only if comparisonValue is equal to the current value of "key". * * const result6 = await client.set("key", "another_new_value", {conditionalSet: "onlyIfEqual", comparisonValue: "value we will compare to"}); * console.log(result6); * // Output: null * // Value wasn't set because the comparisonValue is not equal to the current value of `key`. Value of `key` remains "new_value". * ``` */ set(key: GlideString, value: GlideString, options?: SetOptions & DecoderOption): Promise<"OK" | GlideString | null>; /** * Removes the specified keys. A key is ignored if it does not exist. * * @see {@link https://valkey.io/commands/del/|valkey.io} for details. * * @remarks In cluster mode, if keys in `keys` map to different hash slots, * the command will be split across these slots and executed separately for each. * This means the command is atomic only at the slot level. If one or more slot-specific * requests fail, the entire call will return the first encountered error, even * though some requests may have succeeded while others did not. * If this behavior impacts your application logic, consider splitting the * request into sub-requests per slot to ensure atomicity. * * @param keys - The keys we wanted to remove. * @returns The number of keys that were removed. * * @example * ```typescript * // Example usage of del method to delete an existing key * await client.set("my_key", "my_value"); * const result = await client.del(["my_key"]); * console.log(result); // Output: 1 * ``` * * @example * ```typescript * // Example usage of del method for a non-existing key * const result = await client.del(["non_existing_key"]); * console.log(result); // Output: 0 * ``` */ del(keys: GlideString[]): Promise<number>; /** * Serialize the value stored at `key` in a Valkey-specific format and return it to the user. * * @see {@link https://valkey.io/commands/dump/|valkey.io} for details. * * @param key - The `key` to serialize. * @returns The serialized value of the data stored at `key`. If `key` does not exist, `null` will be returned. * * @example * ```typescript * let result = await client.dump("myKey"); * console.log(result); * // Result contains the serialized value of `myKey` * ``` * * @example * ```typescript * result = await client.dump("nonExistingKey"); * console.log(result); * // Output: null * ``` */ dump(key: GlideString): Promise<Buffer | null>; /** * Create a `key` associated with a `value` that is obtained by deserializing the provided * serialized `value` (obtained via {@link dump}). * * @see {@link https://valkey.io/commands/restore/|valkey.io} for details. * @remarks `options.idletime` and `options.frequency` modifiers cannot be set at the same time. * * @param key - The `key` to create. * @param ttl - The expiry time (in milliseconds). If `0`, the `key` will persist. * @param value - The serialized value to deserialize and assign to `key`. * @param options - (Optional) Restore options {@link RestoreOptions}. * @returns Return "OK" if the `key` was successfully restored with a `value`. * * @example * ```typescript * const result = await client.restore("myKey", 0, value); * console.log(result); // Output: "OK" * ``` * * @example * ```typescript * const result = await client.restore("myKey", 1000, value, {replace: true, absttl: true}); * console.log(result); // Output: "OK" * ``` * * @example * ```typescript * const result = await client.restore("myKey", 0, value, {replace: true, idletime: 10}); * console.log(result); // Output: "OK" * ``` * * @example * ```typescript * const result = await client.restore("myKey", 0, value, {replace: true, frequency: 10}); * console.log(result); // Output: "OK" * ``` */ restore(key: GlideString, ttl: number, value: Buffer, options?: RestoreOptions): Promise<"OK">; /** Retrieve the values of multiple keys. * * @see {@link https://valkey.io/commands/mget/|valkey.io} for details. * * @remarks In cluster mode, if keys in `keys` map to different hash slots, * the command will be split across these slots and executed separately for each. * This means the command is atomic only at the slot level. If one or more slot-specific * requests fail, the entire call will return the first encountered error, even * though some requests may have succeeded while others did not. * If this behavior impacts your application logic, consider splitting the * request into sub-requests per slot to ensure atomicity. * * @param keys - A list of keys to retrieve values for. * @param options - (Optional) See {@link DecoderOption}. * @returns A list of values corresponding to the provided keys. If a key is not found, * its corresponding value in the list will be null. * * @example * ```typescript * // Example usage of mget method to retrieve values of multiple keys * await client.set("key1", "value1"); * await client.set("key2", "value2"); * const result = await client.mget(["key1", "key2"]); * console.log(result); * // Output: ['value1', 'value2'] * ``` */ mget(keys: GlideString[], options?: DecoderOption): Promise<(GlideString | null)[]>; /** Set multiple keys to multiple values in a single operation. * * @see {@link https://valkey.io/commands/mset/|valkey.io} for details. * * @remarks In cluster mode, if keys in `keyValueMap` map to different hash slots, * the command will be split across these slots and executed separately for each. * This means the command is atomic only at the slot level. If one or more slot-specific * requests fail, the entire call will return the first encountered error, even * though some requests may have succeeded while others did not. * If this behavior impacts your application logic, consider splitting the * request into sub-requests per slot to ensure atomicity. * * @param keysAndValues - A list of key-value pairs to set. * * @returns A simple "OK" response. * * @example * ```typescript * // Example usage of mset method to set values for multiple keys * const result = await client.mset({"key1": "value1", "key2": "value2"}); * console.log(result); // Output: 'OK' * ``` * * @example * ```typescript * // Example usage of mset method to set values for multiple keys (GlideRecords allow binary data in the key) * const result = await client.mset([{key: "key1", value: "value1"}, {key: "key2", value: "value2"}]); * console.log(result); // Output: 'OK' * ``` */ mset(keysAndValues: Record<string, GlideString> | GlideRecord<GlideString>): Promise<"OK">; /** * Sets multiple keys to values if the key does not exist. The operation is atomic, and if one or * more keys already exist, the entire operation fails. * * @see {@link https://valkey.io/commands/msetnx/|valkey.io} for more details. * @remarks When in cluster mode, all keys in `keyValueMap` must map to the same hash slot. * * @param keysAndValues - A list of key-value pairs to set. * @returns `true` if all keys were set. `false` if no key was set. * * @example * ```typescript * const result1 = await client.msetnx({"key1": "value1", "key2": "value2"}); * console.log(result1); // Output: `true` * * const result2 = await client.msetnx({"key2": "value4", "key3": "value5"}); * console.log(result2); // Output: `false` * ``` */ msetnx(keysAndValues: Record<string, GlideString> | GlideRecord<GlideString>): Promise<boolean>; /** * Move `key` from the currently selected database to the database specified by `dbIndex`. * * @remarks Move is available for cluster mode since Valkey 9.0.0 and above. * * @see {@link https://valkey.io/commands/move/|valkey.io} for more details. * * @param key - The key to move. * @param dbIndex - The index of the database to move `key` to. * @returns `true` if `key` was moved, or `false` if the `key` already exists in the destination * database or does not exist in the source database. * * @example * ```typescript * const result = await client.move("key", 1); * console.log(result); // Output: true * ``` */ move(key: GlideString, dbIndex: number): Promise<boolean>; /** Increments the number stored at `key` by one. If `key` does not exist, it is set to 0 before performing the operation. * * @see {@link https://valkey.io/commands/incr/|valkey.io} for details. * * @param key - The key to increment its value. * @returns the value of `key` after the increment. * * @example * ```typescript * // Example usage of incr method to increment the value of a key * await client.set("my_counter", "10"); * const result = await client.incr("my_counter"); * console.log(result); // Output: 11 * ``` */ incr(key: GlideString): Promise<number>; /** Increments the number stored at `key` by `amount`. If `key` does not exist, it is set to 0 before performing the operation. * * @see {@link https://valkey.io/commands/incrby/|valkey.io} for details. * * @param key - The key to increment its value. * @param amount - The amount to increment. * @returns the value of `key` after the increment. * * @example * ```typescript * // Example usage of incrBy method to increment the value of a key by a specified amount * await client.set("my_counter", "10"); * const result = await client.incrBy("my_counter", 5); * console.log(result); // Output: 15 * ``` */ incrBy(key: GlideString, amount: number): Promise<number>; /** Increment the string representing a floating point number stored at `key` by `amount`. * By using a negative increment value, the result is that the value stored at `key` is decremented. * If `key` does not exist, it is set to 0 before performing the operation. * * @see {@link https://valkey.io/commands/incrbyfloat/|valkey.io} for details. * * @param key - The key to increment its value. * @param amount - The amount to increment. * @returns the value of `key` after the increment. * * @example * ```typescript * // Example usage of incrByFloat method to increment the value of a floating point key by a specified amount * await client.set("my_float_counter", "10.5"); * const result = await client.incrByFloat("my_float_counter", 2.5); * console.log(result); // Output: 13.0 * ``` */ incrByFloat(key: GlideString, amount: number): Promise<number>; /** * Copies the value stored at the `source` to the `destination` key. If `destinationDB` is specified, * the value will be copied to the database specified, otherwise the current database will be used. * When `replace` is true, removes the `destination` key first if it already exists, otherwise performs * no action. * * @see {@link https://valkey.io/commands/copy/|valkey.io} for more details. * @remarks Since Valkey version 6.2.0. destinationDB parameter for cluster mode is supported since Valkey 9.0.0 and above * * @param source - The key to the source value. * @param destination - The key where the value should be copied to. * @param options - (Optional) Additional parameters: * - (Optional) `destinationDB`: the alternative logical database index for the destination key. * If not provided, the current database will be used. * - (Optional) `replace`: if `true`, the `destination` key should be removed before copying the * value to it. If not provided, no action will be performed if the key already exists. * @returns `true` if `source` was copied, `false` if the `source` was not copied. * * @example * ```typescript * const result = await client.copy("set1", "set2"); * console.log(result); // Output: true - "set1" was copied to "set2". * ``` * ```typescript * const result = await client.copy("set1", "set2", { replace: true }); * console.log(result); // Output: true - "set1" was copied to "set2". * ``` * ```typescript * const result = await client.copy("set1", "set2", { destinationDB: 1, replace: false }); * console.log(result); // Output: true - "set1" was copied to "set2". * ``` */ copy(source: GlideString, destination: GlideString, options?: { destinationDB?: number; replace?: boolean; }): Promise<bool