componentized/directory

componentized:valkey

interface dev

A WASM component client for Valkey (and Redis).

Interfaces

  • tcp-connector-constants since 0.3.0-dev — The keys of the `tcp-connector`'s wasi:config, and their defaults, for the components that derive their config from it. The values are provided by the `tcp-connector-constants` component.
  • types — The types of the package's interfaces, their stable public names.
  • connection — RESP request/reply over a pair of value streams, independent of the transport carrying them.
  • commands — Typed functions for Valkey's commands, over the mechanics of a connection.
  • connector since 0.3.0-dev — Establishes connections, with a transport and settings chosen by whoever provides it, e.g. from configuration.
  • tcp — A transport for connections over wasi:sockets TCP.

Worlds

WIT

package componentized:valkey@0.3.0-dev;

/// The keys of the `tcp-connector`'s wasi:config, and their defaults, for the components that derive
/// their config from it. The values are provided by the `tcp-connector-constants` component.
@since(version = 0.3.0-dev)
interface tcp-connector-constants {
  /// The key of the server's hostname or IP address.
  ///
  /// @value "hostname"
  @since(version = 0.3.0-dev)
  hostname-key: func() -> string;

  /// The server's hostname or IP address without one.
  ///
  /// @value "127.0.0.1"
  @since(version = 0.3.0-dev)
  hostname-default: func() -> string;

  /// The key of the server's port.
  ///
  /// @value "port"
  @since(version = 0.3.0-dev)
  port-key: func() -> string;

  /// The server's port without one.
  ///
  /// @value 6379
  @since(version = 0.3.0-dev)
  port-default: func() -> u16;

  /// The key of the user to authenticate as, with a password.
  ///
  /// @value "username"
  @since(version = 0.3.0-dev)
  username-key: func() -> string;

  /// The user to authenticate as without one.
  ///
  /// @value "default"
  @since(version = 0.3.0-dev)
  username-default: func() -> string;

  /// The key of the password, authenticating when set.
  ///
  /// @value "password"
  @since(version = 0.3.0-dev)
  password-key: func() -> string;

  /// The key of the connection's name, see `CLIENT SETNAME`.
  ///
  /// @value "client-name"
  @since(version = 0.3.0-dev)
  client-name-key: func() -> string;

  /// The key of the milliseconds idle before a `PING`, disabled when unset or `0`.
  ///
  /// @value "keep-alive-interval-ms"
  @since(version = 0.3.0-dev)
  keep-alive-interval-ms-key: func() -> string;
}

/// The types of the package's interfaces, their stable public names.
///
/// The other interfaces use these types under names of their own, which may change, e.g. renamed
/// to avoid clashing with a function for a new command. Refer to a type through this interface for
/// a name that does not change.
interface types {
  /// resp
  /// An encoding error, converting RESP values to or from bytes.
  @since(version = 0.3.0-dev)
  type resp-error = string;

  @since(version = 0.3.0-dev)
  type integer = s64;

  @since(version = 0.3.0-dev)
  type double = f64;

  /// Raw bytes, e.g. a bulk string, which Valkey keeps as given, UTF-8 or not.
  @since(version = 0.3.0-dev)
  type bytes = list<u8>;

  @since(version = 0.3.0-dev)
  variant string-or-bytes {
    /// utf-8 decoded bytes.
    %string(string),
    /// bytes that cannot be represented as a utf-8 string.
    bytes(bytes),
  }

  /// Values nested within an aggregate type. Since WIT types are not allowed to depend on
  /// themselves, nested values are stored as encoded RESP.
  @since(version = 0.3.0-dev)
  type resp-nested-value = list<u8>;

  @since(version = 0.3.0-dev)
  variant resp-value {
    %string(string),
    error(string),
    integer(integer),
    bulk-string(bytes),
    array(list<resp-nested-value>),
    null,
    boolean(bool),
    double(double),
    big-number(string),
    bulk-error(bytes),
    verbatim-string(tuple<string, string>),
    %map(list<tuple<resp-nested-value, resp-nested-value>>),
    set(list<resp-nested-value>),
    push(list<resp-nested-value>),
  }

  /// connection
  /// The errors of a connection and of every command interface.
  @since(version = 0.3.0-dev)
  variant error-code {
    /// The transport closed while a reply was outstanding, or before the command was sent. Holds
    /// the transport's error when it did not close gracefully.
    closed(option<string>),
    /// Client errors are semantic issues with input/output values, e.g. a reply that does not
    /// have the shape the command expects.
    client(string),
    /// RESP errors are encoding issues converting values to/from bytes.
    resp(resp-error),
    /// Server errors are Error or BulkError RESP values returned directly from the server. An Error
    /// is a string, a BulkError a string when it is UTF-8, bytes otherwise.
    server(string-or-bytes),
    /// The reader of a stream fell too far behind and its stream was closed, rather than
    /// holding up the connection. What the stream missed is lost.
    lagged,
  }

  /// What a subscription is subscribed to, see `connection.subscription`.
  @since(version = 0.3.0-dev)
  variant subscription-target {
    /// A channel, see SUBSCRIBE.
    channel(string),
    /// A pattern of channels, see PSUBSCRIBE.
    pattern(string),
    /// A shard channel, see SSUBSCRIBE.
    shardchannel(string),
  }

  /// A message published to a channel.
  ///
  /// A subscription with overlapping targets, e.g. a channel and a pattern matching it, receives
  /// a message once for each target.
  @since(version = 0.3.0-dev)
  record subscription-message {
    /// The message as published, UTF-8 or not.
    payload: string-or-bytes,
    /// The channel the message was published to: a channel, published with PUBLISH, or a shard
    /// channel, published with SPUBLISH. Channels and shard channels are separate, a channel
    /// and a shard channel of the same name are not the same. `target` tells them apart, a
    /// `shardchannel` target for a shard channel, a `channel` or `pattern` target otherwise.
    channel: string,
    /// The subscription's target that matched the channel, the channel itself, or a pattern
    /// matching it.
    target: subscription-target,
  }

  /// Why a target is no longer subscribed to.
  @since(version = 0.3.0-dev)
  enum unsubscribe-reason {
    /// By the subscription, e.g. its `unsubscribe`.
    requested,
    /// By the server on its own, e.g. the slot of a shard channel moved to another node.
    by-server,
    /// By `connection.reset`.
    reset,
  }

  /// What a subscription's stream carries, in the order it happened.
  @since(version = 0.3.0-dev)
  variant subscription-event {
    /// The server confirmed the target, its messages may arrive from now on.
    subscribed(subscription-target),
    /// The target is no longer subscribed to, none of its messages arrive after this.
    unsubscribed(tuple<subscription-target, unsubscribe-reason>),
    message(subscription-message),
  }

  /// shared by the commands
  /// A duration in whole seconds, e.g. `EX seconds`.
  @since(version = 0.3.0-dev)
  record duration-seconds {
    ex: u64,
  }

  /// A duration in whole milliseconds, e.g. `PX milliseconds`.
  @since(version = 0.3.0-dev)
  record duration-milliseconds {
    px: u64,
  }

  /// Options for establishing a connection.
  @since(version = 0.3.0-dev)
  record connect-opts {
    /// The username and password to authenticate with.
    auth: option<tuple<string, string>>,
    /// The name of the connection, see `CLIENT SETNAME`.
    client-name: option<string>,
    /// Enables keep-alive pings at this interval, see `connection.set-keep-alive`.
    keep-alive-interval: option<duration-milliseconds>,
  }

  /// A point in time as whole seconds since the Unix epoch, e.g. `EXAT unix-time-seconds`.
  @since(version = 0.3.0-dev)
  record unix-time-seconds {
    exat: s64,
  }

  /// A point in time as whole milliseconds since the Unix epoch, e.g. `PXAT
  /// unix-time-milliseconds`.
  @since(version = 0.3.0-dev)
  record unix-time-milliseconds {
    pxat: s64,
  }

  /// Where an incremental iteration continues from, e.g. with HSCAN.
  ///
  /// A scan returns the cursor to resume from, always `resume`, none once the scan is complete.
  /// Pass it to the next call until then.
  @since(version = 0.3.0-dev)
  variant cursor {
    /// Starts a new scan, the cursor `0`.
    start,
    /// Continues a scan from the opaque cursor the previous call returned, `0` fails with a client
    /// error, use `start`.
    resume(string),
  }

  /// The condition for setting an expiration, e.g. with EXPIRE or HEXPIRE.
  @since(version = 0.3.0-dev)
  enum ttl-mode {
    /// Set expiration only when the field has no expiration.
    nx,
    /// Set expiration only when the field has an existing expiration.
    xx,
    /// Set expiration only when the new expiration is greater than current one.
    gt,
    /// Set expiration only when the new expiration is less than current one.
    lt,
  }

  /// The remaining time to live of a key or hash field, to the second, see `ttl` and `httl`.
  @since(version = 0.3.0-dev)
  variant ttl-reply {
    /// -2: the key does not exist, or for a hash field, the field or the hash does not exist.
    does-not-exist,
    /// -1: the key or field exists, but has no expiration.
    no-expiration,
    /// The time until it expires.
    expires-in(duration-seconds),
  }

  /// The remaining time to live of a field, see `httl`.
  @since(version = 0.3.0-dev)
  type httl-reply = ttl-reply;

  /// The remaining time to live of a key or hash field, to the millisecond, see `pttl` and `hpttl`.
  @since(version = 0.3.0-dev)
  variant pttl-reply {
    /// -2: the key does not exist, or for a hash field, the field or the hash does not exist.
    does-not-exist,
    /// -1: the key or field exists, but has no expiration.
    no-expiration,
    /// The time until it expires.
    expires-in(duration-milliseconds),
  }

  /// The remaining time to live of a field, see `hpttl`.
  @since(version = 0.3.0-dev)
  type hpttl-reply = pttl-reply;

  /// When a key or hash field expires, to the second, see `expiretime` and `hexpiretime`.
  @since(version = 0.3.0-dev)
  variant expiretime-reply {
    /// -2: the key does not exist, or for a hash field, the field or the hash does not exist.
    does-not-exist,
    /// -1: the key or field exists, but has no expiration.
    no-expiration,
    /// The time at which it expires.
    expires-at(unix-time-seconds),
  }

  /// The expiration time of a field, see `hexpiretime`.
  @since(version = 0.3.0-dev)
  type hexpiretime-reply = expiretime-reply;

  /// When a key or hash field expires, to the millisecond, see `pexpiretime` and `hpexpiretime`.
  @since(version = 0.3.0-dev)
  variant pexpiretime-reply {
    /// -2: the key does not exist, or for a hash field, the field or the hash does not exist.
    does-not-exist,
    /// -1: the key or field exists, but has no expiration.
    no-expiration,
    /// The time at which it expires.
    expires-at(unix-time-milliseconds),
  }

  /// The expiration time of a field, see `hpexpiretime`.
  @since(version = 0.3.0-dev)
  type hpexpiretime-reply = pexpiretime-reply;

  /// A range of a sorted result, `LIMIT offset count`.
  @since(version = 0.3.0-dev)
  record limit {
    /// The number of elements skipped.
    offset: integer,
    /// The maximum number of elements returned, negative for all of them.
    count: integer,
  }

  @since(version = 0.3.0-dev)
  enum sort-order {
    /// ascending, smallest to largest.
    asc,
    /// descending, largest to smallest.
    desc,
  }

  /// admin commands
  /// Whether a user may run a command, see `acl-dryrun`.
  @since(version = 0.3.0-dev)
  variant acl-dryrun-result {
    /// The user may run the command.
    allowed,
    /// The user may not run the command, and why.
    denied(string),
  }

  /// A security event, a command or authentication the rules denied, see `acl-log`.
  @since(version = 0.3.0-dev)
  record acl-log-entry {
    /// The number of events like this one, within 60 seconds of each other.
    count: integer,
    /// What was denied, e.g. `command`, `key`, `channel` or `auth`.
    reason: string,
    /// Where it was denied, e.g. `toplevel`, `multi` or `lua`.
    context: string,
    /// The command, key or channel that was denied.
    object: string,
    username: string,
    /// The seconds since the latest of these events.
    age-seconds: double,
    /// The connection, in the format of CLIENT LIST.
    client-info: string,
    /// The ID of the entry, since Valkey 7.2.
    entry-id: option<integer>,
    /// When the first of these events happened, since Valkey 7.2.
    timestamp-created: option<unix-time-milliseconds>,
    /// When the latest of these events happened, since Valkey 7.2.
    timestamp-last-updated: option<unix-time-milliseconds>,
  }

  /// What BGSAVE does.
  @since(version = 0.3.0-dev)
  enum bgsave-operation {
    /// `SCHEDULE`: saves once the rewrite of the append-only file in progress is done.
    schedule,
    /// `CANCEL`: cancels the save in progress, or scheduled.
    cancel,
  }

  /// The type of a connection, for the `client-filter`.
  @since(version = 0.3.0-dev)
  enum client-type {
    /// `normal`
    normal,
    /// `master`: the connection to the primary of a replica.
    primary,
    /// `replica`
    replica,
    /// `pubsub`
    pubsub,
  }

  /// A filter of connections, for CLIENT KILL and CLIENT LIST.
  @since(version = 0.3.0-dev)
  variant client-filter {
    /// `ID client-id [ client-id ... ]`
    id(list<integer>),
    /// `TYPE`
    %type(client-type),
    /// `USER username`
    user(string),
    /// `ADDR ip:port`: the address of the client.
    addr(string),
    /// `LADDR ip:port`: the address of the server the client connected to.
    laddr(string),
    /// `SKIPME YES | NO`: whether to skip this connection, yes by default for CLIENT KILL.
    skipme(bool),
    /// `MAXAGE`: connections older than the time.
    maxage(duration-seconds),
    /// `NAME`
    name(string),
    /// `IDLE`: connections idle for at least the time.
    idle(duration-seconds),
    /// `FLAGS`: connections with all the flags, e.g. `N`.
    %flags(string),
    /// `LIB-NAME`
    lib-name(string),
    /// `LIB-VER`
    lib-ver(string),
    /// `DB`
    db(integer),
    /// `CAPA`: connections with the capability, e.g. `redirect`.
    capa(string),
    /// `IP`
    ip(string),
    /// `NOT-ID client-id [ client-id ... ]`
    not-id(list<integer>),
    /// `NOT-TYPE`
    not-type(client-type),
    /// `NOT-USER`
    not-user(string),
    /// `NOT-ADDR`
    not-addr(string),
    /// `NOT-LADDR`
    not-laddr(string),
    /// `NOT-NAME`
    not-name(string),
    /// `NOT-FLAGS`
    not-flags(string),
    /// `NOT-LIB-NAME`
    not-lib-name(string),
    /// `NOT-LIB-VER`
    not-lib-ver(string),
    /// `NOT-DB`
    not-db(integer),
    /// `NOT-CAPA`
    not-capa(string),
    /// `NOT-IP`
    not-ip(string),
  }

  /// Which commands CLIENT PAUSE suspends.
  @since(version = 0.3.0-dev)
  enum client-pause-mode {
    /// `WRITE`: commands that may write.
    write,
    /// `ALL`: every command, the default.
    all,
  }

  /// How CLIENT UNBLOCK unblocks a connection.
  @since(version = 0.3.0-dev)
  enum client-unblock-type {
    /// `TIMEOUT`: as if the command timed out, the default.
    timeout,
    /// `ERROR`: with an `UNBLOCKED` error.
    error,
  }

  /// The outcome of CLUSTER BUMPEPOCH.
  @since(version = 0.3.0-dev)
  variant cluster-bumpepoch-result {
    /// `BUMPED`: the config epoch was advanced, to this one.
    bumped(integer),
    /// `STILL`: the config epoch is already the greatest in the cluster, this one.
    still(integer),
  }

  /// How CLUSTER FAILOVER fails over.
  @since(version = 0.3.0-dev)
  enum cluster-failover-mode {
    /// `FORCE`: without the agreement of the primary, which may be down.
    force,
    /// `TAKEOVER`: without the agreement of the primary or the rest of the cluster.
    takeover,
  }

  /// Which way a slot migration moves the slots.
  @since(version = 0.3.0-dev)
  enum cluster-getslotmigrations-operation {
    /// `IMPORT`: to this node.
    %import,
    /// `EXPORT`: from this node.
    %export,
  }

  /// A slot migration, see `cluster-getslotmigrations`.
  @since(version = 0.3.0-dev)
  record cluster-getslotmigrations-entry {
    /// The ID of the migration.
    link-name: string,
    operation: cluster-getslotmigrations-operation,
    /// The ranges of slots, start and end both included.
    slot-ranges: list<tuple<u16, u16>>,
    /// The ID of the node the slots move to.
    target-node: string,
    /// The ID of the node the slots move from.
    source-node: string,
    create-time: unix-time-seconds,
    last-update-time: unix-time-seconds,
    last-ack-time: unix-time-seconds,
    /// The state of the migration, for people to read.
    state: string,
    /// More details of the state, for people to read.
    message: string,
    /// The bytes copied on write while forked for the migration.
    cow-size: integer,
  }

  /// Ranges of slots to migrate to a node, see `cluster-migrateslots`.
  @since(version = 0.3.0-dev)
  record cluster-migrateslots-group {
    /// The ranges of slots, start and end both included.
    ranges: list<tuple<u16, u16>>,
    /// The ID of the node to migrate the slots to.
    node-id: string,
    /// `AUTH username password`: the credentials for the node, since Valkey 9.2.
    auth: option<tuple<string, string>>,
  }

  /// How CLUSTER RESET resets a node.
  @since(version = 0.3.0-dev)
  enum cluster-reset-mode {
    /// `HARD`: also generates a new node ID and resets the epochs.
    hard,
    /// `SOFT`: the default.
    soft,
  }

  /// The state to set a slot to, see `cluster-setslot`.
  @since(version = 0.3.0-dev)
  variant cluster-setslot-state {
    /// `IMPORTING node-id`: importing the slot from the node.
    importing(string),
    /// `MIGRATING node-id`: migrating the slot to the node.
    migrating(string),
    /// `NODE node-id`: assigned to the node.
    node(string),
    /// `STABLE`: neither importing nor migrating.
    stable,
  }

  /// A command log, see `commandlog-get`.
  @since(version = 0.3.0-dev)
  enum commandlog-type {
    /// `slow`: commands that took longer than `commandlog-execution-slower-than`.
    slow,
    /// `large-request`: commands larger than `commandlog-request-larger-than`.
    large-request,
    /// `large-reply`: replies larger than `commandlog-reply-larger-than`.
    large-reply,
  }

  /// An entry of the slow log or a command log.
  @since(version = 0.3.0-dev)
  record commandlog-entry {
    /// The ID of the entry, unique until the server restarts.
    id: integer,
    /// When the command ran.
    timestamp: unix-time-seconds,
    /// The microseconds the command took, or for the large logs, the bytes of the request or
    /// reply.
    value: integer,
    /// The command and its arguments, long ones shortened.
    arguments: list<string>,
    /// The client's address, `ip:port`.
    client-address: string,
    /// The client's name, see CLIENT SETNAME, empty when it has none.
    client-name: string,
  }

  /// An entry of the slow log, see `slowlog-get`.
  @since(version = 0.3.0-dev)
  type slowlog-entry = commandlog-entry;

  /// Where FAILOVER fails over to.
  @since(version = 0.3.0-dev)
  record failover-target {
    host: string,
    port: u16,
    /// `FORCE`: fails over at the timeout, even before the replica has caught up.
    force: bool,
  }

  /// The latency histogram of a command, see `latency-histogram`.
  @since(version = 0.3.0-dev)
  record latency-histogram-entry {
    /// The number of times the command ran.
    calls: integer,
    /// The cumulative counts of the calls that took up to each number of microseconds, a power
    /// of 2.
    histogram-usec: list<tuple<integer, integer>>,
  }

  /// The latest sample of the latency of an event, see `latency-latest`.
  @since(version = 0.3.0-dev)
  record latency-latest-entry {
    event: string,
    /// When the latest sample was taken.
    timestamp: unix-time-seconds,
    latest: duration-milliseconds,
    /// The highest latency since the server started, or the event was reset.
    max: duration-milliseconds,
    /// The sum of the latencies of the samples.
    sum: duration-milliseconds,
    /// The number of samples.
    count: integer,
  }

  /// A loaded module, see `module-list`.
  @since(version = 0.3.0-dev)
  record module-list-entry {
    name: string,
    /// The module's version.
    ver: integer,
    /// The path the module was loaded from.
    path: string,
    /// The arguments the module was loaded with.
    args: list<string>,
  }

  /// A replica of a primary, see `role`.
  @since(version = 0.3.0-dev)
  record role-primary-replica {
    ip: string,
    port: u16,
    /// The replication offset the replica last acknowledged.
    offset: integer,
  }

  /// The replication state of a primary, see `role`.
  @since(version = 0.3.0-dev)
  record role-primary {
    /// The primary's replication offset.
    offset: integer,
    replicas: list<role-primary-replica>,
  }

  /// The replication state of a replica, see `role`.
  @since(version = 0.3.0-dev)
  record role-replica {
    primary-host: string,
    primary-port: u16,
    /// The state of replication, e.g. `connected`, `connecting` or `sync`.
    state: string,
    /// The replication offset of the data received from the primary, -1 when not connected.
    offset: integer,
  }

  /// The server's role in replication, see `role`.
  @since(version = 0.3.0-dev)
  variant role-reply {
    /// `master`
    primary(role-primary),
    /// `slave`
    replica(role-replica),
    /// `sentinel`: the names of the primaries it monitors.
    sentinel(list<string>),
  }

  /// The modifiers of SHUTDOWN.
  @since(version = 0.3.0-dev)
  flags shutdown-flags {
    /// `NOW`: does not wait for lagging replicas.
    now,
    /// `FORCE`: ignores errors that would prevent the shutdown, e.g. failing to save.
    force,
    /// `SAFE`: refuses to shut down while it would lose the cluster's quorum of primaries.
    safe,
    /// `FAILOVER`: fails over to a replica first.
    failover,
  }

  /// Whether SHUTDOWN saves to disk.
  @since(version = 0.3.0-dev)
  enum shutdown-save {
    /// `NOSAVE`: does not save, even with save points configured.
    nosave,
    /// `SAVE`: saves, even without save points configured.
    save,
  }

  /// A rule for the keys a user may access.
  @since(version = 0.3.0-dev)
  variant acl-key-rule {
    /// `~<pattern>`: allows reading and writing the keys matching the glob-style pattern.
    add(string),
    /// `%R~<pattern>`: allows reading the keys matching the glob-style pattern.
    add-read(string),
    /// `%W~<pattern>`: allows writing the keys matching the glob-style pattern.
    add-write(string),
    /// `%RW~<pattern>`: allows reading and writing the keys matching the glob-style pattern, the
    /// same as `add`.
    add-read-write(string),
    /// `allkeys`: allows access to all keys, an alias for `~*`.
    all,
    /// `resetkeys`: removes all the allowed key patterns.
    reset,
  }

  /// A rule for the Pub/Sub channels a user may access.
  @since(version = 0.3.0-dev)
  variant acl-channel-rule {
    /// `&<pattern>`: allows access to the Pub/Sub channels matching the glob-style pattern.
    add(string),
    /// `allchannels`: allows access to all Pub/Sub channels, an alias for `&*`.
    all,
    /// `resetchannels`: removes all the allowed channel patterns, disconnecting the user's Pub/Sub
    /// clients that can no longer access their channels.
    reset,
  }

  /// A rule for the commands a user may call.
  @since(version = 0.3.0-dev)
  variant acl-command-rule {
    /// `+<command>`: allows the command, or a subcommand, e.g. `config|get`.
    add(string),
    /// `+@<category>`: allows all the commands in the category, e.g. `read`, see ACL CAT for the
    /// categories.
    add-category(string),
    /// `+<command>|<first-arg>`: allows the command only with the given first argument, e.g. `select`
    /// with `0`.
    add-first-arg(tuple<string, string>),
    /// `allcommands`: allows all commands, including those of modules loaded later, an alias for `+@all`.
    all,
    /// `-<command>`: disallows the command, or a subcommand.
    remove(string),
    /// `-@<category>`: disallows all the commands in the category.
    remove-category(string),
    /// `nocommands`: disallows all commands, an alias for `-@all`.
    reset,
  }

  /// A rule for the databases a user may access.
  @since(version = 0.3.0-dev)
  variant acl-db-rule {
    /// `db=<id>[,<id>...]`: allows access to the databases with the given IDs.
    db(list<u8>),
    /// `alldbs`: allows access to all databases.
    all,
    /// `resetdbs`: removes all the allowed databases.
    reset,
  }

  /// A rule of a selector, a set of permissions matched independently of the user's root permissions,
  /// the user may run a command when either permits it.
  @since(version = 0.3.0-dev)
  variant acl-selector-rule {
    /// The keys the selector permits access to.
    keys(acl-key-rule),
    /// The Pub/Sub channels the selector permits access to.
    channel(acl-channel-rule),
    /// The commands the selector permits.
    command(acl-command-rule),
    /// The databases the selector permits access to.
    db(acl-db-rule),
    /// A rule this interface does not know, e.g. from a newer server, sent as is.
    other(string),
  }

  /// A rule for the user itself.
  @since(version = 0.3.0-dev)
  variant acl-user-rule {
    /// `on`: enables the user, it is possible to authenticate as this user.
    on,
    /// `off`: disables the user, it is no longer possible to authenticate as this user, connections
    /// already authenticated keep working.
    off,
    /// `nopass`: removes all the user's passwords, any password then authenticates as the user.
    nopass,
    /// `sanitize-payload`: validates the payloads of the user's RESTORE commands, the default.
    sanitize-payload,
    /// `skip-sanitize-payload`: skips validating the payloads of the user's RESTORE commands.
    skip-sanitize-payload,
    /// `><password>`: adds the password to the user's passwords.
    password(string),
    /// `#<hash>`: adds a password, by its SHA-256 hash as 64 lowercase hex characters, to the user's
    /// passwords.
    hashed-password(string),
    /// `<<password>`: removes the password from the user's passwords.
    remove-password(string),
    /// `!<hash>`: removes a password, by its SHA-256 hash, from the user's passwords.
    remove-hashed-password(string),
    /// `(<rule> ...)`: adds a selector, with the given rules.
    selector(list<acl-selector-rule>),
    /// `clearselectors`: removes all the user's selectors.
    clearselectors,
    /// `reset`: resets the user to its state when created, disabled, without passwords, keys,
    /// channels, commands or selectors.
    reset,
  }

  /// A rule of an ACL user, see `acl-setuser`.
  ///
  /// https://valkey.io/topics/acl/
  @since(version = 0.3.0-dev)
  variant acl-rule {
    /// The keys the user may access.
    keys(acl-key-rule),
    /// The Pub/Sub channels the user may access.
    channel(acl-channel-rule),
    /// The commands the user may call.
    command(acl-command-rule),
    /// The databases the user may access.
    db(acl-db-rule),
    /// The user itself, e.g. whether it is enabled and its passwords.
    user(acl-user-rule),
    /// A rule this interface does not know, e.g. from a newer server, sent as is.
    other(string),
  }

  /// A user and its rules, see `acl-list`.
  @since(version = 0.3.0-dev)
  record acl-list-entry {
    username: string,
    /// The user's rules, as the server normalized them, e.g. `allkeys` is `~*`. Applied with
    /// `acl-setuser`, after `reset`, they recreate the user.
    rules: list<acl-rule>,
  }

  /// bitmap commands
  /// A range of a string, negative from the end, for BITCOUNT and BITPOS.
  @since(version = 0.3.0-dev)
  variant bit-range {
    /// `start`: the bytes from the start to the end of the string.
    %from(integer),
    /// `start end`: the bytes from the start to the end, both included.
    bytes(tuple<integer, integer>),
    /// `start end BIT`: the bits from the start to the end, both included.
    bits(tuple<integer, integer>),
  }

  /// The type of an integer field of a string, for BITFIELD.
  @since(version = 0.3.0-dev)
  variant bitfield-encoding {
    /// `i1` to `i64`: a signed integer of the width in bits.
    signed(u8),
    /// `u1` to `u63`: an unsigned integer of the width in bits.
    unsigned(u8),
  }

  /// Where an integer field of a string starts, for BITFIELD.
  @since(version = 0.3.0-dev)
  variant bitfield-offset {
    /// The offset in bits.
    bit(u64),
    /// `#field`: the field of the encoding's width, the offset in bits is the field times the
    /// width.
    field(u64),
  }

  /// What a write does when the field overflows, `OVERFLOW`.
  @since(version = 0.3.0-dev)
  enum bitfield-overflow {
    /// `WRAP`: wraps around, the default.
    wrap,
    /// `SAT`: saturates at the minimum or maximum.
    sat,
    /// `FAIL`: does not write, the result is none.
    fail,
  }

  /// `GET encoding offset`: the value of the field.
  @since(version = 0.3.0-dev)
  record bitfield-get {
    encoding: bitfield-encoding,
    offset: bitfield-offset,
  }

  /// A GET operation, see `bitfield-ro`.
  @since(version = 0.3.0-dev)
  type bitfield-ro-get = bitfield-get;

  /// `SET encoding offset value`: sets the field, the result is its previous value.
  @since(version = 0.3.0-dev)
  record bitfield-set {
    encoding: bitfield-encoding,
    offset: bitfield-offset,
    value: s64,
  }

  /// `INCRBY encoding offset increment`: increments the field, the result is its new value.
  @since(version = 0.3.0-dev)
  record bitfield-incrby {
    encoding: bitfield-encoding,
    offset: bitfield-offset,
    increment: s64,
  }

  /// An operation of BITFIELD.
  ///
  /// A write is preceded by an optional overflow mode, `OVERFLOW WRAP | SAT | FAIL`, for it and
  /// the following writes. None keeps the current mode, `WRAP` at the start of the command.
  @since(version = 0.3.0-dev)
  variant bitfield-operation {
    /// `GET encoding offset`
    get(bitfield-get),
    /// `[ OVERFLOW WRAP | SAT | FAIL ] SET encoding offset value`
    set(tuple<option<bitfield-overflow>, bitfield-set>),
    /// `[ OVERFLOW WRAP | SAT | FAIL ] INCRBY encoding offset increment`
    incrby(tuple<option<bitfield-overflow>, bitfield-incrby>),
  }

  /// A bitwise operation of BITOP, and its source keys.
  @since(version = 0.3.0-dev)
  variant bitop-operation {
    /// `AND`
    and(list<string>),
    /// `OR`
    or(list<string>),
    /// `XOR`
    xor(list<string>),
    /// `NOT`: of a single key.
    not(string),
  }

  /// The keyword before the first key, see `command-key-spec-begin-search`.
  @since(version = 0.3.0-dev)
  record command-key-spec-keyword {
    keyword: string,
    /// The index of the argument to start searching from, from the end when negative.
    startfrom: integer,
  }

  /// connection commands
  /// How a key spec finds the first key, see `command-key-spec`.
  @since(version = 0.3.0-dev)
  variant command-key-spec-begin-search {
    /// `index`: the argument at the index.
    index(integer),
    /// `keyword`: the argument after the keyword.
    keyword(command-key-spec-keyword),
    /// `unknown`: the keys cannot be found from the arguments alone.
    unknown,
  }

  /// A range of keys, see `command-key-spec-find-keys`.
  @since(version = 0.3.0-dev)
  record command-key-spec-range {
    /// The index of the last key, relative to the first, from the end when negative.
    lastkey: integer,
    /// The number of arguments from one key to the next.
    keystep: integer,
    /// With a `lastkey` of -1, divides the remaining arguments, e.g. 2 for half of them.
    limit: integer,
  }

  /// A number of keys, see `command-key-spec-find-keys`.
  @since(version = 0.3.0-dev)
  record command-key-spec-keynum {
    /// The index of the argument with the number of keys, relative to the first.
    keynumidx: integer,
    /// The index of the first key, relative to the first.
    firstkey: integer,
    /// The number of arguments from one key to the next.
    keystep: integer,
  }

  /// How a key spec finds the keys after the first one, see `command-key-spec`.
  @since(version = 0.3.0-dev)
  variant command-key-spec-find-keys {
    /// `range`: a range of arguments.
    range(command-key-spec-range),
    /// `keynum`: the number of keys is an argument.
    keynum(command-key-spec-keynum),
    /// `unknown`: the keys cannot be found from the arguments alone.
    unknown,
  }

  /// Where a command's keys are and how it uses them.
  @since(version = 0.3.0-dev)
  record command-key-spec {
    notes: option<string>,
    /// How the command uses the keys, e.g. `RW`, `access` and `update`.
    %flags: list<string>,
    begin-search: command-key-spec-begin-search,
    find-keys: command-key-spec-find-keys,
  }

  /// A command, see `command` and `command-info`.
  @since(version = 0.3.0-dev)
  record command-info-reply {
    /// The command's name, e.g. `get`, or for a subcommand, `config|get`.
    name: string,
    /// The number of arguments, the name included, the minimum when negative.
    arity: integer,
    /// The command's flags, e.g. `readonly` and `fast`.
    %flags: list<string>,
    /// The index of the first key, 0 for none.
    first-key: integer,
    /// The index of the last key, from the end when negative.
    last-key: integer,
    /// The number of arguments from one key to the next.
    step: integer,
    /// The ACL categories of the command, e.g. `@read`.
    acl-categories: list<string>,
    /// Hints for clients, e.g. `nondeterministic_output`.
    tips: list<string>,
    key-specs: list<command-key-spec>,
  }

  /// The details of a command, see `command`.
  @since(version = 0.3.0-dev)
  type command-reply = command-info-reply;

  /// The type of an argument of a command, see `command-docs-argument`.
  @since(version = 0.3.0-dev)
  variant command-docs-argument-type {
    /// `string`
    %string,
    /// `integer`
    integer,
    /// `double`
    double,
    /// `key`: a key, see `key-spec-index`.
    key,
    /// `pattern`: a glob-style pattern.
    pattern,
    /// `unix-time`
    unix-time,
    /// `pure-token`: the token alone, without a value.
    pure-token,
    /// `oneof`: one of the arguments it contains.
    oneof,
    /// `block`: the arguments it contains, together.
    block,
    /// A type this interface does not know, e.g. from a newer server.
    other(string),
  }

  /// An argument of a command, see `command-docs`.
  @since(version = 0.3.0-dev)
  record command-docs-argument {
    /// The index of the `oneof` or `block` argument containing this one, in the command's
    /// arguments, none at the top level.
    parent: option<u32>,
    name: string,
    %type: command-docs-argument-type,
    /// The name to show for the argument.
    display-text: option<string>,
    /// The index of the argument's key spec, for a key.
    key-spec-index: option<integer>,
    /// The token before the argument's value, e.g. `EX`, or for a `pure-token`, the token alone.
    token: option<string>,
    summary: option<string>,
    /// The version that added the argument.
    since: option<string>,
    deprecated-since: option<string>,
    /// The argument's flags, e.g. `optional`, `multiple` and `multiple_token`.
    %flags: list<string>,
  }

  /// The documentation of a command, see `command-docs`.
  @since(version = 0.3.0-dev)
  record command-docs-reply {
    /// The command's name, e.g. `get`, or for a subcommand, `config|get`.
    name: string,
    summary: string,
    /// The version that added the command.
    since: string,
    /// The command's group, e.g. `string`.
    group: string,
    /// The command's time complexity, none for a few commands, e.g. MONITOR.
    complexity: option<string>,
    /// The module of the command, for a module's command.
    module: option<string>,
    /// The command's documentation flags, e.g. `deprecated` or `syscmd`.
    doc-flags: list<string>,
    deprecated-since: option<string>,
    /// The command to use instead, for a deprecated command.
    replaced-by: option<string>,
    /// The changes to the command, the version of each and what changed.
    history: list<tuple<string, string>>,
    /// The arguments, depth first, those an argument contains after it.
    arguments: list<command-docs-argument>,
  }

  /// Information about the library of a connection, see `client-setinfo`.
  @since(version = 0.3.0-dev)
  variant client-setinfo-attr {
    /// `LIB-NAME`: the name of the library, e.g. `valkey-wasm`.
    lib-name(string),
    /// `LIB-VER`: the version of the library.
    lib-ver(string),
  }

  /// Which keys tracking tracks without CLIENT CACHING.
  @since(version = 0.3.0-dev)
  enum client-tracking-mode {
    /// `OPTIN`: none, only those of commands after CLIENT CACHING YES.
    optin,
    /// `OPTOUT`: all, except those of commands after CLIENT CACHING NO.
    optout,
  }

  /// The options of CLIENT TRACKING ON.
  @since(version = 0.3.0-dev)
  record client-tracking-options {
    /// `PREFIX prefix`: with `bcast`, only notifies about keys with the prefixes.
    prefixes: option<list<string>>,
    /// `BCAST`: notifies about every change of the keys with the prefixes, read or not.
    bcast: bool,
    mode: option<client-tracking-mode>,
    /// `NOLOOP`: does not notify about the keys the connection changed itself.
    noloop: bool,
  }

  /// Where a connection's tracking notifications are redirected, see `client-trackinginfo`.
  ///
  /// Redirecting is for RESP2, which the connection does not use, but CLIENT TRACKING REDIRECT may
  /// still be sent with `connection.exchange`.
  @since(version = 0.3.0-dev)
  variant client-trackinginfo-redirect {
    /// -1: tracking is not on.
    not-tracking,
    /// 0: tracking is on, the notifications are not redirected.
    not-redirected,
    /// The ID of the connection the notifications are redirected to.
    redirected(integer),
  }

  /// A connection's tracking state, see `client-trackinginfo`.
  @since(version = 0.3.0-dev)
  record client-trackinginfo-reply {
    /// The tracking flags, e.g. `on`, `bcast`, `optin` or `noloop`.
    %flags: list<string>,
    /// Where the notifications are redirected.
    redirect: client-trackinginfo-redirect,
    /// The prefixes of BCAST.
    prefixes: list<string>,
  }

  /// The filter of COMMAND LIST.
  @since(version = 0.3.0-dev)
  variant command-list-filter {
    /// `MODULE module-name`: the commands of the module.
    module(string),
    /// `ACLCAT category`: the commands in the ACL category.
    aclcat(string),
    /// `PATTERN pattern`: the commands matching the glob-style pattern.
    pattern(string),
  }

  /// geo commands
  /// A position on the Earth.
  ///
  /// The exact limits, as specified by EPSG:900913 / EPSG:3785 / OSGEO:41001
  @since(version = 0.3.0-dev)
  record geo-coordinates {
    /// The longitude, from -180 to 180 degrees.
    longitude: double,
    /// The latitude, from -85.05112878 to 85.05112878 degrees.
    latitude: double,
  }

  /// A unit of distance.
  @since(version = 0.3.0-dev)
  enum geo-unit {
    /// `m`: meters.
    m,
    /// `km`: kilometers.
    km,
    /// `ft`: feet.
    ft,
    /// `mi`: miles.
    mi,
  }

  /// Only add or only update members, GEOADD's `NX` and `XX`.
  @since(version = 0.3.0-dev)
  enum geoadd-condition {
    /// Only add new members, never update existing ones.
    nx,
    /// Only update existing members, never add new ones.
    xx,
  }

  /// The center of a search, `FROMMEMBER` or `FROMLONLAT`.
  @since(version = 0.3.0-dev)
  variant geosearch-from {
    /// `FROMMEMBER member`: the position of a member of the index.
    member(string-or-bytes),
    /// `FROMLONLAT longitude latitude`
    lonlat(geo-coordinates),
  }

  /// `BYRADIUS`: a circle around the center.
  @since(version = 0.3.0-dev)
  record geosearch-radius {
    %from: geosearch-from,
    radius: double,
    unit: geo-unit,
  }

  /// `BYBOX`: a rectangle around the center.
  @since(version = 0.3.0-dev)
  record geosearch-box {
    %from: geosearch-from,
    width: double,
    height: double,
    unit: geo-unit,
  }

  /// The area of a search.
  @since(version = 0.3.0-dev)
  variant geosearch-shape {
    /// `[ FROMMEMBER member | FROMLONLAT longitude latitude ] BYRADIUS radius unit`
    radius(geosearch-radius),
    /// `[ FROMMEMBER member | FROMLONLAT longitude latitude ] BYBOX width height unit`
    box(geosearch-box),
    /// `BYPOLYGON num-vertices longitude latitude [ longitude latitude ... ]`: the polygon with
    /// the vertices, in order, which has no center.
    polygon(list<geo-coordinates>),
  }

  /// The area to search, see `geosearchstore`.
  @since(version = 0.3.0-dev)
  type geosearchstore-shape = geosearch-shape;

  /// At most a count of the members, `COUNT count [ ANY ]`.
  @since(version = 0.3.0-dev)
  record geosearch-count {
    count: integer,
    /// `ANY`: returns as soon as enough members are found, rather than the nearest ones.
    any: bool,
  }

  /// The number of members to store, see `geosearchstore`.
  @since(version = 0.3.0-dev)
  type geosearchstore-count = geosearch-count;

  /// The details GEOSEARCH returns of each member it found.
  @since(version = 0.3.0-dev)
  flags geosearch-with-flags {
    /// `WITHCOORD`: the position.
    withcoord,
    /// `WITHDIST`: the distance from the center.
    withdist,
    /// `WITHHASH`: the geohash, as an integer.
    withhash,
  }

  /// A member a search found, with the details asked for.
  @since(version = 0.3.0-dev)
  record geosearch-with-result {
    member: string-or-bytes,
    /// `WITHDIST`: the distance from the center, in the unit of the shape.
    distance: option<double>,
    /// `WITHHASH`: the geohash, as an integer.
    hash: option<integer>,
    /// `WITHCOORD`: the position.
    coordinates: option<geo-coordinates>,
  }

  /// hash commands
  /// The outcome of removing the expiration of a hash field.
  @since(version = 0.3.0-dev)
  enum hpersist-result {
    /// -2: the field does not exist, or the hash does not exist.
    does-not-exist,
    /// -1: the field exists, but has no expiration.
    no-expiration,
    /// 1: the expiration was removed.
    removed,
  }

  /// Only set the fields when the hash does, or does not, exist, HSETEX's `NX` and `XX`.
  @since(version = 0.3.0-dev)
  enum hsetex-condition {
    /// Only set the fields when the hash does not exist.
    nx,
    /// Only set the fields when the hash exists.
    xx,
  }

  /// Only set the fields when none, or all, of them exist, HSETEX's `FNX` and `FXX`.
  @since(version = 0.3.0-dev)
  enum hsetex-field-condition {
    /// Only set the fields when none of them exist.
    fnx,
    /// Only set the fields when all of them exist.
    fxx,
  }

  /// The outcome of setting the expiration of a hash field, e.g. with HEXPIRE.
  @since(version = 0.3.0-dev)
  enum hexpire-result {
    /// -2: key does not exist, or field does not exist in the HASH.
    does-not-exist,
    /// 0: the specified NX | XX | GT | LT condition has not been met.
    condition-not-met,
    /// 1: the expiration time was applied.
    applied,
    /// 2: when called with 0 seconds.
    zero-seconds,
  }

  /// The result for a field, see `hexpireat`.
  @since(version = 0.3.0-dev)
  type hexpireat-result = hexpire-result;

  /// The result for a field, see `hpexpire`.
  @since(version = 0.3.0-dev)
  type hpexpire-result = hexpire-result;

  /// The result for a field, see `hpexpireat`.
  @since(version = 0.3.0-dev)
  type hpexpireat-result = hexpire-result;

  /// keyspace commands
  /// The expiration of a key `restore` creates.
  @since(version = 0.3.0-dev)
  variant restore-ttl {
    /// `ttl`: the key expires after the duration.
    expire-in(duration-milliseconds),
    /// `ttl` with `ABSTTL`: the key expires at the time.
    expire-at(unix-time-milliseconds),
  }

  /// The type of the value stored at a key.
  @since(version = 0.3.0-dev)
  variant key-type {
    /// `string`
    %string,
    /// `list`
    %list,
    /// `set`
    set,
    /// `zset`: a sorted set.
    zset,
    /// `hash`
    hash,
    /// `stream`
    %stream,
    /// The type of a module, by name.
    other(string),
  }

  /// The options of MIGRATE.
  @since(version = 0.3.0-dev)
  flags migrate-flags {
    /// `COPY`: keeps the keys in this instance.
    copy,
    /// `REPLACE`: replaces keys that exist in the other instance.
    replace,
  }

  /// The credentials to authenticate to the other instance with, for MIGRATE.
  @since(version = 0.3.0-dev)
  variant migrate-auth {
    /// `AUTH password`
    password(string),
    /// `AUTH2 username password`
    username-password(tuple<string, string>),
  }

  /// How SORT orders and projects the elements of a list, set or sorted set.
  @since(version = 0.3.0-dev)
  record sort-opts {
    /// `BY pattern`: sorts by the values of the keys the pattern names, `*` replaced with each
    /// element, or `nosort` to skip sorting.
    by: option<string>,
    /// `LIMIT offset count`: a range of the sorted elements.
    limit: option<limit>,
    /// `GET pattern`: returns the values of the keys each pattern names instead of the elements,
    /// `#` for the element itself.
    get: option<list<string>>,
    /// order to sort elements.
    order: option<sort-order>,
    /// `ALPHA`: sorts lexicographically, rather than numerically.
    alpha: bool,
  }

  /// The options of the sort, see `sort-ro`.
  @since(version = 0.3.0-dev)
  type sort-ro-opts = sort-opts;

  /// list commands
  /// An end of a list.
  @since(version = 0.3.0-dev)
  enum list-side {
    /// `LEFT`: the head, the first element.
    left,
    /// `RIGHT`: the tail, the last element.
    right,
  }

  /// Where LINSERT inserts an element, relative to the pivot.
  @since(version = 0.3.0-dev)
  enum linsert-position {
    /// `BEFORE`: in front of the pivot.
    before,
    /// `AFTER`: behind the pivot.
    after,
  }

  /// The outcome of LINSERT.
  @since(version = 0.3.0-dev)
  variant linsert-result {
    /// The element was inserted, the length of the list after it.
    inserted(integer),
    /// 0: the key does not exist, nothing was inserted.
    no-such-key,
    /// -1: the pivot is not in the list, nothing was inserted.
    pivot-not-found,
  }

  /// scripting commands
  /// What `function-restore` does with the libraries already loaded.
  @since(version = 0.3.0-dev)
  enum function-restore-policy {
    /// `FLUSH`: deletes them first.
    flush,
    /// `APPEND`: keeps them, failing when a library of the same name is loaded.
    append,
    /// `REPLACE`: keeps them, replacing those with a library of the same name.
    replace,
  }

  /// Whether a flush happens in the background, `ASYNC`, or before replying, `SYNC`.
  @since(version = 0.3.0-dev)
  enum flush-mode {
    /// `ASYNC`
    %async,
    /// `SYNC`
    sync,
  }

  /// A function of a library.
  @since(version = 0.3.0-dev)
  record function-list-function {
    name: string,
    description: option<string>,
    /// The function's flags, e.g. `no-writes`.
    %flags: list<string>,
  }

  /// A library of functions.
  @since(version = 0.3.0-dev)
  record function-list-library {
    library-name: string,
    /// The engine that runs the library, e.g. `LUA`.
    engine: string,
    functions: list<function-list-function>,
    /// The library's source code, with `withcode`.
    library-code: option<string>,
  }

  /// The function that is running.
  @since(version = 0.3.0-dev)
  record function-stats-running {
    name: string,
    /// The command and its arguments that called the function.
    command: list<string>,
    /// How long the function has been running.
    duration: duration-milliseconds,
  }

  /// The libraries and functions of an engine.
  @since(version = 0.3.0-dev)
  record function-stats-engine {
    libraries-count: integer,
    functions-count: integer,
  }

  /// The function that is running, and the libraries and functions of each engine.
  @since(version = 0.3.0-dev)
  record function-stats-reply {
    /// None when no function is running.
    running-script: option<function-stats-running>,
    /// The statistics of each engine, by name.
    engines: map<string, function-stats-engine>,
  }

  /// sortedset commands
  /// A bound of a range of scores.
  @since(version = 0.3.0-dev)
  variant score-bound {
    /// The score, included in the range.
    inclusive(double),
    /// `(score`: the score, excluded from the range.
    exclusive(double),
    /// `-inf` as the min, `+inf` as the max, the start is the max with `REV`.
    unbounded,
  }

  /// A bound of a range of members, for members of equal score, ordered lexicographically.
  @since(version = 0.3.0-dev)
  variant lex-bound {
    /// `[member`: the member, included in the range.
    inclusive(string-or-bytes),
    /// `(member`: the member, excluded from the range.
    exclusive(string-or-bytes),
    /// `-` as the min, `+` as the max, the start is the max with `REV`.
    unbounded,
  }

  /// Which end of a sorted set to pop from.
  @since(version = 0.3.0-dev)
  enum zmpop-end {
    /// The members with the lowest scores.
    min,
    /// The members with the highest scores.
    max,
  }

  /// The end to pop from, see `bzmpop`.
  @since(version = 0.3.0-dev)
  type bzmpop-end = zmpop-end;

  /// How scores combine for a member in several sorted sets.
  @since(version = 0.3.0-dev)
  enum zset-aggregate {
    /// The sum of the weighted scores, the default.
    sum,
    /// The lowest weighted score.
    min,
    /// The highest weighted score.
    max,
  }

  /// The range of ZRANGE and ZRANGESTORE, `start` and `stop`, given as they are sent: with `REV`,
  /// the higher bound first.
  @since(version = 0.3.0-dev)
  variant zrange-by {
    /// Positions, both included, negative from the end.
    rank(tuple<integer, integer>),
    /// `BYSCORE`: the members with scores in the range.
    score(tuple<score-bound, score-bound>),
    /// `BYLEX`: the members in the range, for members of equal score.
    lex(tuple<lex-bound, lex-bound>),
  }

  /// The range of members to store, see `zrangestore`.
  @since(version = 0.3.0-dev)
  type zrangestore-by = zrange-by;

  /// The range of ZRANGE WITHSCORES, which does not support BYLEX, see `zrange-by`.
  @since(version = 0.3.0-dev)
  variant zrange-withscores-by {
    /// Positions, both included, negative from the end.
    rank(tuple<integer, integer>),
    /// `BYSCORE`: the members with scores in the range.
    score(tuple<score-bound, score-bound>),
  }

  /// Only update or only add members, ZADD's `NX` and `XX`.
  @since(version = 0.3.0-dev)
  enum zadd-condition {
    /// Only add new members, never update existing ones.
    nx,
    /// Only update existing members, never add new ones.
    xx,
  }

  /// Only update a member's score when the new score is greater or less, ZADD's `GT` and `LT`.
  @since(version = 0.3.0-dev)
  enum zadd-comparison {
    /// Only update when the new score is greater than the current one.
    gt,
    /// Only update when the new score is less than the current one.
    lt,
  }

  /// stream commands
  /// The ID of a stream entry, `<milliseconds-time>-<sequence-number>`, e.g. `1526919030474-55`.
  ///
  /// Commands that add an entry also accept `*`, for the server to generate the ID.
  @since(version = 0.3.0-dev)
  type stream-id = string;

  /// How exactly a stream is trimmed. Nearly exact trimming is more efficient, the stream may keep a
  /// few entries more than the threshold.
  @since(version = 0.3.0-dev)
  enum stream-trim-efficiency {
    /// `=`: exact trimming
    exact,
    /// `~`: nearly exact trimming
    mearly-exact,
  }

  /// Trims the stream to a maximum length, `MAXLEN [ = | ~ ] threshold [ LIMIT count ]`.
  @since(version = 0.3.0-dev)
  record stream-trim-maxlen {
    /// Exact, `=`, when none.
    efficiency: option<stream-trim-efficiency>,
    /// The maximum number of entries kept.
    threshold: integer,
    /// The maximum number of entries evicted, only with nearly exact trimming, `0` for no limit.
    limit: option<integer>,
  }

  /// Trims the entries with lower IDs, `MINID [ = | ~ ] threshold [ LIMIT count ]`.
  @since(version = 0.3.0-dev)
  record stream-trim-minid {
    /// Exact, `=`, when none.
    efficiency: option<stream-trim-efficiency>,
    /// The lowest ID kept.
    threshold: stream-id,
    /// The maximum number of entries evicted, only with nearly exact trimming, `0` for no limit.
    limit: option<integer>,
  }

  /// How a stream is trimmed, e.g. with XADD or XTRIM.
  @since(version = 0.3.0-dev)
  variant stream-trim {
    /// Evicts entries as long as the stream's length exceeds the specified threshold, where threshold is a positive integer.
    maxlen(stream-trim-maxlen),
    /// Evicts entries with IDs lower than threshold, where threshold is a stream ID.
    minid(stream-trim-minid),
  }

  /// Options of XCLAIM.
  @since(version = 0.3.0-dev)
  record xclaim-opts {
    /// `IDLE ms`: sets the idle time of the entries, the time since they were last delivered, instead
    /// of resetting it.
    idle: option<duration-milliseconds>,
    /// `TIME unix-time-milliseconds`: sets the idle time of the entries to the time since this instant.
    time: option<unix-time-milliseconds>,
    /// `RETRYCOUNT count`: sets the delivery count of the entries, instead of incrementing it.
    retrycount: option<integer>,
    /// `FORCE`: claims the entries even when they are not pending for any consumer, as long as they
    /// exist in the stream.
    force: bool,
    /// `LASTID lastid`: sets the ID of the last entry delivered to the group.
    lastid: option<stream-id>,
  }

  /// A consumer of a group, see `xinfo-consumers`.
  @since(version = 0.3.0-dev)
  record xinfo-consumers-entry {
    /// The consumer's name.
    name: string,
    /// The number of entries pending for the consumer.
    pending: integer,
    /// The time since the consumer last attempted an interaction, e.g. XREADGROUP, XCLAIM or
    /// XAUTOCLAIM.
    idle: duration-milliseconds,
    /// The time since the consumer last interacted successfully, e.g. read or claimed entries.
    /// None when the consumer has never been active.
    inactive: option<duration-milliseconds>,
  }

  /// A consumer group of a stream, see `xinfo-groups`.
  @since(version = 0.3.0-dev)
  record xinfo-groups-entry {
    /// The group's name.
    name: string,
    /// The number of consumers in the group.
    consumers: integer,
    /// The number of entries in the group's pending entries list (PEL), delivered but not acknowledged.
    pending: integer,
    /// The ID of the last entry delivered to the group's consumers.
    last-delivered-id: stream-id,
    /// The logical read counter of the last entry delivered to the group's consumers, none when unknown.
    entries-read: option<integer>,
    /// The number of entries in the stream not yet delivered to the group's consumers, none when it
    /// cannot be determined.
    lag: option<integer>,
  }

  /// Information about a stream, see `xinfo-stream`.
  @since(version = 0.3.0-dev)
  record xinfo-stream-reply {
    /// The number of entries in the stream.
    length: integer,
    /// The number of keys in the radix tree storing the stream.
    radix-tree-keys: integer,
    /// The number of nodes in the radix tree storing the stream.
    radix-tree-nodes: integer,
    /// The number of consumer groups of the stream.
    groups: integer,
    /// The ID of the last entry added to the stream, none when no entry was ever added.
    last-generated-id: option<stream-id>,
    /// The highest ID deleted from the stream, none when no entry was ever deleted.
    max-deleted-entry-id: option<stream-id>,
    /// The number of entries added to the stream over its lifetime.
    entries-added: integer,
    /// The ID and fields of the first entry.
    /// None when the stream is empty.
    first-entry: option<tuple<stream-id, map<string, string-or-bytes>>>,
    /// The ID and fields of the last entry.
    /// None when the stream is empty.
    last-entry: option<tuple<stream-id, map<string, string-or-bytes>>>,
  }

  /// A consumer of a group, with its pending entries.
  @since(version = 0.3.0-dev)
  record xinfo-stream-reply-full-consumer {
    /// The consumer's name.
    name: string,
    /// When the consumer last attempted an interaction, e.g. XREADGROUP, XCLAIM or XAUTOCLAIM.
    seen-time: unix-time-milliseconds,
    /// When the consumer last interacted successfully, e.g. read or claimed entries.
    /// None when the consumer has never been active.
    active-time: option<unix-time-milliseconds>,
    /// The number of entries pending for the consumer, delivered but not acknowledged.
    pel-count: integer,
    /// The consumer's pending entries, the ID of each, when it was last delivered and the number of
    /// times it was delivered.
    pending: list<tuple<stream-id, unix-time-milliseconds, integer>>,
  }

  /// A consumer group of a stream, with its pending entries and consumers.
  @since(version = 0.3.0-dev)
  record xinfo-stream-reply-full-group {
    /// The group's name.
    name: string,
    /// The ID of the last entry delivered to the group's consumers.
    last-delivered-id: stream-id,
    /// The logical read counter of the last entry delivered to the group's consumers, none when unknown.
    entries-read: option<integer>,
    /// The number of entries in the stream not yet delivered to the group's consumers, none when it
    /// cannot be determined.
    lag: option<integer>,
    /// The number of entries in the group's pending entries list (PEL), delivered but not acknowledged.
    pel-count: integer,
    /// The group's pending entries, the ID of each, the consumer it was delivered to, when it was
    /// last delivered and the number of times it was delivered.
    pending: list<tuple<stream-id, string, unix-time-milliseconds, integer>>,
    /// The group's consumers.
    consumers: list<xinfo-stream-reply-full-consumer>,
  }

  /// Information about a stream, its entries and consumer groups, see `xinfo-stream-full`.
  @since(version = 0.3.0-dev)
  record xinfo-stream-reply-full {
    /// The number of entries in the stream.
    length: integer,
    /// The number of keys in the radix tree storing the stream.
    radix-tree-keys: integer,
    /// The number of nodes in the radix tree storing the stream.
    radix-tree-nodes: integer,
    /// The ID of the last entry added to the stream, none when no entry was ever added.
    last-generated-id: option<stream-id>,
    /// The highest ID deleted from the stream, none when no entry was ever deleted.
    max-deleted-entry-id: option<stream-id>,
    /// The number of entries added to the stream over its lifetime.
    entries-added: integer,
    /// The ID and fields of the entries, in ascending ID order, up to the count given.
    entries: list<tuple<stream-id, map<string, string-or-bytes>>>,
    /// The consumer groups of the stream.
    groups: list<xinfo-stream-reply-full-group>,
  }

  /// The pending entries of a consumer group, see `xpending`.
  @since(version = 0.3.0-dev)
  record xpending-summary {
    /// The number of pending entries.
    count: integer,
    /// The lowest ID of the pending entries, none when there are none.
    lowest-id: option<stream-id>,
    /// The highest ID of the pending entries, none when there are none.
    highest-id: option<stream-id>,
    /// Each consumer with pending entries, and how many it has.
    consumers: list<tuple<string, integer>>,
  }

  /// The pending entries of a consumer group, see `xpending-extended`.
  @since(version = 0.3.0-dev)
  record xpending-extended-entry {
    /// The ID of the message.
    id: stream-id,
    /// The name of the consumer that fetched the message and has still to acknowledge it. We call it the current owner of the message.
    name: string,
    /// The number of milliseconds that elapsed since the last time this message was delivered to this consumer.
    since-delivery: duration-milliseconds,
    /// The number of times this message was delivered.
    delivery-count: integer,
  }

  /// string commands
  /// The expiration to set on a key, see `getex`.
  @since(version = 0.3.0-dev)
  variant getex-ttl {
    /// Set the specified expire time, in seconds.
    ex(duration-seconds),
    /// Set the specified expire time, in milliseconds.
    px(duration-milliseconds),
    /// Set the specified Unix time at which the key will expire, in seconds.
    exat(unix-time-seconds),
    /// Set the specified Unix time at which the key will expire, in milliseconds.
    pxat(unix-time-milliseconds),
    /// Remove the time to live associated with the key.
    persist,
  }

  /// The expiration to set on the fields, see `hgetex`.
  @since(version = 0.3.0-dev)
  type hgetex-ttl = getex-ttl;

  /// A part of the longest common subsequence.
  @since(version = 0.3.0-dev)
  record lcs-idx-match {
    /// The inclusive start and end positions of the match in the first key's string.
    key1-range: tuple<integer, integer>,
    /// The inclusive start and end positions of the match in the second key's string.
    key2-range: tuple<integer, integer>,
    /// The length of the match, with `with-match-len`.
    len: option<integer>,
  }

  /// The longest common subsequence of two strings, as the ranges matching in each, see `lcs-idx`.
  @since(version = 0.3.0-dev)
  record lcs-idx-reply {
    /// The ranges that match, from the end of the strings to their start.
    matches: list<lcs-idx-match>,
    /// The length of the longest common subsequence.
    len: integer,
  }

  /// The condition for setting the keys, see `msetex`.
  @since(version = 0.3.0-dev)
  variant msetex-precondition {
    /// Only set the keys if all of them do not already exist.
    nx,
    /// Only set the keys if all of them already exist.
    xx,
  }

  /// The condition for setting a key, see `set`.
  @since(version = 0.3.0-dev)
  variant set-precondition {
    /// Only set the key if it does not already exist.
    nx,
    /// Only set the key if it already exists.
    xx,
    /// Set the key if the comparison value matches the existing value.
    ifeq(string-or-bytes),
    /// Set the key if the comparison value does not match the existing value.
    ifne(string-or-bytes),
  }

  /// The expiration to set on a key, see `set`.
  @since(version = 0.3.0-dev)
  variant set-ttl {
    /// Set the specified expire time, in seconds.
    ex(duration-seconds),
    /// Set the specified expire time, in milliseconds.
    px(duration-milliseconds),
    /// Set the specified Unix time at which the key will expire, in seconds.
    exat(unix-time-seconds),
    /// Set the specified Unix time at which the key will expire, in milliseconds.
    pxat(unix-time-milliseconds),
    /// Retain the time to live associated with the keys.
    keepttl,
  }

  /// The expiration to set on the keys, see `msetex`.
  @since(version = 0.3.0-dev)
  type msetex-ttl = set-ttl;

  /// The expiration to set on the fields, see `hsetex`.
  @since(version = 0.3.0-dev)
  type hsetex-ttl = set-ttl;
}

/// RESP request/reply over a pair of value streams, independent of the transport carrying them.
///
/// A transport and a connection are wired together with their streams: take the replies the
/// transport receives, establish the connection with them, hand the requests the connection
/// returns to the transport to send, then await the connection. See `tcp.connect` for a transport
/// that does this for its caller.
///
/// The connection is the mechanics of talking to a server: sending commands and pairing replies
/// with them, subscriptions, push messages, and transactions. Higher level, typed operations are
/// functions in the `commands` interface that borrow the connection.
interface connection {
  @since(version = 0.3.0-dev)
  use types.{connect-opts, duration-milliseconds, error-code, resp-value, string-or-bytes, subscription-event, subscription-target};

  @since(version = 0.3.0-dev)
  resource connection {
    /// Establishes a connection over a transport.
    ///
    /// `replies` are the values the transport receives from the server, and `closed` resolves
    /// when the transport closes, to `ok` for a graceful close or to the error otherwise, see
    /// `tcp.transport.receive`. Returns the requests for the transport to write to the server,
    /// in order, and the connection once it is established.
    ///
    /// The connection sends `HELLO 3`, with the `auth` and `client-name` of `opts`, as its first
    /// command. This pins the connection to RESP3 and confirms the server can be reached. The
    /// future resolves to the connection once HELLO succeeds, or to the error that stopped it.
    /// The rest of `opts` is applied before the connection is returned.
    ///
    /// It then reports the library to the server, `CLIENT SETINFO LIB-NAME componentized:valkey`
    /// and `LIB-VER` with the version of the package, ignoring an error from a server that does
    /// not know CLIENT SETINFO. They survive `reset`, `client-setinfo` replaces them.
    ///
    /// Async so the connection keeps working between commands after it returns, e.g. to read
    /// push messages and to send keep-alive pings.
    @since(version = 0.3.0-dev)
    new: static async func(replies: stream<resp-value>, closed: future<result<_, error-code>>, opts: option<connect-opts>) -> tuple<stream<resp-value>, future<result<connection, error-code>>>;
    /// The server's properties from the reply to HELLO, e.g. `server`, `version` and `mode`.
    @since(version = 0.3.0-dev)
    server-properties: func() -> list<tuple<string, resp-value>>;
    /// Sends a command and waits for its reply.
    ///
    /// Several commands may be in flight at once, replies are paired with commands in the order
    /// the commands were sent.
    ///
    /// For SUBSCRIBE, PSUBSCRIBE, SSUBSCRIBE and their UNSUBSCRIBE counterparts, prefer a
    /// `subscription`, which owns its targets' messages. Once the connection has one, it alone
    /// sends these commands, and they fail with a client error before anything is sent, here,
    /// with `exchange-all`, `emit` and `transaction`.
    ///
    /// RESET, HELLO and CLIENT REPLY always fail with a client error. See `reset` and
    /// `server-properties`, CLIENT REPLY would stop replies from pairing with commands, see
    /// `emit`.
    ///
    /// A command has at least one word, an empty command fails with a client error.
    @since(version = 0.3.0-dev)
    exchange: async func(command: list<string-or-bytes>) -> result<resp-value, error-code>;
    /// Sends the commands one after another, with no other command sent between them, and waits
    /// for every reply.
    ///
    /// Each command has its own result, in order, as if each was sent with `exchange`. Commands
    /// sharing a connection may otherwise be interleaved with other callers' commands, which
    /// matters for a sequence that must not be interrupted, e.g. MULTI, its commands and EXEC.
    @since(version = 0.3.0-dev)
    exchange-all: async func(commands: list<list<string-or-bytes>>) -> list<result<resp-value, error-code>>;
    /// Sends a command without waiting for its reply, resolving once the command is written.
    ///
    /// The server still replies, the reply is discarded when it arrives and an error it reports
    /// is not returned. An implementation may instead ask the server not to reply, e.g. with
    /// `CLIENT REPLY SKIP`.
    ///
    /// A command has at least one word, an empty command fails with a client error.
    @since(version = 0.3.0-dev)
    emit: async func(command: list<string-or-bytes>) -> result<_, error-code>;
    /// Marks the keys to watch, EXEC aborts the next transaction when any of them changed.
    ///
    /// Watched keys belong to the connection, and EXEC, DISCARD or UNWATCH from any caller sharing
    /// it clears them. Use a connection of your own for WATCH, the reads it guards, and the
    /// transaction.
    ///
    /// WATCH key [ key ... ]
    /// https://valkey.io/commands/watch/
    ///
    /// At least one key, no keys fails with a client error.
    @since(version = 0.3.0-dev)
    watch: async func(keys: list<string>) -> result<_, error-code>;
    /// Forgets all the watched keys.
    ///
    /// UNWATCH
    /// https://valkey.io/commands/unwatch/
    @since(version = 0.3.0-dev)
    unwatch: async func() -> result<_, error-code>;
    /// Runs the commands as a transaction, MULTI, each command, then EXEC, with no other command
    /// sent between them, see `exchange-all`.
    ///
    /// Returns none when a watched key changed and the transaction was aborted, otherwise the
    /// reply of each command in order. A command that fails while running is an error value in
    /// its place, the others still ran. A command rejected while queuing, e.g. an unknown
    /// command, fails the transaction with that error, none of the commands ran.
    ///
    /// MULTI and EXEC are only sent as part of a transaction, the commands between them reply
    /// QUEUED rather than their reply.
    ///
    /// MULTI, EXEC
    /// https://valkey.io/commands/multi/
    /// https://valkey.io/commands/exec/
    @since(version = 0.3.0-dev)
    transaction: async func(commands: list<list<string-or-bytes>>) -> result<option<list<resp-value>>, error-code>;
    /// A new subscription, subscribed to nothing yet, see the subscription's `subscribe`.
    ///
    /// From the first subscription, the connection owns its subscriptions: SUBSCRIBE,
    /// PSUBSCRIBE, SSUBSCRIBE and their UNSUBSCRIBE counterparts sent with `exchange` and the like
    /// fail with a client error, so the server's subscriptions stay in step with the
    /// connection's. Subscriptions made with `exchange` before are unsupported. They may keep
    /// delivering to `dead-letters`, the exact behavior is undocumented.
    ///
    /// Fails with a client error when the connection component was built without pub/sub,
    /// e.g. `connection-minimal`. Its push messages are then all dead letters, and SUBSCRIBE and
    /// the like may still be sent with `exchange`.
    @since(version = 0.3.0-dev)
    subscription: func() -> result<subscription, error-code>;
    /// The values nothing else claims, kept apart from replies.
    ///
    /// Push messages that no subscription owns, e.g. client tracking invalidations, messages
    /// and confirmations of SUBSCRIBE sent with `exchange`, or kinds of push messages from a
    /// newer server. Values the server sends unprompted, when no command is waiting for a
    /// reply, are included, e.g. the feed of MONITOR, which are not RESP push values.
    ///
    /// Each call returns a new stream that receives every value arriving after the call,
    /// values arriving while no stream is open are dropped. A stream that falls too far behind
    /// is closed rather than holding up replies, the values it missed are lost.
    @since(version = 0.3.0-dev)
    dead-letters: func() -> stream<resp-value>;
    /// Resets the connection to the state of a new one, then repeats the handshake of `new`.
    ///
    /// RESET discards a transaction in progress, forgets the watched keys, unsubscribes from
    /// every channel, turns off client tracking and the like, selects database 0, and forgets
    /// the client name and the authenticated user. It also switches the connection to RESP2,
    /// so it is followed at once by `HELLO 3` with the `auth` and `client-name` the connection
    /// was established with, with no other command sent between them. `server-properties`
    /// then holds the new reply to HELLO.
    ///
    /// The subscriptions are unsubscribed from every target, each with the reason `reset`, and
    /// stay open for new targets.
    ///
    /// No other command is sent until the handshake succeeds, so none runs on the connection
    /// RESET leaves. When the handshake fails, e.g. the credentials expired since the connection
    /// was established, the connection closes with its error, and the commands queued after
    /// the reset fail with it without being sent. Establish a new connection.
    ///
    /// RESET
    /// https://valkey.io/commands/reset/
    @since(version = 0.3.0-dev)
    reset: async func() -> result<_, error-code>;
    /// Sends PING when no command has been sent and no reply is outstanding for `interval`,
    /// `none` disables it. A PING that fails closes the connection. Disabled by default.
    ///
    /// Unlike TCP keep-alive, a PING counts as activity for the server's idle client timeout,
    /// and works over any transport.
    @since(version = 0.3.0-dev)
    set-keep-alive: func(interval: option<duration-milliseconds>);
  }

  /// The messages of a set of channels, patterns of channels and shard channels, that changes
  /// as targets are subscribed to and unsubscribed from, see `connection.subscription`.
  ///
  /// Subscriptions sharing a connection may overlap, the server stays subscribed to a target while
  /// any subscription has it. The subscription stays open until it is dropped, with or without
  /// targets or streams, then it unsubscribes from its targets. It keeps its connection open.
  @since(version = 0.3.0-dev)
  resource subscription {
    /// Subscribes to the targets, resolving once the server confirms each of them, see
    /// `subscription-event.subscribed`. Targets already subscribed to are left as they are. The
    /// server unsubscribes from a shard channel on its own when its slot moves to another node.
    ///
    /// Each kind of target is subscribed to with its own command, queued with no other command
    /// between them. Every command is sent, even when another fails, and those that succeed
    /// take effect, see `subscription-event.subscribed` and `targets`. The error then holds the
    /// error of each command that failed, e.g. `PSUBSCRIBE: NOPERM ...`. A command is accepted
    /// or refused as a whole, targets of one kind are subscribed to all or none.
    ///
    /// SUBSCRIBE channel [ channel ... ]
    /// PSUBSCRIBE pattern [ pattern ... ]
    /// SSUBSCRIBE shardchannel [ shardchannel ... ]
    /// https://valkey.io/commands/subscribe/
    /// https://valkey.io/commands/psubscribe/
    /// https://valkey.io/commands/ssubscribe/
    ///
    /// At least one target, no targets fails with a client error.
    @since(version = 0.3.0-dev)
    subscribe: async func(targets: list<subscription-target>) -> result<_, error-code>;
    /// The events arriving after the call: targets subscribed to and unsubscribed from, and
    /// messages, in the order they happened.
    ///
    /// Each call returns a new stream, every open stream receives every event. Events arriving
    /// while no stream is open are kept for the next stream, up to 256, later ones are dropped.
    /// Dropping a stream does not unsubscribe, call `events` again for another.
    ///
    /// Pub/sub delivers each message at most once, to all listeners. A stream receives
    /// no events from before it opened, beyond those kept while no stream was open, and does
    /// not start with the current targets, see `targets`. Messages published while nothing
    /// listens are lost, e.g. before a target is subscribed to, after the connection closed, or
    /// past what a lagging stream holds. For delivery that is guaranteed, use a Valkey stream,
    /// see XADD and XREADGROUP.
    ///
    /// The stream closes once the subscription is dropped, the future then resolves to `ok`,
    /// or to the error that closed the connection. A stream that falls too far behind is
    /// closed rather than holding up the connection, its future resolves to `lagged`, and the
    /// events it missed, messages and changes of targets alike, are lost. The future resolves
    /// after the stream delivered what it holds, read the stream to its end first.
    @since(version = 0.3.0-dev)
    events: func() -> tuple<stream<subscription-event>, future<result<_, error-code>>>;
    /// The targets the server confirmed, in the order they were subscribed to, until they are
    /// unsubscribed from.
    ///
    /// Once the connection closes, the targets confirmed until then are still listed, e.g. to
    /// subscribe to them on a new connection. `subscribe` and `unsubscribe` then fail with the
    /// error that closed the connection, and leave the targets as they are.
    @since(version = 0.3.0-dev)
    targets: func() -> list<subscription-target>;
    /// Unsubscribes from the targets, none for every target, resolving once each is
    /// unsubscribed from, see `subscription-event.unsubscribed`. Targets not subscribed to are
    /// left as they are. The server stays subscribed to targets other subscriptions have.
    ///
    /// Each kind of target is unsubscribed from with its own command, as for `subscribe`, e.g.
    /// the `targets` may be given as they are.
    ///
    /// UNSUBSCRIBE [ channel [ channel ... ] ]
    /// PUNSUBSCRIBE [ pattern [ pattern ... ] ]
    /// SUNSUBSCRIBE [ shardchannel [ shardchannel ... ] ]
    /// https://valkey.io/commands/unsubscribe/
    /// https://valkey.io/commands/punsubscribe/
    /// https://valkey.io/commands/sunsubscribe/
    ///
    /// A list of targets has at least one target, otherwise fails with a client error. None
    /// unsubscribes from every target.
    @since(version = 0.3.0-dev)
    unsubscribe: async func(targets: option<list<subscription-target>>) -> result<_, error-code>;
  }
}

/// Typed functions for Valkey's commands, over the mechanics of a connection.
///
/// Each function sends one command and converts its reply. The docs of a function cover what
/// differs from the raw command, see the linked Valkey docs for what the command does. Commands
/// that change the state of the connection itself are on the connection, e.g. SUBSCRIBE, MULTI and
/// EXEC, WATCH, RESET and HELLO.
///
/// The types are those of the `types` interface, used here under names that may change, e.g.
/// renamed to avoid clashing with a function for a new command. Refer to a type through `types`
/// for a name that does not change.
///
/// The functions follow these idioms:
///
/// - Arguments are in the order of the command's words.
/// - A list argument must have at least one item, as the command requires, an empty list fails with
///   a client error before anything is sent. A list the command allows to be left out is an
///   option, none rather than empty.
/// - An optional argument is an option, a flag is a bool, e.g. `replace` for `REPLACE`, and a
///   choice of keywords is an enum or a variant, e.g. `list-side` for `LEFT | RIGHT`.
/// - Durations and points in time are records named for their unit, e.g. `duration-seconds` and
///   `unix-time-milliseconds`.
/// - Keys, fields, patterns and names are `string`. Values, members and payloads are
///   `string-or-bytes`, a reply that is not UTF-8 is `bytes`. Values that are binary by nature, like
///   the serialized values of DUMP and RESTORE, are `bytes`. A reply where a `string` is expected
///   that is not UTF-8 fails with a client error.
/// - A null reply is none, e.g. GET of a key that does not exist.
/// - An integer reply that is `0` or `1` is a bool, e.g. whether HSETNX set the field.
/// - An integer reply with sentinel values is a variant or an enum with a case for each, e.g.
///   `ttl-reply` for TTL's `-2` and `-1`, or none when it stands for nothing, e.g. BITPOS's `-1`.
/// - A reply whose shape an option changes, e.g. with `WITHSCORES`, has a function of its own for
///   that form, e.g. `zrange-withscores`, its docs naming the other forms.
/// - A scan starts with the `start` cursor and resumes with the one it returned, none once it is
///   complete.
/// - An error reply fails with a `server` error. Arguments the client rejects, and replies it cannot
///   convert, fail with a `client` error.
/// - A command that blocks, e.g. BLPOP, or changes the state of the connection, e.g. SELECT,
///   affects every caller sharing the connection, see the command's docs.
interface commands {
  @since(version = 0.3.0-dev)
  use connection.{connection};
  @since(version = 0.3.0-dev)
  use types.{double, error-code, integer, resp-value, duration-seconds, duration-milliseconds, unix-time-seconds, unix-time-milliseconds, cursor, ttl-mode, hexpire-result, hpexpireat-result, hpexpire-result, hexpireat-result, ttl-reply, httl-reply, pttl-reply, hpttl-reply, expiretime-reply, hexpiretime-reply, pexpiretime-reply, hpexpiretime-reply, acl-dryrun-result, acl-log-entry, bgsave-operation, client-type, client-filter, client-pause-mode, client-unblock-type, cluster-bumpepoch-result, cluster-failover-mode, cluster-getslotmigrations-operation, cluster-getslotmigrations-entry, cluster-migrateslots-group, cluster-reset-mode, cluster-setslot-state, commandlog-type, commandlog-entry, slowlog-entry, failover-target, latency-histogram-entry, latency-latest-entry, module-list-entry, role-primary-replica, role-primary, role-replica, role-reply, shutdown-flags, shutdown-save, acl-list-entry, acl-rule, acl-selector-rule, acl-key-rule, acl-channel-rule, acl-command-rule, acl-db-rule, acl-user-rule, bit-range, bitfield-encoding, bitfield-offset, bitfield-overflow, bitfield-get, bitfield-ro-get, bitfield-set, bitfield-incrby, bitfield-operation, bitop-operation, command-key-spec-begin-search, command-key-spec-keyword, command-key-spec-find-keys, command-key-spec-range, command-key-spec-keynum, command-key-spec, command-info-reply, command-reply, command-docs-argument-type, command-docs-argument, command-docs-reply, client-setinfo-attr, client-tracking-mode, client-tracking-options, client-trackinginfo-redirect, client-trackinginfo-reply, command-list-filter, geo-coordinates, geo-unit, geoadd-condition, geosearch-from, geosearch-radius, geosearch-box, geosearch-shape, geosearchstore-shape, geosearch-count, geosearchstore-count, geosearch-with-flags, geosearch-with-result, hpersist-result, hsetex-condition, hsetex-field-condition, key-type, migrate-flags, migrate-auth, list-side, linsert-position, linsert-result, flush-mode, function-list-function, function-list-library, function-stats-running, function-stats-engine, function-stats-reply, limit, sort-opts, sort-ro-opts, sort-order, score-bound, lex-bound, zmpop-end, bzmpop-end, zset-aggregate, zrange-by, zrangestore-by, zrange-withscores-by, zadd-condition, zadd-comparison, stream-id, stream-trim, stream-trim-maxlen, stream-trim-minid, stream-trim-efficiency, xclaim-opts, xinfo-consumers-entry, xinfo-groups-entry, xinfo-stream-reply, xinfo-stream-reply-full, xinfo-stream-reply-full-group, xinfo-stream-reply-full-consumer, xpending-summary, xpending-extended-entry, getex-ttl, hgetex-ttl, lcs-idx-reply, lcs-idx-match, msetex-precondition, msetex-ttl, set-precondition, set-ttl, hsetex-ttl, bytes, string-or-bytes, restore-ttl, function-restore-policy};

  /// Lists the ACL categories, or the commands inside a category.
  ///
  /// ACL CAT [ category ]
  /// https://valkey.io/commands/acl-cat/
  @since(version = 0.3.0-dev)
  acl-cat: async func(connection: borrow<connection>, category: option<string>) -> result<list<string>, error-code>;

  /// Deletes ACL users, and terminates their connections.
  ///
  /// ACL DELUSER username [ username ... ]
  /// https://valkey.io/commands/acl-deluser/
  @since(version = 0.3.0-dev)
  acl-deluser: async func(connection: borrow<connection>, usernames: list<string>) -> result<integer, error-code>;

  /// Simulates the execution of a command by a user, without executing the command.
  ///
  /// ACL DRYRUN username command [ arg [ arg ... ] ]
  /// https://valkey.io/commands/acl-dryrun/
  @since(version = 0.3.0-dev)
  acl-dryrun: async func(connection: borrow<connection>, username: string, command: list<string>) -> result<acl-dryrun-result, error-code>;

  /// Generates a pseudorandom, secure password that can be used to identify ACL users.
  ///
  /// ACL GENPASS [ bits ]
  /// https://valkey.io/commands/acl-genpass/
  @since(version = 0.3.0-dev)
  acl-genpass: async func(connection: borrow<connection>, bits: option<integer>) -> result<string, error-code>;

  /// Lists the ACL rules of a user.
  ///
  /// None when the user does not exist. The rules are as the server normalized them, e.g.
  /// `allkeys` is `~*`. Applied with `acl-setuser`, after `reset`, they recreate the user.
  ///
  /// ACL GETUSER username
  /// https://valkey.io/commands/acl-getuser/
  @since(version = 0.3.0-dev)
  acl-getuser: async func(connection: borrow<connection>, username: string) -> result<option<list<acl-rule>>, error-code>;

  /// Dumps the effective rules in ACL file format.
  ///
  /// ACL LIST
  /// https://valkey.io/commands/acl-list/
  @since(version = 0.3.0-dev)
  acl-list: async func(connection: borrow<connection>) -> result<list<acl-list-entry>, error-code>;

  /// Reloads the rules from the configured ACL file.
  ///
  /// ACL LOAD
  /// https://valkey.io/commands/acl-load/
  @since(version = 0.3.0-dev)
  acl-load: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Lists recent security events generated due to ACL rules.
  ///
  /// See also `acl-log-reset`.
  ///
  /// ACL LOG [ count ]
  /// https://valkey.io/commands/acl-log/
  @since(version = 0.3.0-dev)
  acl-log: async func(connection: borrow<connection>, count: option<integer>) -> result<list<acl-log-entry>, error-code>;

  /// Lists recent security events generated due to ACL rules.
  ///
  /// The `RESET` form, clearing the security events.
  ///
  /// See also `acl-log`.
  ///
  /// ACL LOG RESET
  /// https://valkey.io/commands/acl-log/
  @since(version = 0.3.0-dev)
  acl-log-reset: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Saves the effective ACL rules in the configured ACL file.
  ///
  /// ACL SAVE
  /// https://valkey.io/commands/acl-save/
  @since(version = 0.3.0-dev)
  acl-save: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Creates and modifies an ACL user and its rules.
  ///
  /// ACL SETUSER username [ rule ] [ [ rule ] ... ]
  /// https://valkey.io/commands/acl-setuser/
  @since(version = 0.3.0-dev)
  acl-setuser: async func(connection: borrow<connection>, username: string, rules: option<list<acl-rule>>) -> result<_, error-code>;

  /// Lists all ACL users.
  ///
  /// ACL USERS
  /// https://valkey.io/commands/acl-users/
  @since(version = 0.3.0-dev)
  acl-users: async func(connection: borrow<connection>) -> result<list<string>, error-code>;

  /// Returns the authenticated username of the current connection.
  ///
  /// ACL WHOAMI
  /// https://valkey.io/commands/acl-whoami/
  @since(version = 0.3.0-dev)
  acl-whoami: async func(connection: borrow<connection>) -> result<string, error-code>;

  /// Asynchronously rewrites the append-only file to disk.
  ///
  /// BGREWRITEAOF
  /// https://valkey.io/commands/bgrewriteaof/
  @since(version = 0.3.0-dev)
  bgrewriteaof: async func(connection: borrow<connection>) -> result<string, error-code>;

  /// Asynchronously saves the database(s) to disk.
  ///
  /// BGSAVE [ SCHEDULE | CANCEL ]
  /// https://valkey.io/commands/bgsave/
  @since(version = 0.3.0-dev)
  bgsave: async func(connection: borrow<connection>, operation: option<bgsave-operation>) -> result<string, error-code>;

  /// Terminates open connections.
  ///
  /// CLIENT KILL filter [ filter ... ]
  /// https://valkey.io/commands/client-kill/
  @since(version = 0.3.0-dev)
  client-kill: async func(connection: borrow<connection>, filters: list<client-filter>) -> result<integer, error-code>;

  /// Lists open connections.
  ///
  /// Each connection is a map of its fields, parsed from the server's text, e.g. `id`, `addr` and
  /// `name`.
  ///
  /// CLIENT LIST [ filter [ filter ... ] ]
  /// https://valkey.io/commands/client-list/
  @since(version = 0.3.0-dev)
  client-list: async func(connection: borrow<connection>, filters: option<list<client-filter>>) -> result<list<map<string, string>>, error-code>;

  /// Sets the client eviction mode of the connection.
  ///
  /// It applies to the connection, so to every caller sharing it.
  ///
  /// CLIENT NO-EVICT 〈 ON | OFF 〉
  /// https://valkey.io/commands/client-no-evict/
  @since(version = 0.3.0-dev)
  client-no-evict: async func(connection: borrow<connection>, enabled: bool) -> result<_, error-code>;

  /// Suspends commands processing.
  ///
  /// CLIENT PAUSE timeout [ WRITE | ALL ]
  /// https://valkey.io/commands/client-pause/
  @since(version = 0.3.0-dev)
  client-pause: async func(connection: borrow<connection>, timeout: duration-milliseconds, mode: option<client-pause-mode>) -> result<_, error-code>;

  /// Unblocks a client blocked by a blocking command from a different connection.
  ///
  /// CLIENT UNBLOCK client-id [ TIMEOUT | ERROR ]
  /// https://valkey.io/commands/client-unblock/
  @since(version = 0.3.0-dev)
  client-unblock: async func(connection: borrow<connection>, client-id: integer, unblock-type: option<client-unblock-type>) -> result<bool, error-code>;

  /// Resumes processing commands from paused clients.
  ///
  /// CLIENT UNPAUSE
  /// https://valkey.io/commands/client-unpause/
  @since(version = 0.3.0-dev)
  client-unpause: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Assigns new hash slots to a node.
  ///
  /// CLUSTER ADDSLOTS slot [ slot ... ]
  /// https://valkey.io/commands/cluster-addslots/
  @since(version = 0.3.0-dev)
  cluster-addslots: async func(connection: borrow<connection>, slots: list<u16>) -> result<_, error-code>;

  /// Assigns new hash slot ranges to a node.
  ///
  /// CLUSTER ADDSLOTSRANGE start-slot end-slot [ start-slot end-slot ... ]
  /// https://valkey.io/commands/cluster-addslotsrange/
  @since(version = 0.3.0-dev)
  cluster-addslotsrange: async func(connection: borrow<connection>, ranges: list<tuple<u16, u16>>) -> result<_, error-code>;

  /// Advances the cluster config epoch.
  ///
  /// CLUSTER BUMPEPOCH
  /// https://valkey.io/commands/cluster-bumpepoch/
  @since(version = 0.3.0-dev)
  cluster-bumpepoch: async func(connection: borrow<connection>) -> result<cluster-bumpepoch-result, error-code>;

  /// Cancel all current ongoing slot migration operations.
  ///
  /// CLUSTER CANCELSLOTMIGRATIONS
  /// https://valkey.io/commands/cluster-cancelslotmigrations/
  @since(version = 0.3.0-dev)
  cluster-cancelslotmigrations: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Returns the number of active failure reports for a node.
  ///
  /// CLUSTER COUNT-FAILURE-REPORTS node-id
  /// https://valkey.io/commands/cluster-count-failure-reports/
  @since(version = 0.3.0-dev)
  cluster-count-failure-reports: async func(connection: borrow<connection>, node-id: string) -> result<integer, error-code>;

  /// Sets hash slots as unbound for a node.
  ///
  /// CLUSTER DELSLOTS slot [ slot ... ]
  /// https://valkey.io/commands/cluster-delslots/
  @since(version = 0.3.0-dev)
  cluster-delslots: async func(connection: borrow<connection>, slots: list<u16>) -> result<_, error-code>;

  /// Sets hash slot ranges as unbound for a node.
  ///
  /// CLUSTER DELSLOTSRANGE start-slot end-slot [ start-slot end-slot ... ]
  /// https://valkey.io/commands/cluster-delslotsrange/
  @since(version = 0.3.0-dev)
  cluster-delslotsrange: async func(connection: borrow<connection>, ranges: list<tuple<u16, u16>>) -> result<_, error-code>;

  /// Forces a replica to perform a manual failover of its primary.
  ///
  /// CLUSTER FAILOVER [ FORCE | TAKEOVER ]
  /// https://valkey.io/commands/cluster-failover/
  @since(version = 0.3.0-dev)
  cluster-failover: async func(connection: borrow<connection>, mode: option<cluster-failover-mode>) -> result<_, error-code>;

  /// Deletes all slots information from a node.
  ///
  /// CLUSTER FLUSHSLOTS
  /// https://valkey.io/commands/cluster-flushslots/
  @since(version = 0.3.0-dev)
  cluster-flushslots: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Removes a node from the nodes table.
  ///
  /// CLUSTER FORGET node-id
  /// https://valkey.io/commands/cluster-forget/
  @since(version = 0.3.0-dev)
  cluster-forget: async func(connection: borrow<connection>, node-id: string) -> result<_, error-code>;

  /// Gets the status of ongoing and recently finished slot import and export operations.
  ///
  /// CLUSTER GETSLOTMIGRATIONS
  /// https://valkey.io/commands/cluster-getslotmigrations/
  @since(version = 0.3.0-dev)
  cluster-getslotmigrations: async func(connection: borrow<connection>) -> result<list<cluster-getslotmigrations-entry>, error-code>;

  /// Forces a node to handshake with another node.
  ///
  /// CLUSTER MEET ip port [ cluster-bus-port ]
  /// https://valkey.io/commands/cluster-meet/
  @since(version = 0.3.0-dev)
  cluster-meet: async func(connection: borrow<connection>, ip: string, port: u16, cluster-bus-port: option<u16>) -> result<_, error-code>;

  /// Migrate the given slots from this node to the specified nodes.
  ///
  /// CLUSTER MIGRATESLOTS SLOTSRANGE start-slot end-slot [ start-slot end-slot ... ] NODE node-id [ AUTH username password ] [ SLOTSRANGE ... ]
  /// https://valkey.io/commands/cluster-migrateslots/
  @since(version = 0.3.0-dev)
  cluster-migrateslots: async func(connection: borrow<connection>, migrations: list<cluster-migrateslots-group>) -> result<_, error-code>;

  /// Lists the replica nodes of a primary node.
  ///
  /// CLUSTER REPLICAS node-id
  /// https://valkey.io/commands/cluster-replicas/
  @since(version = 0.3.0-dev)
  cluster-replicas: async func(connection: borrow<connection>, node-id: string) -> result<list<string>, error-code>;

  /// Configures a node as replica of a primary node or detaches a replica from its primary.
  ///
  /// None detaches the node from its primary, `NO ONE`.
  ///
  /// CLUSTER REPLICATE 〈 node-id | NO ONE 〉
  /// https://valkey.io/commands/cluster-replicate/
  @since(version = 0.3.0-dev)
  cluster-replicate: async func(connection: borrow<connection>, node-id: option<string>) -> result<_, error-code>;

  /// Resets a node.
  ///
  /// CLUSTER RESET [ HARD | SOFT ]
  /// https://valkey.io/commands/cluster-reset/
  @since(version = 0.3.0-dev)
  cluster-reset: async func(connection: borrow<connection>, mode: option<cluster-reset-mode>) -> result<_, error-code>;

  /// Forces a node to save the cluster configuration to disk.
  ///
  /// CLUSTER SAVECONFIG
  /// https://valkey.io/commands/cluster-saveconfig/
  @since(version = 0.3.0-dev)
  cluster-saveconfig: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Sets the configuration epoch for a new node.
  ///
  /// CLUSTER SET-CONFIG-EPOCH config-epoch
  /// https://valkey.io/commands/cluster-set-config-epoch/
  @since(version = 0.3.0-dev)
  cluster-set-config-epoch: async func(connection: borrow<connection>, config-epoch: integer) -> result<_, error-code>;

  /// Binds a hash slot to a node.
  ///
  /// CLUSTER SETSLOT slot 〈 IMPORTING node-id | MIGRATING node-id | NODE node-id | STABLE 〉 [ TIMEOUT timeout ]
  /// https://valkey.io/commands/cluster-setslot/
  @since(version = 0.3.0-dev)
  cluster-setslot: async func(connection: borrow<connection>, slot: u16, state: cluster-setslot-state, timeout: option<duration-milliseconds>) -> result<_, error-code>;

  /// Returns the specified command log's entries.
  ///
  /// COMMANDLOG GET count 〈 slow | large-request | large-reply 〉
  /// https://valkey.io/commands/commandlog-get/
  @since(version = 0.3.0-dev)
  commandlog-get: async func(connection: borrow<connection>, count: integer, %type: commandlog-type) -> result<list<commandlog-entry>, error-code>;

  /// Returns the number of entries in the specified type of command log.
  ///
  /// COMMANDLOG LEN 〈 slow | large-request | large-reply 〉
  /// https://valkey.io/commands/commandlog-len/
  @since(version = 0.3.0-dev)
  commandlog-len: async func(connection: borrow<connection>, %type: commandlog-type) -> result<integer, error-code>;

  /// Clears all entries from the specified type of command log.
  ///
  /// COMMANDLOG RESET 〈 slow | large-request | large-reply 〉
  /// https://valkey.io/commands/commandlog-reset/
  @since(version = 0.3.0-dev)
  commandlog-reset: async func(connection: borrow<connection>, %type: commandlog-type) -> result<_, error-code>;

  /// Returns the effective values of configuration parameters.
  ///
  /// CONFIG GET parameter [ parameter ... ]
  /// https://valkey.io/commands/config-get/
  @since(version = 0.3.0-dev)
  config-get: async func(connection: borrow<connection>, parameters: list<string>) -> result<map<string, string>, error-code>;

  /// Resets the server's statistics.
  ///
  /// CONFIG RESETSTAT
  /// https://valkey.io/commands/config-resetstat/
  @since(version = 0.3.0-dev)
  config-resetstat: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Persists the effective configuration to file.
  ///
  /// CONFIG REWRITE
  /// https://valkey.io/commands/config-rewrite/
  @since(version = 0.3.0-dev)
  config-rewrite: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Sets configuration parameters in-flight.
  ///
  /// CONFIG SET parameter value [ parameter value ... ]
  /// https://valkey.io/commands/config-set/
  @since(version = 0.3.0-dev)
  config-set: async func(connection: borrow<connection>, parameters-and-values: list<tuple<string, string>>) -> result<_, error-code>;

  /// Starts a coordinated failover from a server to one of its replicas.
  ///
  /// FAILOVER [ TO host port [ FORCE ] ] [ ABORT ] [ TIMEOUT milliseconds ]
  /// https://valkey.io/commands/failover/
  @since(version = 0.3.0-dev)
  failover: async func(connection: borrow<connection>, target: option<failover-target>, abort: bool, timeout: option<duration-milliseconds>) -> result<_, error-code>;

  /// Returns the Unix timestamp of the last successful save to disk.
  ///
  /// LASTSAVE
  /// https://valkey.io/commands/lastsave/
  @since(version = 0.3.0-dev)
  lastsave: async func(connection: borrow<connection>) -> result<unix-time-seconds, error-code>;

  /// Returns a human-readable latency analysis report.
  ///
  /// LATENCY DOCTOR
  /// https://valkey.io/commands/latency-doctor/
  @since(version = 0.3.0-dev)
  latency-doctor: async func(connection: borrow<connection>) -> result<string, error-code>;

  /// Returns a latency graph for an event.
  ///
  /// LATENCY GRAPH event
  /// https://valkey.io/commands/latency-graph/
  @since(version = 0.3.0-dev)
  latency-graph: async func(connection: borrow<connection>, event: string) -> result<string, error-code>;

  /// Returns the cumulative distribution of latencies of a subset or all commands.
  ///
  /// LATENCY HISTOGRAM [ command [ command ... ] ]
  /// https://valkey.io/commands/latency-histogram/
  @since(version = 0.3.0-dev)
  latency-histogram: async func(connection: borrow<connection>, commands: option<list<string>>) -> result<map<string, latency-histogram-entry>, error-code>;

  /// Returns timestamp-latency samples for an event.
  ///
  /// LATENCY HISTORY event
  /// https://valkey.io/commands/latency-history/
  @since(version = 0.3.0-dev)
  latency-history: async func(connection: borrow<connection>, event: string) -> result<list<tuple<unix-time-seconds, duration-milliseconds>>, error-code>;

  /// Returns the latest latency samples for all events.
  ///
  /// LATENCY LATEST
  /// https://valkey.io/commands/latency-latest/
  @since(version = 0.3.0-dev)
  latency-latest: async func(connection: borrow<connection>) -> result<list<latency-latest-entry>, error-code>;

  /// Resets the latency data for one or more events.
  ///
  /// LATENCY RESET [ event [ event ... ] ]
  /// https://valkey.io/commands/latency-reset/
  @since(version = 0.3.0-dev)
  latency-reset: async func(connection: borrow<connection>, events: option<list<string>>) -> result<integer, error-code>;

  /// Returns all loaded modules.
  ///
  /// MODULE LIST
  /// https://valkey.io/commands/module-list/
  @since(version = 0.3.0-dev)
  module-list: async func(connection: borrow<connection>) -> result<list<module-list-entry>, error-code>;

  /// Loads a module.
  ///
  /// MODULE LOAD path [ arg [ arg ... ] ]
  /// https://valkey.io/commands/module-load/
  @since(version = 0.3.0-dev)
  module-load: async func(connection: borrow<connection>, path: string, args: option<list<string>>) -> result<_, error-code>;

  /// Loads a module using extended parameters.
  ///
  /// MODULE LOADEX path [ CONFIG name value [ CONFIG name value ... ] ] [ ARGS args [ args ... ] ]
  /// https://valkey.io/commands/module-loadex/
  @since(version = 0.3.0-dev)
  module-loadex: async func(connection: borrow<connection>, path: string, configs: option<list<tuple<string, string>>>, args: option<list<string>>) -> result<_, error-code>;

  /// Unloads a module.
  ///
  /// MODULE UNLOAD name
  /// https://valkey.io/commands/module-unload/
  @since(version = 0.3.0-dev)
  module-unload: async func(connection: borrow<connection>, name: string) -> result<_, error-code>;

  /// Configures a server as replica of another, or promotes it to a primary.
  ///
  /// None makes the server a primary, `NO ONE`.
  ///
  /// REPLICAOF 〈 host port | NO ONE 〉
  /// https://valkey.io/commands/replicaof/
  @since(version = 0.3.0-dev)
  replicaof: async func(connection: borrow<connection>, primary: option<tuple<string, u16>>) -> result<string, error-code>;

  /// Returns the replication role.
  ///
  /// ROLE
  /// https://valkey.io/commands/role/
  @since(version = 0.3.0-dev)
  role: async func(connection: borrow<connection>) -> result<role-reply, error-code>;

  /// Synchronously saves the database(s) to disk.
  ///
  /// SAVE
  /// https://valkey.io/commands/save/
  @since(version = 0.3.0-dev)
  save: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Synchronously saves the database(s) to disk and shuts down the server.
  ///
  /// The server closes the connection once it stops, so a shutdown that succeeds fails the call
  /// with a closed error.
  ///
  /// See also `shutdown-abort`.
  ///
  /// SHUTDOWN [ NOSAVE | SAVE ] [ NOW ] [ FORCE ] [ SAFE ] [ FAILOVER ]
  /// https://valkey.io/commands/shutdown/
  @since(version = 0.3.0-dev)
  shutdown: async func(connection: borrow<connection>, save: option<shutdown-save>, modifiers: shutdown-flags) -> result<_, error-code>;

  /// Synchronously saves the database(s) to disk and shuts down the server.
  ///
  /// The `ABORT` form, aborting a shutdown in progress.
  ///
  /// See also `shutdown`.
  ///
  /// SHUTDOWN ABORT
  /// https://valkey.io/commands/shutdown/
  @since(version = 0.3.0-dev)
  shutdown-abort: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Returns the slow log's entries.
  ///
  /// SLOWLOG GET [ count ]
  /// https://valkey.io/commands/slowlog-get/
  @since(version = 0.3.0-dev)
  slowlog-get: async func(connection: borrow<connection>, count: option<integer>) -> result<list<slowlog-entry>, error-code>;

  /// Returns the number of entries in the slow log.
  ///
  /// SLOWLOG LEN
  /// https://valkey.io/commands/slowlog-len/
  @since(version = 0.3.0-dev)
  slowlog-len: async func(connection: borrow<connection>) -> result<integer, error-code>;

  /// Clears all entries from the slow log.
  ///
  /// SLOWLOG RESET
  /// https://valkey.io/commands/slowlog-reset/
  @since(version = 0.3.0-dev)
  slowlog-reset: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Counts the number of set bits (population counting) in a string.
  ///
  /// BITCOUNT key [ start [ end [ BYTE | BIT ] ] ]
  /// https://valkey.io/commands/bitcount/
  @since(version = 0.3.0-dev)
  bitcount: async func(connection: borrow<connection>, key: string, range: option<bit-range>) -> result<integer, error-code>;

  /// Performs arbitrary bitfield integer operations on strings.
  ///
  /// None for a write that failed with `OVERFLOW FAIL`.
  ///
  /// BITFIELD key [ GET encoding offset | [ OVERFLOW WRAP | SAT | FAIL ] 〈 SET encoding offset value | INCRBY encoding offset increment 〉 [ GET encoding offset | [ OVERFLOW WRAP | SAT | FAIL ] 〈 SET encoding offset value | INCRBY encoding offset increment 〉 ... ] ]
  /// https://valkey.io/commands/bitfield/
  @since(version = 0.3.0-dev)
  bitfield: async func(connection: borrow<connection>, key: string, operations: option<list<bitfield-operation>>) -> result<list<option<integer>>, error-code>;

  /// Performs arbitrary read-only bitfield integer operations on strings.
  ///
  /// BITFIELD_RO key [ GET encoding offset [ GET encoding offset ... ] ]
  /// https://valkey.io/commands/bitfield_ro/
  @since(version = 0.3.0-dev)
  bitfield-ro: async func(connection: borrow<connection>, key: string, gets: option<list<bitfield-ro-get>>) -> result<list<integer>, error-code>;

  /// Performs bitwise operations on multiple strings, and stores the result.
  ///
  /// BITOP 〈 AND | OR | XOR | NOT 〉 destkey key [ key ... ]
  /// https://valkey.io/commands/bitop/
  @since(version = 0.3.0-dev)
  bitop: async func(connection: borrow<connection>, destination: string, operation: bitop-operation) -> result<integer, error-code>;

  /// Finds the first set (1) or clear (0) bit in a string.
  ///
  /// None when no bit matches, the server's `-1`.
  ///
  /// BITPOS key bit [ start [ end [ BYTE | BIT ] ] ]
  /// https://valkey.io/commands/bitpos/
  @since(version = 0.3.0-dev)
  bitpos: async func(connection: borrow<connection>, key: string, bit: bool, range: option<bit-range>) -> result<option<integer>, error-code>;

  /// Returns a bit value by offset.
  ///
  /// GETBIT key offset
  /// https://valkey.io/commands/getbit/
  @since(version = 0.3.0-dev)
  getbit: async func(connection: borrow<connection>, key: string, offset: u64) -> result<bool, error-code>;

  /// Sets or clears the bit at offset of the string value.
  ///
  /// SETBIT key offset value
  /// https://valkey.io/commands/setbit/
  @since(version = 0.3.0-dev)
  setbit: async func(connection: borrow<connection>, key: string, offset: u64, value: bool) -> result<bool, error-code>;

  /// Signals that a cluster client is following an -ASK redirect.
  ///
  /// It applies to the next command on the connection, which may be another caller's when the
  /// connection is shared. Use a connection of your own.
  ///
  /// ASKING
  /// https://valkey.io/commands/asking/
  @since(version = 0.3.0-dev)
  asking: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Authenticates the connection.
  ///
  /// AUTH [ username ] password
  /// https://valkey.io/commands/auth/
  @since(version = 0.3.0-dev)
  auth: async func(connection: borrow<connection>, username: option<string>, password: string) -> result<_, error-code>;

  /// Instructs the server whether to track the keys in the next request.
  ///
  /// It applies to the next command on the connection, which may be another caller's when the
  /// connection is shared. Use a connection of your own.
  ///
  /// CLIENT CACHING 〈 YES | NO 〉
  /// https://valkey.io/commands/client-caching/
  @since(version = 0.3.0-dev)
  client-caching: async func(connection: borrow<connection>, enabled: bool) -> result<_, error-code>;

  /// A client claims its capability.
  ///
  /// CLIENT CAPA capability [ capability ... ]
  /// https://valkey.io/commands/client-capa/
  @since(version = 0.3.0-dev)
  client-capa: async func(connection: borrow<connection>, capabilities: list<string>) -> result<_, error-code>;

  /// Returns the name of the connection.
  ///
  /// CLIENT GETNAME
  /// https://valkey.io/commands/client-getname/
  @since(version = 0.3.0-dev)
  client-getname: async func(connection: borrow<connection>) -> result<option<string>, error-code>;

  /// Returns the unique client ID of the connection.
  ///
  /// CLIENT ID
  /// https://valkey.io/commands/client-id/
  @since(version = 0.3.0-dev)
  client-id: async func(connection: borrow<connection>) -> result<integer, error-code>;

  /// Marks this client as an import source when the server is in import mode.
  ///
  /// CLIENT IMPORT-SOURCE 〈 ON | OFF 〉
  /// https://valkey.io/commands/client-import-source/
  @since(version = 0.3.0-dev)
  client-import-source: async func(connection: borrow<connection>, enabled: bool) -> result<_, error-code>;

  /// Returns information about the connection.
  ///
  /// A map of the fields, parsed from the server's text, e.g. `id`, `addr` and `name`.
  ///
  /// CLIENT INFO
  /// https://valkey.io/commands/client-info/
  @since(version = 0.3.0-dev)
  client-info: async func(connection: borrow<connection>) -> result<map<string, string>, error-code>;

  /// Controls whether commands sent by the client affect the LRU/LFU of accessed keys.
  ///
  /// It applies to the connection, so to every caller sharing it.
  ///
  /// CLIENT NO-TOUCH 〈 ON | OFF 〉
  /// https://valkey.io/commands/client-no-touch/
  @since(version = 0.3.0-dev)
  client-no-touch: async func(connection: borrow<connection>, enabled: bool) -> result<_, error-code>;

  /// Sets information specific to the client or connection.
  ///
  /// CLIENT SETINFO 〈 LIB-NAME libname | LIB-VER libver 〉
  /// https://valkey.io/commands/client-setinfo/
  @since(version = 0.3.0-dev)
  client-setinfo: async func(connection: borrow<connection>, attr: client-setinfo-attr) -> result<_, error-code>;

  /// Sets the connection name.
  ///
  /// CLIENT SETNAME connection-name
  /// https://valkey.io/commands/client-setname/
  @since(version = 0.3.0-dev)
  client-setname: async func(connection: borrow<connection>, connection-name: string) -> result<_, error-code>;

  /// Controls server-assisted client-side caching for the connection.
  ///
  /// Invalidations arrive as push messages, see `connection.dead-letters`. It applies to the
  /// connection, so to every caller sharing it.
  ///
  /// CLIENT TRACKING 〈 ON | OFF 〉 [ PREFIX prefix [ PREFIX prefix ... ] ] [ BCAST ] [ OPTIN ] [ OPTOUT ] [ NOLOOP ]
  /// https://valkey.io/commands/client-tracking/
  @since(version = 0.3.0-dev)
  client-tracking: async func(connection: borrow<connection>, options: option<client-tracking-options>) -> result<_, error-code>;

  /// Returns information about server-assisted client-side caching for the connection.
  ///
  /// CLIENT TRACKINGINFO
  /// https://valkey.io/commands/client-trackinginfo/
  @since(version = 0.3.0-dev)
  client-trackinginfo: async func(connection: borrow<connection>) -> result<client-trackinginfo-reply, error-code>;

  /// Returns detailed information about all commands.
  ///
  /// COMMAND
  /// https://valkey.io/commands/command/
  @since(version = 0.3.0-dev)
  command: async func(connection: borrow<connection>) -> result<list<command-reply>, error-code>;

  /// Returns a count of commands.
  ///
  /// COMMAND COUNT
  /// https://valkey.io/commands/command-count/
  @since(version = 0.3.0-dev)
  command-count: async func(connection: borrow<connection>) -> result<integer, error-code>;

  /// Returns documentary information about one, multiple or all commands.
  ///
  /// A container is followed by its subcommands. Commands that do not exist are left out.
  ///
  /// COMMAND DOCS [ command-name [ command-name ... ] ]
  /// https://valkey.io/commands/command-docs/
  @since(version = 0.3.0-dev)
  command-docs: async func(connection: borrow<connection>, command-names: option<list<string>>) -> result<list<command-docs-reply>, error-code>;

  /// Extracts the key names from an arbitrary command.
  ///
  /// COMMAND GETKEYS command [ arg [ arg ... ] ]
  /// https://valkey.io/commands/command-getkeys/
  @since(version = 0.3.0-dev)
  command-getkeys: async func(connection: borrow<connection>, command: list<string>) -> result<list<string>, error-code>;

  /// Extracts the key names and access flags for an arbitrary command.
  ///
  /// COMMAND GETKEYSANDFLAGS command [ arg [ arg ... ] ]
  /// https://valkey.io/commands/command-getkeysandflags/
  @since(version = 0.3.0-dev)
  command-getkeysandflags: async func(connection: borrow<connection>, command: list<string>) -> result<list<tuple<string, list<string>>>, error-code>;

  /// Returns information about one, multiple or all commands.
  ///
  /// A container is followed by its subcommands. Commands that do not exist are left out.
  ///
  /// COMMAND INFO [ command-name [ command-name ... ] ]
  /// https://valkey.io/commands/command-info/
  @since(version = 0.3.0-dev)
  command-info: async func(connection: borrow<connection>, command-names: option<list<string>>) -> result<list<command-info-reply>, error-code>;

  /// Returns a list of command names.
  ///
  /// COMMAND LIST [ FILTERBY 〈 MODULE module-name | ACLCAT category | PATTERN pattern 〉 ]
  /// https://valkey.io/commands/command-list/
  @since(version = 0.3.0-dev)
  command-list: async func(connection: borrow<connection>, filter: option<command-list-filter>) -> result<list<string>, error-code>;

  /// Returns the given string.
  ///
  /// ECHO message
  /// https://valkey.io/commands/echo/
  @since(version = 0.3.0-dev)
  echo: async func(connection: borrow<connection>, message: string-or-bytes) -> result<string-or-bytes, error-code>;

  /// Returns the server's liveliness response.
  ///
  /// PING [ message ]
  /// https://valkey.io/commands/ping/
  @since(version = 0.3.0-dev)
  ping: async func(connection: borrow<connection>, message: option<string-or-bytes>) -> result<_, error-code>;

  /// Enables read-only queries for a connection to a Valkey replica node.
  ///
  /// It applies to the connection, so to every caller sharing it.
  ///
  /// READONLY
  /// https://valkey.io/commands/readonly/
  @since(version = 0.3.0-dev)
  readonly: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Enables read-write queries for a connection to a Valkey replica node.
  ///
  /// It applies to the connection, so to every caller sharing it.
  ///
  /// READWRITE
  /// https://valkey.io/commands/readwrite/
  @since(version = 0.3.0-dev)
  readwrite: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Changes the selected database.
  ///
  /// It applies to the connection, so to every caller sharing it.
  ///
  /// SELECT index
  /// https://valkey.io/commands/select/
  @since(version = 0.3.0-dev)
  select: async func(connection: borrow<connection>, index: integer) -> result<_, error-code>;

  /// Blocks until the asynchronous replication of all preceding write commands sent by the connection is completed.
  ///
  /// The connection waits too, replies to commands sent after it on the connection wait behind
  /// it. Use a connection of your own.
  ///
  /// WAIT numreplicas timeout
  /// https://valkey.io/commands/wait/
  @since(version = 0.3.0-dev)
  wait: async func(connection: borrow<connection>, numreplicas: integer, timeout: duration-milliseconds) -> result<integer, error-code>;

  /// Blocks until all of the preceding write commands sent by the connection are written to the append-only file of the primary and/or replicas.
  ///
  /// The connection waits too, replies to commands sent after it on the connection wait behind
  /// it. Use a connection of your own.
  ///
  /// WAITAOF numlocal numreplicas timeout
  /// https://valkey.io/commands/waitaof/
  @since(version = 0.3.0-dev)
  waitaof: async func(connection: borrow<connection>, numlocal: integer, numreplicas: integer, timeout: duration-milliseconds) -> result<tuple<integer, integer>, error-code>;

  /// Adds one or more members to a geospatial index.
  ///
  /// GEOADD key [ NX | XX ] [ CH ] longitude latitude member [ longitude latitude member ... ]
  /// https://valkey.io/commands/geoadd/
  @since(version = 0.3.0-dev)
  geoadd: async func(connection: borrow<connection>, key: string, condition: option<geoadd-condition>, changed: bool, coordinates-and-members: list<tuple<geo-coordinates, string-or-bytes>>) -> result<integer, error-code>;

  /// Returns the distance between two members of a geospatial index.
  ///
  /// GEODIST key member1 member2 [ m | km | ft | mi ]
  /// https://valkey.io/commands/geodist/
  @since(version = 0.3.0-dev)
  geodist: async func(connection: borrow<connection>, key: string, member1: string-or-bytes, member2: string-or-bytes, unit: option<geo-unit>) -> result<option<double>, error-code>;

  /// Returns members from a geospatial index as geohash strings.
  ///
  /// GEOHASH key [ member [ member ... ] ]
  /// https://valkey.io/commands/geohash/
  @since(version = 0.3.0-dev)
  geohash: async func(connection: borrow<connection>, key: string, members: option<list<string-or-bytes>>) -> result<list<option<string>>, error-code>;

  /// Returns the longitude and latitude of members from a geospatial index.
  ///
  /// GEOPOS key [ member [ member ... ] ]
  /// https://valkey.io/commands/geopos/
  @since(version = 0.3.0-dev)
  geopos: async func(connection: borrow<connection>, key: string, members: option<list<string-or-bytes>>) -> result<list<option<geo-coordinates>>, error-code>;

  /// Queries a geospatial index for members inside an area of a box, circle, or a polygon.
  ///
  /// See also `geosearch-with`.
  ///
  /// GEOSEARCH key [ FROMMEMBER member | FROMLONLAT longitude latitude ] 〈 BYRADIUS radius 〈 m | km | ft | mi 〉 | BYBOX width height 〈 m | km | ft | mi 〉 | BYPOLYGON num-vertices longitude latitude [ longitude latitude ... ] 〉 [ ASC | DESC ] [ COUNT count [ ANY ] ]
  /// https://valkey.io/commands/geosearch/
  @since(version = 0.3.0-dev)
  geosearch: async func(connection: borrow<connection>, key: string, shape: geosearch-shape, order: option<sort-order>, count: option<geosearch-count>) -> result<list<string-or-bytes>, error-code>;

  /// Queries a geospatial index for members inside an area of a box, circle, or a polygon.
  ///
  /// Returns each member with the details asked for, `WITHCOORD`, `WITHDIST` and `WITHHASH`.
  ///
  /// See also `geosearch`.
  ///
  /// GEOSEARCH key [ FROMMEMBER member | FROMLONLAT longitude latitude ] 〈 BYRADIUS radius 〈 m | km | ft | mi 〉 | BYBOX width height 〈 m | km | ft | mi 〉 | BYPOLYGON num-vertices longitude latitude [ longitude latitude ... ] 〉 [ ASC | DESC ] [ COUNT count [ ANY ] ] [ WITHCOORD ] [ WITHDIST ] [ WITHHASH ]
  /// https://valkey.io/commands/geosearch/
  @since(version = 0.3.0-dev)
  geosearch-with: async func(connection: borrow<connection>, key: string, shape: geosearch-shape, order: option<sort-order>, count: option<geosearch-count>, details: geosearch-with-flags) -> result<list<geosearch-with-result>, error-code>;

  /// Queries a geospatial index for members inside an area of a box, a circle, or a polygon, optionally stores the result.
  ///
  /// GEOSEARCHSTORE destination source [ FROMMEMBER member | FROMLONLAT longitude latitude ] 〈 BYRADIUS radius 〈 m | km | ft | mi 〉 | BYBOX width height 〈 m | km | ft | mi 〉 | BYPOLYGON num-vertices longitude latitude [ longitude latitude ... ] 〉 [ ASC | DESC ] [ COUNT count [ ANY ] ] [ STOREDIST ]
  /// https://valkey.io/commands/geosearchstore/
  @since(version = 0.3.0-dev)
  geosearchstore: async func(connection: borrow<connection>, destination: string, source: string, shape: geosearchstore-shape, order: option<sort-order>, count: option<geosearchstore-count>, storedist: bool) -> result<integer, error-code>;

  /// Deletes one or more fields and their values from a hash.
  ///
  /// HDEL key field [ field ... ]
  /// https://valkey.io/commands/hdel/
  @since(version = 0.3.0-dev)
  hdel: async func(connection: borrow<connection>, key: string, fields: list<string>) -> result<integer, error-code>;

  /// Determines whether a field exists in a hash.
  ///
  /// HEXISTS key field
  /// https://valkey.io/commands/hexists/
  @since(version = 0.3.0-dev)
  hexists: async func(connection: borrow<connection>, key: string, field: string) -> result<bool, error-code>;

  /// Sets the expiration time of one or more hash fields in seconds.
  ///
  /// HEXPIRE key seconds [ NX | XX | GT | LT ] FIELDS numfields field [ field ... ]
  /// https://valkey.io/commands/hexpire/
  @since(version = 0.3.0-dev)
  hexpire: async func(connection: borrow<connection>, key: string, seconds: duration-seconds, mode: option<ttl-mode>, fields: list<string>) -> result<list<hexpire-result>, error-code>;

  /// Sets the expiration time of one or more hash fields to a Unix timestamp.
  ///
  /// HEXPIREAT key unix-time-seconds [ NX | XX | GT | LT ] FIELDS numfields field [ field ... ]
  /// https://valkey.io/commands/hexpireat/
  @since(version = 0.3.0-dev)
  hexpireat: async func(connection: borrow<connection>, key: string, seconds: unix-time-seconds, mode: option<ttl-mode>, fields: list<string>) -> result<list<hexpireat-result>, error-code>;

  /// Returns Unix timestamps in seconds since the epoch at which the given key's field(s) will expire.
  ///
  /// HEXPIRETIME key FIELDS numfields field [ field ... ]
  /// https://valkey.io/commands/hexpiretime/
  @since(version = 0.3.0-dev)
  hexpiretime: async func(connection: borrow<connection>, key: string, fields: list<string>) -> result<list<hexpiretime-reply>, error-code>;

  /// Returns the value of a field in a hash.
  ///
  /// HGET key field
  /// https://valkey.io/commands/hget/
  @since(version = 0.3.0-dev)
  hget: async func(connection: borrow<connection>, key: string, field: string) -> result<option<string-or-bytes>, error-code>;

  /// Returns all fields and values in a hash.
  ///
  /// HGETALL key
  /// https://valkey.io/commands/hgetall/
  @since(version = 0.3.0-dev)
  hgetall: async func(connection: borrow<connection>, key: string) -> result<map<string, string-or-bytes>, error-code>;

  /// Returns the values of one or more fields and deletes them from a hash.
  ///
  /// HGETDEL key FIELDS numfields field [ field ... ]
  /// https://valkey.io/commands/hgetdel/
  @since(version = 0.3.0-dev)
  hgetdel: async func(connection: borrow<connection>, key: string, fields: list<string>) -> result<list<option<string-or-bytes>>, error-code>;

  /// Gets the value of one or more fields of a given hash key, and optionally sets their expiration time or time-to-live (TTL).
  ///
  /// HGETEX key [ EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | PERSIST ] FIELDS numfields field [ field ... ]
  /// https://valkey.io/commands/hgetex/
  @since(version = 0.3.0-dev)
  hgetex: async func(connection: borrow<connection>, key: string, ttl: option<hgetex-ttl>, fields: list<string>) -> result<list<option<string-or-bytes>>, error-code>;

  /// Increments the integer value of a field in a hash by a number.
  ///
  /// HINCRBY key field increment
  /// https://valkey.io/commands/hincrby/
  @since(version = 0.3.0-dev)
  hincrby: async func(connection: borrow<connection>, key: string, field: string, increment: integer) -> result<integer, error-code>;

  /// Increments the floating point value of a field by a number.
  ///
  /// HINCRBYFLOAT key field increment
  /// https://valkey.io/commands/hincrbyfloat/
  @since(version = 0.3.0-dev)
  hincrbyfloat: async func(connection: borrow<connection>, key: string, field: string, increment: double) -> result<double, error-code>;

  /// Returns all fields in a hash.
  ///
  /// HKEYS key
  /// https://valkey.io/commands/hkeys/
  @since(version = 0.3.0-dev)
  hkeys: async func(connection: borrow<connection>, key: string) -> result<list<string>, error-code>;

  /// Returns the number of fields in a hash.
  ///
  /// HLEN key
  /// https://valkey.io/commands/hlen/
  @since(version = 0.3.0-dev)
  hlen: async func(connection: borrow<connection>, key: string) -> result<integer, error-code>;

  /// Returns the values of all fields in a hash.
  ///
  /// HMGET key field [ field ... ]
  /// https://valkey.io/commands/hmget/
  @since(version = 0.3.0-dev)
  hmget: async func(connection: borrow<connection>, key: string, fields: list<string>) -> result<list<option<string-or-bytes>>, error-code>;

  /// Sets the values of multiple fields.
  ///
  /// HMSET key field value [ field value ... ]
  /// https://valkey.io/commands/hmset/
  @since(version = 0.3.0-dev)
  hmset: async func(connection: borrow<connection>, key: string, field-and-values: list<tuple<string, string-or-bytes>>) -> result<_, error-code>;

  /// Remove the existing expiration on a hash key's field(s).
  ///
  /// HPERSIST key FIELDS numfields field [ field ... ]
  /// https://valkey.io/commands/hpersist/
  @since(version = 0.3.0-dev)
  hpersist: async func(connection: borrow<connection>, key: string, fields: list<string>) -> result<list<hpersist-result>, error-code>;

  /// Sets the expiration time of one or more hash fields in milliseconds.
  ///
  /// HPEXPIRE key milliseconds [ NX | XX | GT | LT ] FIELDS numfields field [ field ... ]
  /// https://valkey.io/commands/hpexpire/
  @since(version = 0.3.0-dev)
  hpexpire: async func(connection: borrow<connection>, key: string, milliseconds: duration-milliseconds, mode: option<ttl-mode>, fields: list<string>) -> result<list<hpexpire-result>, error-code>;

  /// Sets the expiration time of one or more hash fields to a Unix timestamp in milliseconds.
  ///
  /// HPEXPIREAT key unix-time-milliseconds [ NX | XX | GT | LT ] FIELDS numfields field [ field ... ]
  /// https://valkey.io/commands/hpexpireat/
  @since(version = 0.3.0-dev)
  hpexpireat: async func(connection: borrow<connection>, key: string, milliseconds: unix-time-milliseconds, mode: option<ttl-mode>, fields: list<string>) -> result<list<hpexpireat-result>, error-code>;

  /// Returns the Unix timestamp in milliseconds since Unix epoch at which the given key's field(s) will expire.
  ///
  /// HPEXPIRETIME key FIELDS numfields field [ field ... ]
  /// https://valkey.io/commands/hpexpiretime/
  @since(version = 0.3.0-dev)
  hpexpiretime: async func(connection: borrow<connection>, key: string, fields: list<string>) -> result<list<hpexpiretime-reply>, error-code>;

  /// Returns the remaining time to live in milliseconds of a hash key's field(s) that have an associated expiration.
  ///
  /// HPTTL key FIELDS numfields field [ field ... ]
  /// https://valkey.io/commands/hpttl/
  @since(version = 0.3.0-dev)
  hpttl: async func(connection: borrow<connection>, key: string, fields: list<string>) -> result<list<hpttl-reply>, error-code>;

  /// Returns one or more random fields from a hash.
  ///
  /// Without a count, at most one field.
  ///
  /// See also `hrandfield-withvalues`.
  ///
  /// HRANDFIELD key [ count ]
  /// https://valkey.io/commands/hrandfield/
  @since(version = 0.3.0-dev)
  hrandfield: async func(connection: borrow<connection>, key: string, count: option<integer>) -> result<list<string>, error-code>;

  /// Returns one or more random fields from a hash.
  ///
  /// The `WITHVALUES` form, the fields and their values.
  ///
  /// See also `hrandfield`.
  ///
  /// HRANDFIELD key count WITHVALUES
  /// https://valkey.io/commands/hrandfield/
  @since(version = 0.3.0-dev)
  hrandfield-withvalues: async func(connection: borrow<connection>, key: string, count: integer) -> result<list<tuple<string, string-or-bytes>>, error-code>;

  /// Iterates over fields and values of a hash.
  ///
  /// See also `hscan-novalues`.
  ///
  /// HSCAN key cursor [ MATCH pattern ] [ COUNT count ]
  /// https://valkey.io/commands/hscan/
  @since(version = 0.3.0-dev)
  hscan: async func(connection: borrow<connection>, key: string, cursor: cursor, match: option<string>, count: option<integer>) -> result<tuple<option<cursor>, map<string, string-or-bytes>>, error-code>;

  /// Iterates over fields and values of a hash.
  ///
  /// The `NOVALUES` form, the fields only.
  ///
  /// See also `hscan`.
  ///
  /// HSCAN key cursor [ MATCH pattern ] [ COUNT count ] NOVALUES
  /// https://valkey.io/commands/hscan/
  @since(version = 0.3.0-dev)
  hscan-novalues: async func(connection: borrow<connection>, key: string, cursor: cursor, match: option<string>, count: option<integer>) -> result<tuple<option<cursor>, list<string>>, error-code>;

  /// Creates or modifies the value of a field in a hash.
  ///
  /// HSET key field value [ field value ... ]
  /// https://valkey.io/commands/hset/
  @since(version = 0.3.0-dev)
  hset: async func(connection: borrow<connection>, key: string, field-and-values: list<tuple<string, string-or-bytes>>) -> result<integer, error-code>;

  /// Sets the value of one or more fields of a given hash key, and optionally sets their expiration time.
  ///
  /// HSETEX key [ NX | XX ] [ FNX | FXX ] [ EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL ] FIELDS numfields field value [ field value ... ]
  /// https://valkey.io/commands/hsetex/
  @since(version = 0.3.0-dev)
  hsetex: async func(connection: borrow<connection>, key: string, condition: option<hsetex-condition>, field-condition: option<hsetex-field-condition>, ttl: option<hsetex-ttl>, field-and-values: list<tuple<string, string-or-bytes>>) -> result<bool, error-code>;

  /// Sets the value of a field in a hash only when the field doesn't exist.
  ///
  /// HSETNX key field value
  /// https://valkey.io/commands/hsetnx/
  @since(version = 0.3.0-dev)
  hsetnx: async func(connection: borrow<connection>, key: string, field: string, value: string-or-bytes) -> result<bool, error-code>;

  /// Returns the length of the value of a field.
  ///
  /// HSTRLEN key field
  /// https://valkey.io/commands/hstrlen/
  @since(version = 0.3.0-dev)
  hstrlen: async func(connection: borrow<connection>, key: string, field: string) -> result<integer, error-code>;

  /// Returns the remaining time to live (in seconds) of a hash key's field(s) that have an associated expiration.
  ///
  /// HTTL key FIELDS numfields field [ field ... ]
  /// https://valkey.io/commands/httl/
  @since(version = 0.3.0-dev)
  httl: async func(connection: borrow<connection>, key: string, fields: list<string>) -> result<list<httl-reply>, error-code>;

  /// Returns all values in a hash.
  ///
  /// HVALS key
  /// https://valkey.io/commands/hvals/
  @since(version = 0.3.0-dev)
  hvals: async func(connection: borrow<connection>, key: string) -> result<list<string-or-bytes>, error-code>;

  /// Adds elements to a HyperLogLog key.
  ///
  /// PFADD key [ element [ element ... ] ]
  /// https://valkey.io/commands/pfadd/
  @since(version = 0.3.0-dev)
  pfadd: async func(connection: borrow<connection>, key: string, elements: option<list<string-or-bytes>>) -> result<bool, error-code>;

  /// Returns the approximated cardinality of the set(s) observed by the HyperLogLog key(s).
  ///
  /// PFCOUNT key [ key ... ]
  /// https://valkey.io/commands/pfcount/
  @since(version = 0.3.0-dev)
  pfcount: async func(connection: borrow<connection>, keys: list<string>) -> result<integer, error-code>;

  /// Merges one or more HyperLogLog values into a single key.
  ///
  /// PFMERGE destkey [ sourcekey [ sourcekey ... ] ]
  /// https://valkey.io/commands/pfmerge/
  @since(version = 0.3.0-dev)
  pfmerge: async func(connection: borrow<connection>, destination: string, sources: option<list<string>>) -> result<_, error-code>;

  /// Removes all keys from the target slot.
  ///
  /// CLUSTER FLUSHSLOT slot [ ASYNC | SYNC ]
  /// https://valkey.io/commands/cluster-flushslot/
  @since(version = 0.3.0-dev)
  cluster-flushslot: async func(connection: borrow<connection>, slot: u16, mode: option<flush-mode>) -> result<_, error-code>;

  /// Iterates over the keys in the cluster.
  ///
  /// The cursor carries the slot, for clients to route each call to the node that owns it.
  ///
  /// CLUSTERSCAN cursor [ MATCH match-pattern ] [ COUNT count ] [ TYPE type ] [ SLOT slot ]
  /// https://valkey.io/commands/clusterscan/
  @since(version = 0.3.0-dev)
  clusterscan: async func(connection: borrow<connection>, cursor: cursor, match: option<string>, count: option<integer>, %type: option<key-type>, slot: option<u16>) -> result<tuple<option<cursor>, list<string>>, error-code>;

  /// Copies the value of a key to a new key.
  ///
  /// COPY source destination [ DB destination-db ] [ REPLACE ]
  /// https://valkey.io/commands/copy/
  @since(version = 0.3.0-dev)
  copy: async func(connection: borrow<connection>, source: string, destination: string, destination-db: option<integer>, replace: bool) -> result<bool, error-code>;

  /// Returns the number of keys in the database.
  ///
  /// DBSIZE
  /// https://valkey.io/commands/dbsize/
  @since(version = 0.3.0-dev)
  dbsize: async func(connection: borrow<connection>) -> result<integer, error-code>;

  /// Deletes one or more keys.
  ///
  /// DEL key [ key ... ]
  /// https://valkey.io/commands/del/
  @since(version = 0.3.0-dev)
  del: async func(connection: borrow<connection>, keys: list<string>) -> result<integer, error-code>;

  /// Returns a serialized representation of the value stored at a key.
  ///
  /// DUMP key
  /// https://valkey.io/commands/dump/
  @since(version = 0.3.0-dev)
  dump: async func(connection: borrow<connection>, key: string) -> result<option<bytes>, error-code>;

  /// Determines whether one or more keys exist.
  ///
  /// EXISTS key [ key ... ]
  /// https://valkey.io/commands/exists/
  @since(version = 0.3.0-dev)
  exists: async func(connection: borrow<connection>, keys: list<string>) -> result<integer, error-code>;

  /// Sets the expiration time of a key in seconds.
  ///
  /// EXPIRE key seconds [ NX | XX | GT | LT ]
  /// https://valkey.io/commands/expire/
  @since(version = 0.3.0-dev)
  expire: async func(connection: borrow<connection>, key: string, seconds: duration-seconds, mode: option<ttl-mode>) -> result<bool, error-code>;

  /// Sets the expiration time of a key to a Unix timestamp.
  ///
  /// EXPIREAT key unix-time-seconds [ NX | XX | GT | LT ]
  /// https://valkey.io/commands/expireat/
  @since(version = 0.3.0-dev)
  expireat: async func(connection: borrow<connection>, key: string, seconds: unix-time-seconds, mode: option<ttl-mode>) -> result<bool, error-code>;

  /// Returns the expiration time of a key as a Unix timestamp.
  ///
  /// EXPIRETIME key
  /// https://valkey.io/commands/expiretime/
  @since(version = 0.3.0-dev)
  expiretime: async func(connection: borrow<connection>, key: string) -> result<expiretime-reply, error-code>;

  /// Removes all keys from all databases.
  ///
  /// FLUSHALL [ ASYNC | SYNC ]
  /// https://valkey.io/commands/flushall/
  @since(version = 0.3.0-dev)
  flushall: async func(connection: borrow<connection>, mode: option<flush-mode>) -> result<_, error-code>;

  /// Removes all keys from the current database.
  ///
  /// FLUSHDB [ ASYNC | SYNC ]
  /// https://valkey.io/commands/flushdb/
  @since(version = 0.3.0-dev)
  flushdb: async func(connection: borrow<connection>, mode: option<flush-mode>) -> result<_, error-code>;

  /// Returns all key names that match a pattern.
  ///
  /// KEYS pattern
  /// https://valkey.io/commands/keys/
  @since(version = 0.3.0-dev)
  keys: async func(connection: borrow<connection>, pattern: string) -> result<list<string>, error-code>;

  /// Atomically transfers a key from one instance to another.
  ///
  /// False when none of the keys exist, the server's `NOKEY`.
  ///
  /// MIGRATE host port "" destination-db timeout [ COPY ] [ REPLACE ] [ AUTH password | AUTH2 username password ] KEYS key [ key ... ]
  /// https://valkey.io/commands/migrate/
  @since(version = 0.3.0-dev)
  migrate: async func(connection: borrow<connection>, host: string, port: u16, destination-db: integer, timeout: duration-milliseconds, options: migrate-flags, auth: option<migrate-auth>, keys: list<string>) -> result<bool, error-code>;

  /// Moves a key to another database.
  ///
  /// MOVE key db [ REPLACE ]
  /// https://valkey.io/commands/move/
  @since(version = 0.3.0-dev)
  move: async func(connection: borrow<connection>, key: string, db: integer, replace: bool) -> result<bool, error-code>;

  /// Returns the internal encoding of an object.
  ///
  /// OBJECT ENCODING key
  /// https://valkey.io/commands/object-encoding/
  @since(version = 0.3.0-dev)
  object-encoding: async func(connection: borrow<connection>, key: string) -> result<option<string>, error-code>;

  /// Returns the logarithmic access frequency counter of an object.
  ///
  /// OBJECT FREQ key
  /// https://valkey.io/commands/object-freq/
  @since(version = 0.3.0-dev)
  object-freq: async func(connection: borrow<connection>, key: string) -> result<option<integer>, error-code>;

  /// Returns the time since the last access to an object.
  ///
  /// OBJECT IDLETIME key
  /// https://valkey.io/commands/object-idletime/
  @since(version = 0.3.0-dev)
  object-idletime: async func(connection: borrow<connection>, key: string) -> result<option<duration-seconds>, error-code>;

  /// Returns the reference count of a value of a key.
  ///
  /// OBJECT REFCOUNT key
  /// https://valkey.io/commands/object-refcount/
  @since(version = 0.3.0-dev)
  object-refcount: async func(connection: borrow<connection>, key: string) -> result<option<integer>, error-code>;

  /// Removes the expiration time of a key.
  ///
  /// PERSIST key
  /// https://valkey.io/commands/persist/
  @since(version = 0.3.0-dev)
  persist: async func(connection: borrow<connection>, key: string) -> result<bool, error-code>;

  /// Sets the expiration time of a key in milliseconds.
  ///
  /// PEXPIRE key milliseconds [ NX | XX | GT | LT ]
  /// https://valkey.io/commands/pexpire/
  @since(version = 0.3.0-dev)
  pexpire: async func(connection: borrow<connection>, key: string, milliseconds: duration-milliseconds, mode: option<ttl-mode>) -> result<bool, error-code>;

  /// Sets the expiration time of a key to a Unix milliseconds timestamp.
  ///
  /// PEXPIREAT key unix-time-milliseconds [ NX | XX | GT | LT ]
  /// https://valkey.io/commands/pexpireat/
  @since(version = 0.3.0-dev)
  pexpireat: async func(connection: borrow<connection>, key: string, milliseconds: unix-time-milliseconds, mode: option<ttl-mode>) -> result<bool, error-code>;

  /// Returns the expiration time of a key as a Unix milliseconds timestamp.
  ///
  /// PEXPIRETIME key
  /// https://valkey.io/commands/pexpiretime/
  @since(version = 0.3.0-dev)
  pexpiretime: async func(connection: borrow<connection>, key: string) -> result<pexpiretime-reply, error-code>;

  /// Returns the expiration time in milliseconds of a key.
  ///
  /// PTTL key
  /// https://valkey.io/commands/pttl/
  @since(version = 0.3.0-dev)
  pttl: async func(connection: borrow<connection>, key: string) -> result<pttl-reply, error-code>;

  /// Returns a random key name from the database.
  ///
  /// RANDOMKEY
  /// https://valkey.io/commands/randomkey/
  @since(version = 0.3.0-dev)
  randomkey: async func(connection: borrow<connection>) -> result<option<string>, error-code>;

  /// Renames a key and overwrites the destination.
  ///
  /// RENAME key newkey
  /// https://valkey.io/commands/rename/
  @since(version = 0.3.0-dev)
  rename: async func(connection: borrow<connection>, key: string, newkey: string) -> result<_, error-code>;

  /// Renames a key only when the target key name doesn't exist.
  ///
  /// RENAMENX key newkey
  /// https://valkey.io/commands/renamenx/
  @since(version = 0.3.0-dev)
  renamenx: async func(connection: borrow<connection>, key: string, newkey: string) -> result<bool, error-code>;

  /// Creates a key from the serialized representation of a value.
  ///
  /// A `ttl` of none restores the key without an expiration, `0`, `expire-at` adds `ABSTTL`.
  ///
  /// RESTORE key ttl serialized-value [ REPLACE ] [ ABSTTL ] [ IDLETIME seconds ] [ FREQ frequency ]
  /// https://valkey.io/commands/restore/
  @since(version = 0.3.0-dev)
  restore: async func(connection: borrow<connection>, key: string, ttl: option<restore-ttl>, serialized-value: bytes, replace: bool, idletime: option<duration-seconds>, freq: option<integer>) -> result<_, error-code>;

  /// An internal command for migrating keys in a cluster.
  ///
  /// A `ttl` of none restores the key without an expiration, `0`, `expire-at` adds `ABSTTL`.
  ///
  /// RESTORE-ASKING key ttl serialized-value [ REPLACE ] [ ABSTTL ] [ IDLETIME seconds ] [ FREQ frequency ]
  /// https://valkey.io/commands/restore-asking/
  @since(version = 0.3.0-dev)
  restore-asking: async func(connection: borrow<connection>, key: string, ttl: option<restore-ttl>, serialized-value: bytes, replace: bool, idletime: option<duration-seconds>, freq: option<integer>) -> result<_, error-code>;

  /// Iterates over the key names in the database.
  ///
  /// SCAN cursor [ MATCH pattern ] [ COUNT count ] [ TYPE type ]
  /// https://valkey.io/commands/scan/
  @since(version = 0.3.0-dev)
  scan: async func(connection: borrow<connection>, cursor: cursor, match: option<string>, count: option<integer>, %type: option<key-type>) -> result<tuple<option<cursor>, list<string>>, error-code>;

  /// Swaps two databases.
  ///
  /// SWAPDB index1 index2
  /// https://valkey.io/commands/swapdb/
  @since(version = 0.3.0-dev)
  swapdb: async func(connection: borrow<connection>, index1: integer, index2: integer) -> result<_, error-code>;

  /// Returns the number of existing keys out of those specified after updating the time they were last accessed.
  ///
  /// TOUCH key [ key ... ]
  /// https://valkey.io/commands/touch/
  @since(version = 0.3.0-dev)
  touch: async func(connection: borrow<connection>, keys: list<string>) -> result<integer, error-code>;

  /// Returns the expiration time in seconds of a key.
  ///
  /// TTL key
  /// https://valkey.io/commands/ttl/
  @since(version = 0.3.0-dev)
  ttl: async func(connection: borrow<connection>, key: string) -> result<ttl-reply, error-code>;

  /// Determines the type of value stored at a key.
  ///
  /// None when the key does not exist, the server's `none`.
  ///
  /// TYPE key
  /// https://valkey.io/commands/type/
  @since(version = 0.3.0-dev)
  %type: async func(connection: borrow<connection>, key: string) -> result<option<key-type>, error-code>;

  /// Asynchronously deletes one or more keys.
  ///
  /// UNLINK key [ key ... ]
  /// https://valkey.io/commands/unlink/
  @since(version = 0.3.0-dev)
  unlink: async func(connection: borrow<connection>, keys: list<string>) -> result<integer, error-code>;

  /// Pops an element from a list, pushes it to another list and returns it.
  ///
  /// Returns none when the timeout passed. The connection waits too, replies to commands sent
  /// after it on the connection wait behind it. Use a connection of your own.
  ///
  /// BLMOVE source destination 〈 LEFT | RIGHT 〉 〈 LEFT | RIGHT 〉 timeout
  /// https://valkey.io/commands/blmove/
  @since(version = 0.3.0-dev)
  blmove: async func(connection: borrow<connection>, source: string, destination: string, wherefrom: list-side, whereto: list-side, timeout: duration-milliseconds) -> result<option<string-or-bytes>, error-code>;

  /// Pops the first element from one of multiple lists.
  ///
  /// Returns none when the timeout passed. The connection waits too, replies to commands sent
  /// after it on the connection wait behind it. Use a connection of your own.
  ///
  /// BLMPOP timeout numkeys key [ key ... ] 〈 LEFT | RIGHT 〉 [ COUNT count ]
  /// https://valkey.io/commands/blmpop/
  @since(version = 0.3.0-dev)
  blmpop: async func(connection: borrow<connection>, timeout: duration-milliseconds, keys: list<string>, end: list-side, count: option<integer>) -> result<option<tuple<string, list<string-or-bytes>>>, error-code>;

  /// Removes and returns the first element in a list.
  ///
  /// Returns none when the timeout passed. The connection waits too, replies to commands sent
  /// after it on the connection wait behind it. Use a connection of your own.
  ///
  /// BLPOP key [ key ... ] timeout
  /// https://valkey.io/commands/blpop/
  @since(version = 0.3.0-dev)
  blpop: async func(connection: borrow<connection>, keys: list<string>, timeout: duration-milliseconds) -> result<option<tuple<string, string-or-bytes>>, error-code>;

  /// Removes and returns the last element in a list.
  ///
  /// Returns none when the timeout passed. The connection waits too, replies to commands sent
  /// after it on the connection wait behind it. Use a connection of your own.
  ///
  /// BRPOP key [ key ... ] timeout
  /// https://valkey.io/commands/brpop/
  @since(version = 0.3.0-dev)
  brpop: async func(connection: borrow<connection>, keys: list<string>, timeout: duration-milliseconds) -> result<option<tuple<string, string-or-bytes>>, error-code>;

  /// Pops an element from a list, pushes it to another list and returns it.
  ///
  /// Returns none when the timeout passed. The connection waits too, replies to commands sent
  /// after it on the connection wait behind it. Use a connection of your own.
  ///
  /// BRPOPLPUSH source destination timeout
  /// https://valkey.io/commands/brpoplpush/
  @since(version = 0.3.0-dev)
  brpoplpush: async func(connection: borrow<connection>, source: string, destination: string, timeout: duration-milliseconds) -> result<option<string-or-bytes>, error-code>;

  /// Returns an element from a list by its index.
  ///
  /// LINDEX key index
  /// https://valkey.io/commands/lindex/
  @since(version = 0.3.0-dev)
  lindex: async func(connection: borrow<connection>, key: string, index: integer) -> result<option<string-or-bytes>, error-code>;

  /// Inserts an element before or after another element in a list.
  ///
  /// LINSERT key 〈 BEFORE | AFTER 〉 pivot element
  /// https://valkey.io/commands/linsert/
  @since(version = 0.3.0-dev)
  linsert: async func(connection: borrow<connection>, key: string, position: linsert-position, pivot: string-or-bytes, element: string-or-bytes) -> result<linsert-result, error-code>;

  /// Returns the length of a list.
  ///
  /// LLEN key
  /// https://valkey.io/commands/llen/
  @since(version = 0.3.0-dev)
  llen: async func(connection: borrow<connection>, key: string) -> result<integer, error-code>;

  /// Returns an element after popping it from one list and pushing it to another.
  ///
  /// LMOVE source destination 〈 LEFT | RIGHT 〉 〈 LEFT | RIGHT 〉
  /// https://valkey.io/commands/lmove/
  @since(version = 0.3.0-dev)
  lmove: async func(connection: borrow<connection>, source: string, destination: string, wherefrom: list-side, whereto: list-side) -> result<option<string-or-bytes>, error-code>;

  /// Returns multiple elements from a list after removing them.
  ///
  /// LMPOP numkeys key [ key ... ] 〈 LEFT | RIGHT 〉 [ COUNT count ]
  /// https://valkey.io/commands/lmpop/
  @since(version = 0.3.0-dev)
  lmpop: async func(connection: borrow<connection>, keys: list<string>, end: list-side, count: option<integer>) -> result<option<tuple<string, list<string-or-bytes>>>, error-code>;

  /// Returns and removes one or more elements from the beginning of a list.
  ///
  /// Without a count, at most one element.
  ///
  /// LPOP key [ count ]
  /// https://valkey.io/commands/lpop/
  @since(version = 0.3.0-dev)
  lpop: async func(connection: borrow<connection>, key: string, count: option<integer>) -> result<list<string-or-bytes>, error-code>;

  /// Returns the index of matching elements in a list.
  ///
  /// Without a count, at most one position.
  ///
  /// LPOS key element [ RANK rank ] [ COUNT num-matches ] [ MAXLEN len ]
  /// https://valkey.io/commands/lpos/
  @since(version = 0.3.0-dev)
  lpos: async func(connection: borrow<connection>, key: string, element: string-or-bytes, rank: option<integer>, count: option<integer>, maxlen: option<integer>) -> result<list<integer>, error-code>;

  /// Prepends one or more elements to a list.
  ///
  /// LPUSH key element [ element ... ]
  /// https://valkey.io/commands/lpush/
  @since(version = 0.3.0-dev)
  lpush: async func(connection: borrow<connection>, key: string, elements: list<string-or-bytes>) -> result<integer, error-code>;

  /// Prepends one or more elements to a list only when the list exists.
  ///
  /// LPUSHX key element [ element ... ]
  /// https://valkey.io/commands/lpushx/
  @since(version = 0.3.0-dev)
  lpushx: async func(connection: borrow<connection>, key: string, elements: list<string-or-bytes>) -> result<integer, error-code>;

  /// Returns a range of elements from a list.
  ///
  /// LRANGE key start stop
  /// https://valkey.io/commands/lrange/
  @since(version = 0.3.0-dev)
  lrange: async func(connection: borrow<connection>, key: string, start: integer, stop: integer) -> result<list<string-or-bytes>, error-code>;

  /// Removes elements from a list.
  ///
  /// LREM key count element
  /// https://valkey.io/commands/lrem/
  @since(version = 0.3.0-dev)
  lrem: async func(connection: borrow<connection>, key: string, count: integer, element: string-or-bytes) -> result<integer, error-code>;

  /// Sets the value of an element in a list by its index.
  ///
  /// LSET key index element
  /// https://valkey.io/commands/lset/
  @since(version = 0.3.0-dev)
  lset: async func(connection: borrow<connection>, key: string, index: integer, element: string-or-bytes) -> result<_, error-code>;

  /// Removes elements from both ends of a list.
  ///
  /// LTRIM key start stop
  /// https://valkey.io/commands/ltrim/
  @since(version = 0.3.0-dev)
  ltrim: async func(connection: borrow<connection>, key: string, start: integer, stop: integer) -> result<_, error-code>;

  /// Returns and removes one or more elements from the end of a list.
  ///
  /// Without a count, at most one element.
  ///
  /// RPOP key [ count ]
  /// https://valkey.io/commands/rpop/
  @since(version = 0.3.0-dev)
  rpop: async func(connection: borrow<connection>, key: string, count: option<integer>) -> result<list<string-or-bytes>, error-code>;

  /// Returns the last element of a list after removing and pushing it to another list.
  ///
  /// RPOPLPUSH source destination
  /// https://valkey.io/commands/rpoplpush/
  @since(version = 0.3.0-dev)
  rpoplpush: async func(connection: borrow<connection>, source: string, destination: string) -> result<option<string-or-bytes>, error-code>;

  /// Appends one or more elements to a list.
  ///
  /// RPUSH key element [ element ... ]
  /// https://valkey.io/commands/rpush/
  @since(version = 0.3.0-dev)
  rpush: async func(connection: borrow<connection>, key: string, elements: list<string-or-bytes>) -> result<integer, error-code>;

  /// Appends one or more elements to a list only when the list exists.
  ///
  /// RPUSHX key element [ element ... ]
  /// https://valkey.io/commands/rpushx/
  @since(version = 0.3.0-dev)
  rpushx: async func(connection: borrow<connection>, key: string, elements: list<string-or-bytes>) -> result<integer, error-code>;

  /// Posts a message to a channel.
  ///
  /// PUBLISH channel message
  /// https://valkey.io/commands/publish/
  @since(version = 0.3.0-dev)
  publish: async func(connection: borrow<connection>, channel: string, message: string-or-bytes) -> result<integer, error-code>;

  /// Returns the active channels.
  ///
  /// PUBSUB CHANNELS [ pattern ]
  /// https://valkey.io/commands/pubsub-channels/
  @since(version = 0.3.0-dev)
  pubsub-channels: async func(connection: borrow<connection>, pattern: option<string>) -> result<list<string>, error-code>;

  /// Returns a count of unique pattern subscriptions.
  ///
  /// PUBSUB NUMPAT
  /// https://valkey.io/commands/pubsub-numpat/
  @since(version = 0.3.0-dev)
  pubsub-numpat: async func(connection: borrow<connection>) -> result<integer, error-code>;

  /// Returns a count of subscribers to channels.
  ///
  /// PUBSUB NUMSUB [ channel ] [ [ channel ] ... ]
  /// https://valkey.io/commands/pubsub-numsub/
  @since(version = 0.3.0-dev)
  pubsub-numsub: async func(connection: borrow<connection>, channels: option<list<string>>) -> result<map<string, integer>, error-code>;

  /// Returns the active shard channels.
  ///
  /// PUBSUB SHARDCHANNELS [ pattern ]
  /// https://valkey.io/commands/pubsub-shardchannels/
  @since(version = 0.3.0-dev)
  pubsub-shardchannels: async func(connection: borrow<connection>, pattern: option<string>) -> result<list<string>, error-code>;

  /// Returns the count of subscribers of shard channels.
  ///
  /// PUBSUB SHARDNUMSUB [ shardchannel [ shardchannel ... ] ]
  /// https://valkey.io/commands/pubsub-shardnumsub/
  @since(version = 0.3.0-dev)
  pubsub-shardnumsub: async func(connection: borrow<connection>, shardchannels: option<list<string>>) -> result<map<string, integer>, error-code>;

  /// Posts a message to a shard channel.
  ///
  /// SPUBLISH shardchannel message
  /// https://valkey.io/commands/spublish/
  @since(version = 0.3.0-dev)
  spublish: async func(connection: borrow<connection>, shardchannel: string, message: string-or-bytes) -> result<integer, error-code>;

  /// Executes a server-side Lua script.
  ///
  /// An error the script returns fails the call.
  ///
  /// EVAL script numkeys [ key [ key ... ] ] [ arg [ arg ... ] ]
  /// https://valkey.io/commands/eval/
  @since(version = 0.3.0-dev)
  eval: async func(connection: borrow<connection>, script: string, keys: option<list<string>>, args: option<list<string-or-bytes>>) -> result<resp-value, error-code>;

  /// Executes a read-only server-side Lua script.
  ///
  /// An error the script returns fails the call.
  ///
  /// EVAL_RO script numkeys [ key [ key ... ] ] [ arg [ arg ... ] ]
  /// https://valkey.io/commands/eval_ro/
  @since(version = 0.3.0-dev)
  eval-ro: async func(connection: borrow<connection>, script: string, keys: option<list<string>>, args: option<list<string-or-bytes>>) -> result<resp-value, error-code>;

  /// Executes a server-side Lua script by SHA1 digest.
  ///
  /// An error the script returns fails the call.
  ///
  /// EVALSHA sha1 numkeys [ key [ key ... ] ] [ arg [ arg ... ] ]
  /// https://valkey.io/commands/evalsha/
  @since(version = 0.3.0-dev)
  evalsha: async func(connection: borrow<connection>, sha1: string, keys: option<list<string>>, args: option<list<string-or-bytes>>) -> result<resp-value, error-code>;

  /// Executes a read-only server-side Lua script by SHA1 digest.
  ///
  /// An error the script returns fails the call.
  ///
  /// EVALSHA_RO sha1 numkeys [ key [ key ... ] ] [ arg [ arg ... ] ]
  /// https://valkey.io/commands/evalsha_ro/
  @since(version = 0.3.0-dev)
  evalsha-ro: async func(connection: borrow<connection>, sha1: string, keys: option<list<string>>, args: option<list<string-or-bytes>>) -> result<resp-value, error-code>;

  /// Invokes a function.
  ///
  /// An error the function returns fails the call.
  ///
  /// FCALL function numkeys [ key [ key ... ] ] [ arg [ arg ... ] ]
  /// https://valkey.io/commands/fcall/
  @since(version = 0.3.0-dev)
  fcall: async func(connection: borrow<connection>, function: string, keys: option<list<string>>, args: option<list<string-or-bytes>>) -> result<resp-value, error-code>;

  /// Invokes a read-only function.
  ///
  /// An error the function returns fails the call.
  ///
  /// FCALL_RO function numkeys [ key [ key ... ] ] [ arg [ arg ... ] ]
  /// https://valkey.io/commands/fcall_ro/
  @since(version = 0.3.0-dev)
  fcall-ro: async func(connection: borrow<connection>, function: string, keys: option<list<string>>, args: option<list<string-or-bytes>>) -> result<resp-value, error-code>;

  /// Deletes a library and its functions.
  ///
  /// FUNCTION DELETE library-name
  /// https://valkey.io/commands/function-delete/
  @since(version = 0.3.0-dev)
  function-delete: async func(connection: borrow<connection>, library-name: string) -> result<_, error-code>;

  /// Dumps all libraries into a serialized binary payload.
  ///
  /// FUNCTION DUMP
  /// https://valkey.io/commands/function-dump/
  @since(version = 0.3.0-dev)
  function-dump: async func(connection: borrow<connection>) -> result<bytes, error-code>;

  /// Deletes all libraries and functions.
  ///
  /// FUNCTION FLUSH [ ASYNC | SYNC ]
  /// https://valkey.io/commands/function-flush/
  @since(version = 0.3.0-dev)
  function-flush: async func(connection: borrow<connection>, mode: option<flush-mode>) -> result<_, error-code>;

  /// Terminates a function during execution.
  ///
  /// FUNCTION KILL
  /// https://valkey.io/commands/function-kill/
  @since(version = 0.3.0-dev)
  function-kill: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Returns information about all libraries.
  ///
  /// FUNCTION LIST [ LIBRARYNAME library-name-pattern ] [ WITHCODE ]
  /// https://valkey.io/commands/function-list/
  @since(version = 0.3.0-dev)
  function-list: async func(connection: borrow<connection>, library-name-pattern: option<string>, withcode: bool) -> result<list<function-list-library>, error-code>;

  /// Creates a library.
  ///
  /// FUNCTION LOAD [ REPLACE ] function-code
  /// https://valkey.io/commands/function-load/
  @since(version = 0.3.0-dev)
  function-load: async func(connection: borrow<connection>, replace: bool, function-code: string) -> result<string, error-code>;

  /// Restores all libraries from a payload.
  ///
  /// FUNCTION RESTORE serialized-value [ FLUSH | APPEND | REPLACE ]
  /// https://valkey.io/commands/function-restore/
  @since(version = 0.3.0-dev)
  function-restore: async func(connection: borrow<connection>, serialized-value: bytes, policy: option<function-restore-policy>) -> result<_, error-code>;

  /// Returns information about a function during execution.
  ///
  /// FUNCTION STATS
  /// https://valkey.io/commands/function-stats/
  @since(version = 0.3.0-dev)
  function-stats: async func(connection: borrow<connection>) -> result<function-stats-reply, error-code>;

  /// Determines whether server-side Lua scripts exist in the script cache.
  ///
  /// SCRIPT EXISTS sha1 [ sha1 ... ]
  /// https://valkey.io/commands/script-exists/
  @since(version = 0.3.0-dev)
  script-exists: async func(connection: borrow<connection>, sha1s: list<string>) -> result<list<bool>, error-code>;

  /// Removes all server-side Lua scripts from the script cache.
  ///
  /// SCRIPT FLUSH [ ASYNC | SYNC ]
  /// https://valkey.io/commands/script-flush/
  @since(version = 0.3.0-dev)
  script-flush: async func(connection: borrow<connection>, mode: option<flush-mode>) -> result<_, error-code>;

  /// Terminates a server-side Lua script during execution.
  ///
  /// SCRIPT KILL
  /// https://valkey.io/commands/script-kill/
  @since(version = 0.3.0-dev)
  script-kill: async func(connection: borrow<connection>) -> result<_, error-code>;

  /// Loads a server-side Lua script to the script cache.
  ///
  /// SCRIPT LOAD script
  /// https://valkey.io/commands/script-load/
  @since(version = 0.3.0-dev)
  script-load: async func(connection: borrow<connection>, script: string) -> result<string, error-code>;

  /// Show server-side Lua script in the script cache.
  ///
  /// SCRIPT SHOW sha1
  /// https://valkey.io/commands/script-show/
  @since(version = 0.3.0-dev)
  script-show: async func(connection: borrow<connection>, sha1: string) -> result<string, error-code>;

  /// Adds one or more members to a set.
  ///
  /// SADD key member [ member ... ]
  /// https://valkey.io/commands/sadd/
  @since(version = 0.3.0-dev)
  sadd: async func(connection: borrow<connection>, key: string, members: list<string-or-bytes>) -> result<integer, error-code>;

  /// Returns the number of members in a set.
  ///
  /// SCARD key
  /// https://valkey.io/commands/scard/
  @since(version = 0.3.0-dev)
  scard: async func(connection: borrow<connection>, key: string) -> result<integer, error-code>;

  /// Returns the difference of multiple sets.
  ///
  /// SDIFF key [ key ... ]
  /// https://valkey.io/commands/sdiff/
  @since(version = 0.3.0-dev)
  sdiff: async func(connection: borrow<connection>, keys: list<string>) -> result<list<string-or-bytes>, error-code>;

  /// Stores the difference of multiple sets in a key.
  ///
  /// SDIFFSTORE destination key [ key ... ]
  /// https://valkey.io/commands/sdiffstore/
  @since(version = 0.3.0-dev)
  sdiffstore: async func(connection: borrow<connection>, destination: string, keys: list<string>) -> result<integer, error-code>;

  /// Returns the intersect of multiple sets.
  ///
  /// SINTER key [ key ... ]
  /// https://valkey.io/commands/sinter/
  @since(version = 0.3.0-dev)
  sinter: async func(connection: borrow<connection>, keys: list<string>) -> result<list<string-or-bytes>, error-code>;

  /// Returns the number of members of the intersect of multiple sets.
  ///
  /// SINTERCARD numkeys key [ key ... ] [ LIMIT limit ]
  /// https://valkey.io/commands/sintercard/
  @since(version = 0.3.0-dev)
  sintercard: async func(connection: borrow<connection>, keys: list<string>, limit: option<integer>) -> result<integer, error-code>;

  /// Stores the intersect of multiple sets in a key.
  ///
  /// SINTERSTORE destination key [ key ... ]
  /// https://valkey.io/commands/sinterstore/
  @since(version = 0.3.0-dev)
  sinterstore: async func(connection: borrow<connection>, destination: string, keys: list<string>) -> result<integer, error-code>;

  /// Determines whether a member belongs to a set.
  ///
  /// False when the key does not exist.
  ///
  /// See also `sismember-xx`.
  ///
  /// SISMEMBER key member
  /// https://valkey.io/commands/sismember/
  @since(version = 0.3.0-dev)
  sismember: async func(connection: borrow<connection>, key: string, member: string-or-bytes) -> result<bool, error-code>;

  /// Determines whether a member belongs to a set.
  ///
  /// The `XX` form, none when the key does not exist, rather than false.
  ///
  /// See also `sismember`.
  ///
  /// SISMEMBER key member XX
  /// https://valkey.io/commands/sismember/
  @since(version = 0.3.0-dev)
  sismember-xx: async func(connection: borrow<connection>, key: string, member: string-or-bytes) -> result<option<bool>, error-code>;

  /// Returns all members of a set.
  ///
  /// SMEMBERS key
  /// https://valkey.io/commands/smembers/
  @since(version = 0.3.0-dev)
  smembers: async func(connection: borrow<connection>, key: string) -> result<list<string-or-bytes>, error-code>;

  /// Determines whether multiple members belong to a set.
  ///
  /// SMISMEMBER key member [ member ... ]
  /// https://valkey.io/commands/smismember/
  @since(version = 0.3.0-dev)
  smismember: async func(connection: borrow<connection>, key: string, members: list<string-or-bytes>) -> result<list<bool>, error-code>;

  /// Moves a member from one set to another.
  ///
  /// SMOVE source destination member
  /// https://valkey.io/commands/smove/
  @since(version = 0.3.0-dev)
  smove: async func(connection: borrow<connection>, source: string, destination: string, member: string-or-bytes) -> result<bool, error-code>;

  /// Returns one or more random members from a set after removing them.
  ///
  /// Without a count, at most one member.
  ///
  /// SPOP key [ count ]
  /// https://valkey.io/commands/spop/
  @since(version = 0.3.0-dev)
  spop: async func(connection: borrow<connection>, key: string, count: option<integer>) -> result<list<string-or-bytes>, error-code>;

  /// Gets one or multiple random members from a set.
  ///
  /// Without a count, at most one member.
  ///
  /// SRANDMEMBER key [ count ]
  /// https://valkey.io/commands/srandmember/
  @since(version = 0.3.0-dev)
  srandmember: async func(connection: borrow<connection>, key: string, count: option<integer>) -> result<list<string-or-bytes>, error-code>;

  /// Removes one or more members from a set.
  ///
  /// SREM key member [ member ... ]
  /// https://valkey.io/commands/srem/
  @since(version = 0.3.0-dev)
  srem: async func(connection: borrow<connection>, key: string, members: list<string-or-bytes>) -> result<integer, error-code>;

  /// Iterates over members of a set.
  ///
  /// SSCAN key cursor [ MATCH pattern ] [ COUNT count ]
  /// https://valkey.io/commands/sscan/
  @since(version = 0.3.0-dev)
  sscan: async func(connection: borrow<connection>, key: string, cursor: cursor, match: option<string>, count: option<integer>) -> result<tuple<option<cursor>, list<string-or-bytes>>, error-code>;

  /// Returns the union of multiple sets.
  ///
  /// SUNION key [ key ... ]
  /// https://valkey.io/commands/sunion/
  @since(version = 0.3.0-dev)
  sunion: async func(connection: borrow<connection>, keys: list<string>) -> result<list<string-or-bytes>, error-code>;

  /// Stores the union of multiple sets in a key.
  ///
  /// SUNIONSTORE destination key [ key ... ]
  /// https://valkey.io/commands/sunionstore/
  @since(version = 0.3.0-dev)
  sunionstore: async func(connection: borrow<connection>, destination: string, keys: list<string>) -> result<integer, error-code>;

  /// Sorts the elements in a list, a set, or a sorted set, optionally storing the result.
  ///
  /// Each row is the element, or with `get`, the value of each pattern, none when its key does
  /// not exist.
  ///
  /// See also `sort-store`.
  ///
  /// SORT key [ BY pattern ] [ LIMIT offset count ] [ GET pattern ... ] [ ASC | DESC ] [ ALPHA ]
  /// https://valkey.io/commands/sort/
  @since(version = 0.3.0-dev)
  sort: async func(connection: borrow<connection>, key: string, opts: option<sort-opts>) -> result<list<list<option<string-or-bytes>>>, error-code>;

  /// Sorts the elements in a list, a set, or a sorted set, optionally storing the result.
  ///
  /// The `STORE` form, storing the elements as a list, returning how many.
  ///
  /// See also `sort`.
  ///
  /// SORT key [ BY pattern ] [ LIMIT offset count ] [ GET pattern ... ] [ ASC | DESC ] [ ALPHA ] STORE destination
  /// https://valkey.io/commands/sort/
  @since(version = 0.3.0-dev)
  sort-store: async func(connection: borrow<connection>, key: string, opts: option<sort-opts>, destination: string) -> result<integer, error-code>;

  /// Returns the sorted elements of a list, a set, or a sorted set.
  ///
  /// Each row is the element, or with `get`, the value of each pattern, none when its key does
  /// not exist.
  ///
  /// SORT_RO key [ BY pattern ] [ LIMIT offset count ] [ GET pattern ... ] [ ASC | DESC ] [ ALPHA ]
  /// https://valkey.io/commands/sort_ro/
  @since(version = 0.3.0-dev)
  sort-ro: async func(connection: borrow<connection>, key: string, opts: option<sort-ro-opts>) -> result<list<list<option<string-or-bytes>>>, error-code>;

  /// Removes and returns a member by score from one or more sorted sets.
  ///
  /// Returns none when the timeout passed. The connection waits too, replies to commands sent
  /// after it on the connection wait behind it. Use a connection of your own.
  ///
  /// BZMPOP timeout numkeys key [ key ... ] 〈 MIN | MAX 〉 [ COUNT count ]
  /// https://valkey.io/commands/bzmpop/
  @since(version = 0.3.0-dev)
  bzmpop: async func(connection: borrow<connection>, timeout: duration-milliseconds, keys: list<string>, end: bzmpop-end, count: option<integer>) -> result<option<tuple<string, list<tuple<string-or-bytes, double>>>>, error-code>;

  /// Removes and returns the member with the highest score from one or more sorted sets.
  ///
  /// Returns none when the timeout passed. The connection waits too, replies to commands sent
  /// after it on the connection wait behind it. Use a connection of your own.
  ///
  /// BZPOPMAX key [ key ... ] timeout
  /// https://valkey.io/commands/bzpopmax/
  @since(version = 0.3.0-dev)
  bzpopmax: async func(connection: borrow<connection>, keys: list<string>, timeout: duration-milliseconds) -> result<option<tuple<string, string-or-bytes, double>>, error-code>;

  /// Removes and returns the member with the lowest score from one or more sorted sets.
  ///
  /// Returns none when the timeout passed. The connection waits too, replies to commands sent
  /// after it on the connection wait behind it. Use a connection of your own.
  ///
  /// BZPOPMIN key [ key ... ] timeout
  /// https://valkey.io/commands/bzpopmin/
  @since(version = 0.3.0-dev)
  bzpopmin: async func(connection: borrow<connection>, keys: list<string>, timeout: duration-milliseconds) -> result<option<tuple<string, string-or-bytes, double>>, error-code>;

  /// Adds one or more members to a sorted set, or updates their scores.
  ///
  /// See also `zadd-incr`.
  ///
  /// ZADD key [ NX | XX ] [ GT | LT ] [ CH ] score member [ score member ... ]
  /// https://valkey.io/commands/zadd/
  @since(version = 0.3.0-dev)
  zadd: async func(connection: borrow<connection>, key: string, condition: option<zadd-condition>, comparison: option<zadd-comparison>, changed: bool, score-and-members: list<tuple<double, string-or-bytes>>) -> result<option<integer>, error-code>;

  /// Adds one or more members to a sorted set, or updates their scores.
  ///
  /// The `INCR` form, returning the new score, none when the condition or comparison prevented
  /// it.
  ///
  /// See also `zadd`.
  ///
  /// ZADD key [ NX | XX ] [ GT | LT ] INCR score member
  /// https://valkey.io/commands/zadd/
  @since(version = 0.3.0-dev)
  zadd-incr: async func(connection: borrow<connection>, key: string, condition: option<zadd-condition>, comparison: option<zadd-comparison>, increment: double, member: string-or-bytes) -> result<option<double>, error-code>;

  /// Returns the number of members in a sorted set.
  ///
  /// ZCARD key
  /// https://valkey.io/commands/zcard/
  @since(version = 0.3.0-dev)
  zcard: async func(connection: borrow<connection>, key: string) -> result<integer, error-code>;

  /// Returns the count of members in a sorted set that have scores within a range.
  ///
  /// ZCOUNT key min max
  /// https://valkey.io/commands/zcount/
  @since(version = 0.3.0-dev)
  zcount: async func(connection: borrow<connection>, key: string, min: score-bound, max: score-bound) -> result<integer, error-code>;

  /// Returns the difference between multiple sorted sets.
  ///
  /// See also `zdiff-withscores`.
  ///
  /// ZDIFF numkeys key [ key ... ]
  /// https://valkey.io/commands/zdiff/
  @since(version = 0.3.0-dev)
  zdiff: async func(connection: borrow<connection>, keys: list<string>) -> result<list<string-or-bytes>, error-code>;

  /// Returns the difference between multiple sorted sets.
  ///
  /// The `WITHSCORES` form, the members and their scores.
  ///
  /// See also `zdiff`.
  ///
  /// ZDIFF numkeys key [ key ... ] WITHSCORES
  /// https://valkey.io/commands/zdiff/
  @since(version = 0.3.0-dev)
  zdiff-withscores: async func(connection: borrow<connection>, keys: list<string>) -> result<list<tuple<string-or-bytes, double>>, error-code>;

  /// Stores the difference of multiple sorted sets in a key.
  ///
  /// ZDIFFSTORE destination numkeys key [ key ... ]
  /// https://valkey.io/commands/zdiffstore/
  @since(version = 0.3.0-dev)
  zdiffstore: async func(connection: borrow<connection>, destination: string, keys: list<string>) -> result<integer, error-code>;

  /// Increments the score of a member in a sorted set.
  ///
  /// ZINCRBY key increment member
  /// https://valkey.io/commands/zincrby/
  @since(version = 0.3.0-dev)
  zincrby: async func(connection: borrow<connection>, key: string, increment: double, member: string-or-bytes) -> result<double, error-code>;

  /// Returns the intersect of multiple sorted sets.
  ///
  /// See also `zinter-withscores`.
  ///
  /// ZINTER numkeys key [ key ... ] [ WEIGHTS weight [ weight ... ] ] [ AGGREGATE SUM | MIN | MAX ]
  /// https://valkey.io/commands/zinter/
  @since(version = 0.3.0-dev)
  zinter: async func(connection: borrow<connection>, keys: list<string>, weights: option<list<double>>, aggregate: option<zset-aggregate>) -> result<list<string-or-bytes>, error-code>;

  /// Returns the intersect of multiple sorted sets.
  ///
  /// The `WITHSCORES` form, the members and their combined scores.
  ///
  /// See also `zinter`.
  ///
  /// ZINTER numkeys key [ key ... ] [ WEIGHTS weight [ weight ... ] ] [ AGGREGATE SUM | MIN | MAX ] WITHSCORES
  /// https://valkey.io/commands/zinter/
  @since(version = 0.3.0-dev)
  zinter-withscores: async func(connection: borrow<connection>, keys: list<string>, weights: option<list<double>>, aggregate: option<zset-aggregate>) -> result<list<tuple<string-or-bytes, double>>, error-code>;

  /// Returns the number of members of the intersect of multiple sorted sets.
  ///
  /// ZINTERCARD numkeys key [ key ... ] [ LIMIT limit ]
  /// https://valkey.io/commands/zintercard/
  @since(version = 0.3.0-dev)
  zintercard: async func(connection: borrow<connection>, keys: list<string>, limit: option<integer>) -> result<integer, error-code>;

  /// Stores the intersect of multiple sorted sets in a key.
  ///
  /// ZINTERSTORE destination numkeys key [ key ... ] [ WEIGHTS weight [ weight ... ] ] [ AGGREGATE SUM | MIN | MAX ]
  /// https://valkey.io/commands/zinterstore/
  @since(version = 0.3.0-dev)
  zinterstore: async func(connection: borrow<connection>, destination: string, keys: list<string>, weights: option<list<double>>, aggregate: option<zset-aggregate>) -> result<integer, error-code>;

  /// Returns the number of members in a sorted set within a lexicographical range.
  ///
  /// ZLEXCOUNT key min max
  /// https://valkey.io/commands/zlexcount/
  @since(version = 0.3.0-dev)
  zlexcount: async func(connection: borrow<connection>, key: string, min: lex-bound, max: lex-bound) -> result<integer, error-code>;

  /// Returns the highest- or lowest-scoring members from one or more sorted sets after removing them.
  ///
  /// ZMPOP numkeys key [ key ... ] 〈 MIN | MAX 〉 [ COUNT count ]
  /// https://valkey.io/commands/zmpop/
  @since(version = 0.3.0-dev)
  zmpop: async func(connection: borrow<connection>, keys: list<string>, end: zmpop-end, count: option<integer>) -> result<option<tuple<string, list<tuple<string-or-bytes, double>>>>, error-code>;

  /// Returns the score of one or more members in a sorted set.
  ///
  /// ZMSCORE key member [ member ... ]
  /// https://valkey.io/commands/zmscore/
  @since(version = 0.3.0-dev)
  zmscore: async func(connection: borrow<connection>, key: string, members: list<string-or-bytes>) -> result<list<option<double>>, error-code>;

  /// Returns the highest-scoring members from a sorted set after removing them.
  ///
  /// Without a count, at most one member.
  ///
  /// ZPOPMAX key [ count ]
  /// https://valkey.io/commands/zpopmax/
  @since(version = 0.3.0-dev)
  zpopmax: async func(connection: borrow<connection>, key: string, count: option<integer>) -> result<list<tuple<string-or-bytes, double>>, error-code>;

  /// Returns the lowest-scoring members from a sorted set after removing them.
  ///
  /// Without a count, at most one member.
  ///
  /// ZPOPMIN key [ count ]
  /// https://valkey.io/commands/zpopmin/
  @since(version = 0.3.0-dev)
  zpopmin: async func(connection: borrow<connection>, key: string, count: option<integer>) -> result<list<tuple<string-or-bytes, double>>, error-code>;

  /// Returns one or more random members from a sorted set.
  ///
  /// Without a count, at most one member.
  ///
  /// See also `zrandmember-withscores`.
  ///
  /// ZRANDMEMBER key [ count ]
  /// https://valkey.io/commands/zrandmember/
  @since(version = 0.3.0-dev)
  zrandmember: async func(connection: borrow<connection>, key: string, count: option<integer>) -> result<list<string-or-bytes>, error-code>;

  /// Returns one or more random members from a sorted set.
  ///
  /// The `WITHSCORES` form, the members and their scores.
  ///
  /// See also `zrandmember`.
  ///
  /// ZRANDMEMBER key count WITHSCORES
  /// https://valkey.io/commands/zrandmember/
  @since(version = 0.3.0-dev)
  zrandmember-withscores: async func(connection: borrow<connection>, key: string, count: integer) -> result<list<tuple<string-or-bytes, double>>, error-code>;

  /// Returns members in a sorted set within a range of indexes.
  ///
  /// Also covers ZRANGEBYLEX, ZRANGEBYSCORE, ZREVRANGE, ZREVRANGEBYLEX and ZREVRANGEBYSCORE. A
  /// limit fails the command unless the range is by score or by lex. With `xx`, returns none when
  /// the key does not exist.
  ///
  /// See also `zrange-withscores`.
  ///
  /// ZRANGE key start stop [ BYSCORE | BYLEX ] [ REV ] [ LIMIT offset count ] [ XX ]
  /// https://valkey.io/commands/zrange/
  @since(version = 0.3.0-dev)
  zrange: async func(connection: borrow<connection>, key: string, range: zrange-by, rev: bool, limit: option<limit>, xx: bool) -> result<option<list<string-or-bytes>>, error-code>;

  /// Returns members in a sorted set within a range of indexes.
  ///
  /// The `WITHSCORES` form, the members and their scores. A limit fails the command unless the
  /// range is by score. With `xx`, returns none when the key does not exist.
  ///
  /// See also `zrange`.
  ///
  /// ZRANGE key start stop [ BYSCORE ] [ REV ] [ LIMIT offset count ] WITHSCORES [ XX ]
  /// https://valkey.io/commands/zrange/
  @since(version = 0.3.0-dev)
  zrange-withscores: async func(connection: borrow<connection>, key: string, range: zrange-withscores-by, rev: bool, limit: option<limit>, xx: bool) -> result<option<list<tuple<string-or-bytes, double>>>, error-code>;

  /// Stores a range of members from sorted set in a key.
  ///
  /// A limit fails the command unless the range is by score or by lex.
  ///
  /// ZRANGESTORE dst src min max [ BYSCORE | BYLEX ] [ REV ] [ LIMIT offset count ]
  /// https://valkey.io/commands/zrangestore/
  @since(version = 0.3.0-dev)
  zrangestore: async func(connection: borrow<connection>, destination: string, source: string, range: zrangestore-by, rev: bool, limit: option<limit>) -> result<integer, error-code>;

  /// Returns the index of a member in a sorted set ordered by ascending scores.
  ///
  /// See also `zrank-withscore`.
  ///
  /// ZRANK key member
  /// https://valkey.io/commands/zrank/
  @since(version = 0.3.0-dev)
  zrank: async func(connection: borrow<connection>, key: string, member: string-or-bytes) -> result<option<integer>, error-code>;

  /// Returns the index of a member in a sorted set ordered by ascending scores.
  ///
  /// The `WITHSCORE` form, the position and the score.
  ///
  /// See also `zrank`.
  ///
  /// ZRANK key member WITHSCORE
  /// https://valkey.io/commands/zrank/
  @since(version = 0.3.0-dev)
  zrank-withscore: async func(connection: borrow<connection>, key: string, member: string-or-bytes) -> result<option<tuple<integer, double>>, error-code>;

  /// Removes one or more members from a sorted set.
  ///
  /// ZREM key member [ member ... ]
  /// https://valkey.io/commands/zrem/
  @since(version = 0.3.0-dev)
  zrem: async func(connection: borrow<connection>, key: string, members: list<string-or-bytes>) -> result<integer, error-code>;

  /// Removes members in a sorted set within a lexicographical range.
  ///
  /// ZREMRANGEBYLEX key min max
  /// https://valkey.io/commands/zremrangebylex/
  @since(version = 0.3.0-dev)
  zremrangebylex: async func(connection: borrow<connection>, key: string, min: lex-bound, max: lex-bound) -> result<integer, error-code>;

  /// Removes members in a sorted set within a range of indexes.
  ///
  /// ZREMRANGEBYRANK key start stop
  /// https://valkey.io/commands/zremrangebyrank/
  @since(version = 0.3.0-dev)
  zremrangebyrank: async func(connection: borrow<connection>, key: string, start: integer, stop: integer) -> result<integer, error-code>;

  /// Removes members in a sorted set within a range of scores.
  ///
  /// ZREMRANGEBYSCORE key min max
  /// https://valkey.io/commands/zremrangebyscore/
  @since(version = 0.3.0-dev)
  zremrangebyscore: async func(connection: borrow<connection>, key: string, min: score-bound, max: score-bound) -> result<integer, error-code>;

  /// Returns the index of a member in a sorted set ordered by descending scores.
  ///
  /// See also `zrevrank-withscore`.
  ///
  /// ZREVRANK key member
  /// https://valkey.io/commands/zrevrank/
  @since(version = 0.3.0-dev)
  zrevrank: async func(connection: borrow<connection>, key: string, member: string-or-bytes) -> result<option<integer>, error-code>;

  /// Returns the index of a member in a sorted set ordered by descending scores.
  ///
  /// The `WITHSCORE` form, the position and the score.
  ///
  /// See also `zrevrank`.
  ///
  /// ZREVRANK key member WITHSCORE
  /// https://valkey.io/commands/zrevrank/
  @since(version = 0.3.0-dev)
  zrevrank-withscore: async func(connection: borrow<connection>, key: string, member: string-or-bytes) -> result<option<tuple<integer, double>>, error-code>;

  /// Iterates over members and scores of a sorted set.
  ///
  /// See also `zscan-noscores`.
  ///
  /// ZSCAN key cursor [ MATCH pattern ] [ COUNT count ]
  /// https://valkey.io/commands/zscan/
  @since(version = 0.3.0-dev)
  zscan: async func(connection: borrow<connection>, key: string, cursor: cursor, match: option<string>, count: option<integer>) -> result<tuple<option<cursor>, list<tuple<string-or-bytes, double>>>, error-code>;

  /// Iterates over members and scores of a sorted set.
  ///
  /// The `NOSCORES` form, the members only.
  ///
  /// See also `zscan`.
  ///
  /// ZSCAN key cursor [ MATCH pattern ] [ COUNT count ] NOSCORES
  /// https://valkey.io/commands/zscan/
  @since(version = 0.3.0-dev)
  zscan-noscores: async func(connection: borrow<connection>, key: string, cursor: cursor, match: option<string>, count: option<integer>) -> result<tuple<option<cursor>, list<string-or-bytes>>, error-code>;

  /// Returns the score of a member in a sorted set.
  ///
  /// ZSCORE key member
  /// https://valkey.io/commands/zscore/
  @since(version = 0.3.0-dev)
  zscore: async func(connection: borrow<connection>, key: string, member: string-or-bytes) -> result<option<double>, error-code>;

  /// Returns the union of multiple sorted sets.
  ///
  /// See also `zunion-withscores`.
  ///
  /// ZUNION numkeys key [ key ... ] [ WEIGHTS weight [ weight ... ] ] [ AGGREGATE SUM | MIN | MAX ]
  /// https://valkey.io/commands/zunion/
  @since(version = 0.3.0-dev)
  zunion: async func(connection: borrow<connection>, keys: list<string>, weights: option<list<double>>, aggregate: option<zset-aggregate>) -> result<list<string-or-bytes>, error-code>;

  /// Returns the union of multiple sorted sets.
  ///
  /// The `WITHSCORES` form, the members and their combined scores.
  ///
  /// See also `zunion`.
  ///
  /// ZUNION numkeys key [ key ... ] [ WEIGHTS weight [ weight ... ] ] [ AGGREGATE SUM | MIN | MAX ] WITHSCORES
  /// https://valkey.io/commands/zunion/
  @since(version = 0.3.0-dev)
  zunion-withscores: async func(connection: borrow<connection>, keys: list<string>, weights: option<list<double>>, aggregate: option<zset-aggregate>) -> result<list<tuple<string-or-bytes, double>>, error-code>;

  /// Stores the union of multiple sorted sets in a key.
  ///
  /// ZUNIONSTORE destination numkeys key [ key ... ] [ WEIGHTS weight [ weight ... ] ] [ AGGREGATE SUM | MIN | MAX ]
  /// https://valkey.io/commands/zunionstore/
  @since(version = 0.3.0-dev)
  zunionstore: async func(connection: borrow<connection>, destination: string, keys: list<string>, weights: option<list<double>>, aggregate: option<zset-aggregate>) -> result<integer, error-code>;

  /// Returns the number of messages that were successfully acknowledged by the consumer group member of a stream.
  ///
  /// XACK key group ID [ ID ... ]
  /// https://valkey.io/commands/xack/
  @since(version = 0.3.0-dev)
  xack: async func(connection: borrow<connection>, key: string, group: string, ids: list<stream-id>) -> result<integer, error-code>;

  /// Appends a new message to a stream.
  ///
  /// XADD key [ NOMKSTREAM ] [ 〈 MAXLEN | MINID 〉 [ = | ~ ] threshold [ LIMIT count ] ] 〈 * | id 〉 field value [ field value ... ]
  /// https://valkey.io/commands/xadd/
  @since(version = 0.3.0-dev)
  xadd: async func(connection: borrow<connection>, key: string, nomkstream: bool, trim: option<stream-trim>, id: stream-id, field-and-values: list<tuple<string, string-or-bytes>>) -> result<option<stream-id>, error-code>;

  /// Changes, or acquires, ownership of messages in a consumer group, as if the messages were delivered to a consumer group member.
  ///
  /// A start of none scans from the beginning, `0-0`. The next start is returned, none once the
  /// scan is complete.
  ///
  /// See also `xautoclaim-justid`.
  ///
  /// XAUTOCLAIM key group consumer min-idle-time start [ COUNT count ]
  /// https://valkey.io/commands/xautoclaim/
  @since(version = 0.3.0-dev)
  xautoclaim: async func(connection: borrow<connection>, key: string, group: string, consumer: string, min-idle-time: duration-milliseconds, start: option<stream-id>, count: option<integer>) -> result<tuple<option<stream-id>, list<tuple<stream-id, map<string, string-or-bytes>>>, list<stream-id>>, error-code>;

  /// Changes, or acquires, ownership of messages in a consumer group, as if the messages were delivered to a consumer group member.
  ///
  /// The `JUSTID` form, the IDs only. A start of none scans from the beginning, `0-0`. The next
  /// start is returned, none once the scan is complete.
  ///
  /// See also `xautoclaim`.
  ///
  /// XAUTOCLAIM key group consumer min-idle-time start [ COUNT count ] JUSTID
  /// https://valkey.io/commands/xautoclaim/
  @since(version = 0.3.0-dev)
  xautoclaim-justid: async func(connection: borrow<connection>, key: string, group: string, consumer: string, min-idle-time: duration-milliseconds, start: option<stream-id>, count: option<integer>) -> result<tuple<option<stream-id>, list<stream-id>, list<stream-id>>, error-code>;

  /// Changes, or acquires, ownership of a message in a consumer group, as if the message was delivered to a consumer group member.
  ///
  /// See also `xclaim-justid`.
  ///
  /// XCLAIM key group consumer min-idle-time ID [ ID ... ] [ IDLE ms ] [ TIME unix-time-milliseconds ] [ RETRYCOUNT count ] [ FORCE ] [ LASTID lastid ]
  /// https://valkey.io/commands/xclaim/
  @since(version = 0.3.0-dev)
  xclaim: async func(connection: borrow<connection>, key: string, group: string, consumer: string, min-idle-time: duration-milliseconds, ids: list<stream-id>, opts: option<xclaim-opts>) -> result<list<tuple<stream-id, map<string, string-or-bytes>>>, error-code>;

  /// Changes, or acquires, ownership of a message in a consumer group, as if the message was delivered to a consumer group member.
  ///
  /// The `JUSTID` form, the IDs only.
  ///
  /// See also `xclaim`.
  ///
  /// XCLAIM key group consumer min-idle-time ID [ ID ... ] [ IDLE ms ] [ TIME unix-time-milliseconds ] [ RETRYCOUNT count ] [ FORCE ] JUSTID [ LASTID lastid ]
  /// https://valkey.io/commands/xclaim/
  @since(version = 0.3.0-dev)
  xclaim-justid: async func(connection: borrow<connection>, key: string, group: string, consumer: string, min-idle-time: duration-milliseconds, ids: list<stream-id>, opts: option<xclaim-opts>) -> result<list<stream-id>, error-code>;

  /// Returns the number of messages after removing them from a stream.
  ///
  /// XDEL key ID [ ID ... ]
  /// https://valkey.io/commands/xdel/
  @since(version = 0.3.0-dev)
  xdel: async func(connection: borrow<connection>, key: string, ids: list<stream-id>) -> result<integer, error-code>;

  /// Creates a consumer group.
  ///
  /// XGROUP CREATE key group 〈 id | $ 〉 [ MKSTREAM ] [ ENTRIESREAD entriesread ]
  /// https://valkey.io/commands/xgroup-create/
  @since(version = 0.3.0-dev)
  xgroup-create: async func(connection: borrow<connection>, key: string, group: string, id: stream-id, mkstream: bool, entriesread: option<integer>) -> result<_, error-code>;

  /// Creates a consumer in a consumer group.
  ///
  /// XGROUP CREATECONSUMER key group consumer
  /// https://valkey.io/commands/xgroup-createconsumer/
  @since(version = 0.3.0-dev)
  xgroup-createconsumer: async func(connection: borrow<connection>, key: string, group: string, consumer: string) -> result<bool, error-code>;

  /// Deletes a consumer from a consumer group.
  ///
  /// XGROUP DELCONSUMER key group consumer
  /// https://valkey.io/commands/xgroup-delconsumer/
  @since(version = 0.3.0-dev)
  xgroup-delconsumer: async func(connection: borrow<connection>, key: string, group: string, consumer: string) -> result<integer, error-code>;

  /// Destroys a consumer group.
  ///
  /// XGROUP DESTROY key group
  /// https://valkey.io/commands/xgroup-destroy/
  @since(version = 0.3.0-dev)
  xgroup-destroy: async func(connection: borrow<connection>, key: string, group: string) -> result<bool, error-code>;

  /// Sets the last-delivered ID of a consumer group.
  ///
  /// XGROUP SETID key group 〈 id | $ 〉 [ ENTRIESREAD entriesread ]
  /// https://valkey.io/commands/xgroup-setid/
  @since(version = 0.3.0-dev)
  xgroup-setid: async func(connection: borrow<connection>, key: string, group: string, id: stream-id, entriesread: option<integer>) -> result<_, error-code>;

  /// Returns a list of the consumers in a consumer group.
  ///
  /// XINFO CONSUMERS key group
  /// https://valkey.io/commands/xinfo-consumers/
  @since(version = 0.3.0-dev)
  xinfo-consumers: async func(connection: borrow<connection>, key: string, group: string) -> result<list<xinfo-consumers-entry>, error-code>;

  /// Returns a list of the consumer groups of a stream.
  ///
  /// XINFO GROUPS key
  /// https://valkey.io/commands/xinfo-groups/
  @since(version = 0.3.0-dev)
  xinfo-groups: async func(connection: borrow<connection>, key: string) -> result<list<xinfo-groups-entry>, error-code>;

  /// Returns information about a stream.
  ///
  /// See also `xinfo-stream-full`.
  ///
  /// XINFO STREAM key
  /// https://valkey.io/commands/xinfo-stream/
  @since(version = 0.3.0-dev)
  xinfo-stream: async func(connection: borrow<connection>, key: string) -> result<xinfo-stream-reply, error-code>;

  /// Returns information about a stream.
  ///
  /// The `FULL` form, with the entries, groups and consumers.
  ///
  /// See also `xinfo-stream`.
  ///
  /// XINFO STREAM key FULL [ COUNT count ]
  /// https://valkey.io/commands/xinfo-stream/
  @since(version = 0.3.0-dev)
  xinfo-stream-full: async func(connection: borrow<connection>, key: string, count: option<integer>) -> result<xinfo-stream-reply-full, error-code>;

  /// Returns the number of messages in a stream.
  ///
  /// XLEN key
  /// https://valkey.io/commands/xlen/
  @since(version = 0.3.0-dev)
  xlen: async func(connection: borrow<connection>, key: string) -> result<integer, error-code>;

  /// Returns the information and entries from a stream consumer group's pending entries list.
  ///
  /// The summary form.
  ///
  /// See also `xpending-extended`.
  ///
  /// XPENDING key group
  /// https://valkey.io/commands/xpending/
  @since(version = 0.3.0-dev)
  xpending: async func(connection: borrow<connection>, key: string, group: string) -> result<xpending-summary, error-code>;

  /// Returns the information and entries from a stream consumer group's pending entries list.
  ///
  /// The extended form, the pending entries in the range.
  ///
  /// See also `xpending`.
  ///
  /// XPENDING key group [ IDLE min-idle-time ] start end count [ consumer ]
  /// https://valkey.io/commands/xpending/
  @since(version = 0.3.0-dev)
  xpending-extended: async func(connection: borrow<connection>, key: string, group: string, min-idle-time: option<duration-milliseconds>, start: stream-id, end: stream-id, count: integer, consumer: option<string>) -> result<list<xpending-extended-entry>, error-code>;

  /// Returns the messages from a stream within a range of IDs.
  ///
  /// XRANGE key start end [ COUNT count ]
  /// https://valkey.io/commands/xrange/
  @since(version = 0.3.0-dev)
  xrange: async func(connection: borrow<connection>, key: string, start: stream-id, end: stream-id, count: option<integer>) -> result<list<tuple<stream-id, map<string, string-or-bytes>>>, error-code>;

  /// Returns messages from multiple streams with IDs greater than the ones requested.
  ///
  /// With `block`, returns none when the timeout passed. The connection waits too, replies to
  /// commands sent after it on the connection wait behind it. Use a connection of your own.
  ///
  /// XREAD [ COUNT count ] [ BLOCK milliseconds ] STREAMS key [ key ... ] ID [ ID ... ]
  /// https://valkey.io/commands/xread/
  @since(version = 0.3.0-dev)
  xread: async func(connection: borrow<connection>, count: option<integer>, block: option<duration-milliseconds>, keys: list<string>, ids: list<stream-id>) -> result<option<map<string, list<tuple<stream-id, map<string, string-or-bytes>>>>>, error-code>;

  /// Returns new or historical messages from a stream for a consumer in a group.
  ///
  /// The fields of an entry are none when it was deleted after it was delivered, e.g. when
  /// reading the pending entries with the ID `0`.
  ///
  /// With `block`, returns none when the timeout passed. The connection waits too, replies to
  /// commands sent after it on the connection wait behind it. Use a connection of your own.
  ///
  /// XREADGROUP GROUP group consumer [ COUNT count ] [ BLOCK milliseconds ] [ NOACK ] STREAMS key [ key ... ] ID [ ID ... ]
  /// https://valkey.io/commands/xreadgroup/
  @since(version = 0.3.0-dev)
  xreadgroup: async func(connection: borrow<connection>, group: string, consumer: string, count: option<integer>, block: option<duration-milliseconds>, noack: bool, keys: list<string>, ids: list<stream-id>) -> result<option<map<string, list<tuple<stream-id, option<map<string, string-or-bytes>>>>>>, error-code>;

  /// Returns the messages from a stream within a range of IDs in reverse order.
  ///
  /// XREVRANGE key end start [ COUNT count ]
  /// https://valkey.io/commands/xrevrange/
  @since(version = 0.3.0-dev)
  xrevrange: async func(connection: borrow<connection>, key: string, end: stream-id, start: stream-id, count: option<integer>) -> result<list<tuple<stream-id, map<string, string-or-bytes>>>, error-code>;

  /// An internal command for replicating stream values.
  ///
  /// XSETID key last-id [ ENTRIESADDED entries-added ] [ MAXDELETEDID max-deleted-id ]
  /// https://valkey.io/commands/xsetid/
  @since(version = 0.3.0-dev)
  xsetid: async func(connection: borrow<connection>, key: string, last-id: stream-id, entries-added: option<integer>, max-deleted-id: option<stream-id>) -> result<_, error-code>;

  /// Deletes messages from the beginning of a stream.
  ///
  /// XTRIM key 〈 MAXLEN | MINID 〉 [ = | ~ ] threshold [ LIMIT count ]
  /// https://valkey.io/commands/xtrim/
  @since(version = 0.3.0-dev)
  xtrim: async func(connection: borrow<connection>, key: string, trim: stream-trim) -> result<integer, error-code>;

  /// Appends a string to the value of a key.
  ///
  /// APPEND key value
  /// https://valkey.io/commands/append/
  @since(version = 0.3.0-dev)
  append: async func(connection: borrow<connection>, key: string, value: string-or-bytes) -> result<integer, error-code>;

  /// Decrements the integer value of a key by one.
  ///
  /// DECR key
  /// https://valkey.io/commands/decr/
  @since(version = 0.3.0-dev)
  decr: async func(connection: borrow<connection>, key: string) -> result<integer, error-code>;

  /// Decrements the integer value of a key by a number.
  ///
  /// DECRBY key decrement
  /// https://valkey.io/commands/decrby/
  @since(version = 0.3.0-dev)
  decrby: async func(connection: borrow<connection>, key: string, decrement: integer) -> result<integer, error-code>;

  /// Delete key if value matches string.
  ///
  /// DELIFEQ key value
  /// https://valkey.io/commands/delifeq/
  @since(version = 0.3.0-dev)
  delifeq: async func(connection: borrow<connection>, key: string, value: string-or-bytes) -> result<bool, error-code>;

  /// Returns the string value of a key.
  ///
  /// GET key
  /// https://valkey.io/commands/get/
  @since(version = 0.3.0-dev)
  get: async func(connection: borrow<connection>, key: string) -> result<option<string-or-bytes>, error-code>;

  /// Returns the string value of a key after deleting the key.
  ///
  /// GETDEL key
  /// https://valkey.io/commands/getdel/
  @since(version = 0.3.0-dev)
  getdel: async func(connection: borrow<connection>, key: string) -> result<option<string-or-bytes>, error-code>;

  /// Returns the string value of a key after setting its expiration time.
  ///
  /// GETEX key [ EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | PERSIST ]
  /// https://valkey.io/commands/getex/
  @since(version = 0.3.0-dev)
  getex: async func(connection: borrow<connection>, key: string, ttl: option<getex-ttl>) -> result<option<string-or-bytes>, error-code>;

  /// Returns a substring of the string stored at a key.
  ///
  /// GETRANGE key start end
  /// https://valkey.io/commands/getrange/
  @since(version = 0.3.0-dev)
  getrange: async func(connection: borrow<connection>, key: string, start: integer, end: integer) -> result<string-or-bytes, error-code>;

  /// Returns the previous string value of a key after setting it to a new value.
  ///
  /// GETSET key value
  /// https://valkey.io/commands/getset/
  @since(version = 0.3.0-dev)
  getset: async func(connection: borrow<connection>, key: string, value: string-or-bytes) -> result<option<string-or-bytes>, error-code>;

  /// Increments the integer value of a key by one.
  ///
  /// INCR key
  /// https://valkey.io/commands/incr/
  @since(version = 0.3.0-dev)
  incr: async func(connection: borrow<connection>, key: string) -> result<integer, error-code>;

  /// Increments the integer value of a key by a number.
  ///
  /// INCRBY key increment
  /// https://valkey.io/commands/incrby/
  @since(version = 0.3.0-dev)
  incrby: async func(connection: borrow<connection>, key: string, increment: integer) -> result<integer, error-code>;

  /// Increments the floating point value of a key by a number.
  ///
  /// INCRBYFLOAT key increment
  /// https://valkey.io/commands/incrbyfloat/
  @since(version = 0.3.0-dev)
  incrbyfloat: async func(connection: borrow<connection>, key: string, increment: double) -> result<double, error-code>;

  /// Finds the longest common substring.
  ///
  /// See also `lcs-len` and `lcs-idx`.
  ///
  /// LCS key1 key2
  /// https://valkey.io/commands/lcs/
  @since(version = 0.3.0-dev)
  lcs: async func(connection: borrow<connection>, key1: string, key2: string) -> result<string-or-bytes, error-code>;

  /// Finds the longest common substring.
  ///
  /// The `LEN` form, the length only.
  ///
  /// See also `lcs` and `lcs-idx`.
  ///
  /// LCS key1 key2 LEN
  /// https://valkey.io/commands/lcs/
  @since(version = 0.3.0-dev)
  lcs-len: async func(connection: borrow<connection>, key1: string, key2: string) -> result<integer, error-code>;

  /// Finds the longest common substring.
  ///
  /// The `IDX` form, the ranges of the matches.
  ///
  /// See also `lcs` and `lcs-len`.
  ///
  /// LCS key1 key2 IDX [ MINMATCHLEN min-match-len ] [ WITHMATCHLEN ]
  /// https://valkey.io/commands/lcs/
  @since(version = 0.3.0-dev)
  lcs-idx: async func(connection: borrow<connection>, key1: string, key2: string, min-match-len: option<integer>, with-match-len: bool) -> result<lcs-idx-reply, error-code>;

  /// Atomically returns the string values of one or more keys.
  ///
  /// MGET key [ key ... ]
  /// https://valkey.io/commands/mget/
  @since(version = 0.3.0-dev)
  mget: async func(connection: borrow<connection>, keys: list<string>) -> result<list<option<string-or-bytes>>, error-code>;

  /// Atomically creates or modifies the string values of one or more keys.
  ///
  /// MSET key value [ key value ... ]
  /// https://valkey.io/commands/mset/
  @since(version = 0.3.0-dev)
  mset: async func(connection: borrow<connection>, keys-and-values: list<tuple<string, string-or-bytes>>) -> result<_, error-code>;

  /// Atomically creates or modifies the string values of one or more keys, and optionally set their expiration.
  ///
  /// MSETEX numkeys key value [ key value ... ] [ NX | XX ] [ EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL ]
  /// https://valkey.io/commands/msetex/
  @since(version = 0.3.0-dev)
  msetex: async func(connection: borrow<connection>, keys-and-values: list<tuple<string, string-or-bytes>>, precondition: option<msetex-precondition>, ttl: option<msetex-ttl>) -> result<bool, error-code>;

  /// Atomically modifies the string values of one or more keys only when all keys don't exist.
  ///
  /// MSETNX key value [ key value ... ]
  /// https://valkey.io/commands/msetnx/
  @since(version = 0.3.0-dev)
  msetnx: async func(connection: borrow<connection>, keys-and-values: list<tuple<string, string-or-bytes>>) -> result<bool, error-code>;

  /// Sets both string value and expiration time in milliseconds of a key.
  ///
  /// PSETEX key milliseconds value
  /// https://valkey.io/commands/psetex/
  @since(version = 0.3.0-dev)
  psetex: async func(connection: borrow<connection>, key: string, milliseconds: duration-milliseconds, value: string-or-bytes) -> result<_, error-code>;

  /// Sets the string value of a key, ignoring its type.
  ///
  /// Returns false when the precondition is not met, the key is unchanged.
  ///
  /// See also `set-get`.
  ///
  /// SET key value [ NX | XX | IFEQ comparison-value | IFNE comparison-not-equal ] [ EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL ]
  /// https://valkey.io/commands/set/
  @since(version = 0.3.0-dev)
  set: async func(connection: borrow<connection>, key: string, value: string-or-bytes, precondition: option<set-precondition>, ttl: option<set-ttl>) -> result<bool, error-code>;

  /// Sets the string value of a key, ignoring its type.
  ///
  /// The `GET` form, returning the previous value, none when the key did not exist.
  ///
  /// See also `set`.
  ///
  /// SET key value [ NX | XX | IFEQ comparison-value | IFNE comparison-not-equal ] GET [ EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL ]
  /// https://valkey.io/commands/set/
  @since(version = 0.3.0-dev)
  set-get: async func(connection: borrow<connection>, key: string, value: string-or-bytes, precondition: option<set-precondition>, ttl: option<set-ttl>) -> result<option<string-or-bytes>, error-code>;

  /// Sets the string value and expiration time of a key.
  ///
  /// SETEX key seconds value
  /// https://valkey.io/commands/setex/
  @since(version = 0.3.0-dev)
  setex: async func(connection: borrow<connection>, key: string, seconds: duration-seconds, value: string-or-bytes) -> result<_, error-code>;

  /// Sets the string value of a key only when the key doesn't exist.
  ///
  /// SETNX key value
  /// https://valkey.io/commands/setnx/
  @since(version = 0.3.0-dev)
  setnx: async func(connection: borrow<connection>, key: string, value: string-or-bytes) -> result<bool, error-code>;

  /// Overwrites a part of a string value with another by an offset.
  ///
  /// SETRANGE key offset value
  /// https://valkey.io/commands/setrange/
  @since(version = 0.3.0-dev)
  setrange: async func(connection: borrow<connection>, key: string, offset: u32, value: string-or-bytes) -> result<integer, error-code>;

  /// Returns the length of a string value.
  ///
  /// STRLEN key
  /// https://valkey.io/commands/strlen/
  @since(version = 0.3.0-dev)
  strlen: async func(connection: borrow<connection>, key: string) -> result<integer, error-code>;

  /// Returns a substring from a string value.
  ///
  /// SUBSTR key start end
  /// https://valkey.io/commands/substr/
  @since(version = 0.3.0-dev)
  substr: async func(connection: borrow<connection>, key: string, start: integer, end: integer) -> result<string-or-bytes, error-code>;
}

/// Establishes connections, with a transport and settings chosen by whoever provides it, e.g. from
/// configuration.
///
/// A component that needs a connection, but not a say in how it is made, imports a connector, the
/// composition decides which one, e.g. `tcp-connector`.
@since(version = 0.3.0-dev)
interface connector {
  @since(version = 0.3.0-dev)
  use types.{error-code};
  @since(version = 0.3.0-dev)
  use connection.{connection};

  /// Establishes a new connection.
  @since(version = 0.3.0-dev)
  connect: async func() -> result<connection, error-code>;
}

/// A transport for connections over wasi:sockets TCP.
interface tcp {
  @since(version = 0.3.0-dev)
  use types.{connect-opts, error-code, resp-value};
  @since(version = 0.3.0-dev)
  use connection.{connection};

  /// A TCP connection to a Valkey server, framing the bytes it carries into RESP values in each
  /// direction.
  @since(version = 0.3.0-dev)
  resource transport {
    /// Opens a transport to `host`, a hostname or an IP address. Each address the host resolves
    /// to is tried in turn.
    @since(version = 0.3.0-dev)
    open: static async func(host: string, port: u16) -> result<transport, error-code>;
    /// Writes each value from `requests` to the server, in order.
    ///
    /// May be called at most once, like `tcp-socket.send`. Closing `requests` half-closes the
    /// socket. The future resolves once every value is written, or with the error that stopped
    /// writing.
    @since(version = 0.3.0-dev)
    send: func(requests: stream<resp-value>) -> future<result<_, error-code>>;
    /// The values the server sends, in order.
    ///
    /// May be called at most once, like `tcp-socket.receive`. The stream closes when the server
    /// closes the socket, the future resolves to `ok` for a graceful close or to the error
    /// otherwise.
    @since(version = 0.3.0-dev)
    receive: func() -> tuple<stream<resp-value>, future<result<_, error-code>>>;
  }

  /// Opens a transport and establishes a connection over it with `opts`, see `connection.new`.
  ///
  /// The connection keeps the transport alive.
  @since(version = 0.3.0-dev)
  connect: async func(host: string, port: u16, opts: option<connect-opts>) -> result<connection, error-code>;
}

world imports {
  import types;
  import connection;
  import commands;
  import connector;
  import tcp;
  import tcp-connector-constants;
}