///|
/// Checks that Redis is reachable.
///
/// Example:
/// ```moonbit nocheck
/// assert_true(client.ping() == "PONG")
/// assert_true(client.ping(message="hello") == "hello")
/// ```
pub async fn Client::ping(self : Client, message? : String) -> String {
  self.execute(Command::ping(message?))
}

///|
pub async fn Client::echo(self : Client, message : String) -> String {
  self.execute(Command::echo(message))
}

///|
pub async fn Client::del(self : Client, keys : ArrayView[String]) -> Int {
  self.execute(Command::del(keys))
}

///|
pub async fn Client::exists(self : Client, keys : ArrayView[String]) -> Int {
  self.execute(Command::exists(keys))
}

///|
pub async fn Client::expire(self : Client, key : String, seconds : Int) -> Bool {
  self.execute(Command::expire(key, seconds))
}

///|
pub async fn Client::pexpire(
  self : Client,
  key : String,
  milliseconds : Int,
) -> Bool {
  self.execute(Command::pexpire(key, milliseconds))
}

///|
pub async fn Client::ttl(self : Client, key : String) -> Int {
  self.execute(Command::ttl(key))
}

///|
pub async fn Client::pttl(self : Client, key : String) -> Int {
  self.execute(Command::pttl(key))
}

///|
pub async fn Client::persist(self : Client, key : String) -> Bool {
  self.execute(Command::persist(key))
}

///|
pub async fn Client::rename(
  self : Client,
  key : String,
  new_key : String,
) -> Unit {
  self.execute(Command::rename(key, new_key))
}

///|
pub async fn Client::renamenx(
  self : Client,
  key : String,
  new_key : String,
) -> Bool {
  self.execute(Command::renamenx(key, new_key))
}

///|
pub async fn Client::type_(self : Client, key : String) -> String {
  self.execute(Command::type_(key))
}

///|
pub async fn Client::keys(self : Client, pattern : String) -> Array[String] {
  self.execute(Command::keys(pattern))
}

///|
pub async fn Client::scan(
  self : Client,
  cursor : String,
  pattern? : String,
  count? : Int,
) -> (String, Array[String]) {
  self.execute(Command::scan(cursor, pattern?, count?))
}

///|
pub async fn Client::randomkey(self : Client) -> String? {
  self.execute(Command::randomkey())
}

///|
/// Reads a string value. Returns `None` when the key does not exist.
///
/// Example:
/// ```moonbit nocheck
/// assert_true(client.get("missing") is None)
/// ```
pub async fn Client::get(self : Client, key : String) -> String? {
  self.execute(Command::get(key))
}

///|
/// Sets a string value.
///
/// Returns `false` when `nx` or `xx` prevents the write.
///
/// Example:
/// ```moonbit nocheck
/// assert_true(client.set("name", "MoonBit"))
/// assert_true(client.set("token", "abc", ex=60, nx=true))
/// ```
pub async fn Client::set(
  self : Client,
  key : String,
  value : String,
  ex? : Int,
  px? : Int,
  nx? : Bool,
  xx? : Bool,
) -> Bool {
  self.execute(Command::set(key, value, ex?, px?, nx?, xx?))
}

///|
pub async fn Client::set_get(
  self : Client,
  key : String,
  value : String,
  ex? : Int,
  px? : Int,
  nx? : Bool,
  xx? : Bool,
) -> String? {
  self.execute(Command::set_get(key, value, ex?, px?, nx?, xx?))
}

///|
pub async fn Client::setnx(self : Client, key : String, value : String) -> Bool {
  self.execute(Command::setnx(key, value))
}

///|
pub async fn Client::setex(
  self : Client,
  key : String,
  seconds : Int,
  value : String,
) -> Unit {
  self.execute(Command::setex(key, seconds, value))
}

///|
pub async fn Client::psetex(
  self : Client,
  key : String,
  milliseconds : Int,
  value : String,
) -> Unit {
  self.execute(Command::psetex(key, milliseconds, value))
}

///|
/// Reads multiple string values in the same order as `keys`.
///
/// Missing keys are returned as `None`.
///
/// Example:
/// ```moonbit nocheck
/// let values = client.mget(["name", "missing"])
/// assert_true(values is [Some("MoonBit"), None])
/// ```
pub async fn Client::mget(
  self : Client,
  keys : ArrayView[String],
) -> Array[String?] {
  self.execute(Command::mget(keys))
}

///|
pub async fn Client::mset(
  self : Client,
  items : ArrayView[(String, String)],
) -> Unit {
  self.execute(Command::mset(items))
}

///|
pub async fn Client::msetnx(
  self : Client,
  items : ArrayView[(String, String)],
) -> Bool {
  self.execute(Command::msetnx(items))
}

///|
/// Increments an integer string value by one and returns the new value.
///
/// Example:
/// ```moonbit nocheck
/// ignore(client.set("count", "1"))
/// assert_true(client.incr("count") == 2)
/// ```
pub async fn Client::incr(self : Client, key : String) -> Int {
  self.execute(Command::incr(key))
}

///|
pub async fn Client::incrby(
  self : Client,
  key : String,
  increment : Int,
) -> Int {
  self.execute(Command::incrby(key, increment))
}

///|
pub async fn Client::incrbyfloat(
  self : Client,
  key : String,
  increment : Double,
) -> Double {
  self.execute(Command::incrbyfloat(key, increment))
}

///|
pub async fn Client::decr(self : Client, key : String) -> Int {
  self.execute(Command::decr(key))
}

///|
pub async fn Client::decrby(
  self : Client,
  key : String,
  decrement : Int,
) -> Int {
  self.execute(Command::decrby(key, decrement))
}

///|
pub async fn Client::append(self : Client, key : String, value : String) -> Int {
  self.execute(Command::append(key, value))
}

///|
pub async fn Client::strlen(self : Client, key : String) -> Int {
  self.execute(Command::strlen(key))
}

///|
pub async fn Client::getrange(
  self : Client,
  key : String,
  start : Int,
  end : Int,
) -> String {
  self.execute(Command::getrange(key, start, end))
}

///|
pub async fn Client::setrange(
  self : Client,
  key : String,
  offset : Int,
  value : String,
) -> Int {
  self.execute(Command::setrange(key, offset, value))
}

///|
/// Reads a hash field. Returns `None` when the key or field does not exist.
///
/// Example:
/// ```moonbit nocheck
/// assert_true(client.hget("user:1", "name") is Some("MoonBit"))
/// ```
pub async fn Client::hget(
  self : Client,
  key : String,
  field : String,
) -> String? {
  self.execute(Command::hget(key, field))
}

///|
/// Sets a hash field and returns the number of fields newly added.
///
/// Example:
/// ```moonbit nocheck
/// ignore(client.hset("user:1", "name", "MoonBit"))
/// ```
pub async fn Client::hset(
  self : Client,
  key : String,
  field : String,
  value : String,
) -> Int {
  self.execute(Command::hset(key, field, value))
}

///|
pub async fn Client::hmset(
  self : Client,
  key : String,
  fields : ArrayView[(String, String)],
) -> Unit {
  self.execute(Command::hmset(key, fields))
}

///|
pub async fn Client::hdel(
  self : Client,
  key : String,
  fields : ArrayView[String],
) -> Int {
  self.execute(Command::hdel(key, fields))
}

///|
pub async fn Client::hexists(
  self : Client,
  key : String,
  field : String,
) -> Bool {
  self.execute(Command::hexists(key, field))
}

///|
/// Reads all fields from a hash as a map.
///
/// Example:
/// ```moonbit nocheck
/// let fields = client.hgetall("user:1")
/// ```
pub async fn Client::hgetall(
  self : Client,
  key : String,
) -> Map[String, String] {
  self.execute(Command::hgetall(key))
}

///|
pub async fn Client::hkeys(self : Client, key : String) -> Array[String] {
  self.execute(Command::hkeys(key))
}

///|
pub async fn Client::hvals(self : Client, key : String) -> Array[String] {
  self.execute(Command::hvals(key))
}

///|
pub async fn Client::hlen(self : Client, key : String) -> Int {
  self.execute(Command::hlen(key))
}

///|
pub async fn Client::hmget(
  self : Client,
  key : String,
  fields : ArrayView[String],
) -> Array[String?] {
  self.execute(Command::hmget(key, fields))
}

///|
pub async fn Client::hincrby(
  self : Client,
  key : String,
  field : String,
  increment : Int,
) -> Int {
  self.execute(Command::hincrby(key, field, increment))
}

///|
pub async fn Client::hincrbyfloat(
  self : Client,
  key : String,
  field : String,
  increment : Double,
) -> Double {
  self.execute(Command::hincrbyfloat(key, field, increment))
}

///|
pub async fn Client::hstrlen(
  self : Client,
  key : String,
  field : String,
) -> Int {
  self.execute(Command::hstrlen(key, field))
}

///|
pub async fn Client::hscan(
  self : Client,
  key : String,
  cursor : String,
  pattern? : String,
  count? : Int,
) -> (String, Map[String, String]) {
  self.execute(Command::hscan(key, cursor, pattern?, count?))
}

///|
/// Pushes values to the left side of a list and returns the new list length.
///
/// Example:
/// ```moonbit nocheck
/// ignore(client.lpush("jobs", ["a", "b"]))
/// ```
pub async fn Client::lpush(
  self : Client,
  key : String,
  values : ArrayView[String],
) -> Int {
  self.execute(Command::lpush(key, values))
}

///|
pub async fn Client::rpush(
  self : Client,
  key : String,
  values : ArrayView[String],
) -> Int {
  self.execute(Command::rpush(key, values))
}

///|
pub async fn Client::lpop(self : Client, key : String) -> String? {
  self.execute(Command::lpop(key))
}

///|
pub async fn Client::rpop(self : Client, key : String) -> String? {
  self.execute(Command::rpop(key))
}

///|
pub async fn Client::lpop_count(
  self : Client,
  key : String,
  count : Int,
) -> Array[String] {
  self.execute(Command::lpop_count(key, count))
}

///|
pub async fn Client::rpop_count(
  self : Client,
  key : String,
  count : Int,
) -> Array[String] {
  self.execute(Command::rpop_count(key, count))
}

///|
pub async fn Client::llen(self : Client, key : String) -> Int {
  self.execute(Command::llen(key))
}

///|
/// Reads a range from a list.
///
/// Example:
/// ```moonbit nocheck
/// let values = client.lrange("jobs", 0, -1)
/// ```
pub async fn Client::lrange(
  self : Client,
  key : String,
  start : Int,
  stop : Int,
) -> Array[String] {
  self.execute(Command::lrange(key, start, stop))
}

///|
pub async fn Client::lindex(
  self : Client,
  key : String,
  index : Int,
) -> String? {
  self.execute(Command::lindex(key, index))
}

///|
pub async fn Client::lset(
  self : Client,
  key : String,
  index : Int,
  value : String,
) -> Unit {
  self.execute(Command::lset(key, index, value))
}

///|
pub async fn Client::ltrim(
  self : Client,
  key : String,
  start : Int,
  stop : Int,
) -> Unit {
  self.execute(Command::ltrim(key, start, stop))
}

///|
pub async fn Client::lrem(
  self : Client,
  key : String,
  count : Int,
  value : String,
) -> Int {
  self.execute(Command::lrem(key, count, value))
}

///|
pub async fn Client::linsert_before(
  self : Client,
  key : String,
  pivot : String,
  value : String,
) -> Int {
  self.execute(Command::linsert_before(key, pivot, value))
}

///|
pub async fn Client::linsert_after(
  self : Client,
  key : String,
  pivot : String,
  value : String,
) -> Int {
  self.execute(Command::linsert_after(key, pivot, value))
}

///|
/// Adds members to a set and returns the number of members newly added.
///
/// Example:
/// ```moonbit nocheck
/// ignore(client.sadd("tags", ["moonbit", "redis"]))
/// ```
pub async fn Client::sadd(
  self : Client,
  key : String,
  members : ArrayView[String],
) -> Int {
  self.execute(Command::sadd(key, members))
}

///|
pub async fn Client::srem(
  self : Client,
  key : String,
  members : ArrayView[String],
) -> Int {
  self.execute(Command::srem(key, members))
}

///|
/// Reads all members of a set.
///
/// Example:
/// ```moonbit nocheck
/// let members = client.smembers("tags")
/// ```
pub async fn Client::smembers(
  self : Client,
  key : String,
) -> @hashset.HashSet[String] {
  self.execute(Command::smembers(key))
}

///|
pub async fn Client::sismember(
  self : Client,
  key : String,
  value : String,
) -> Bool {
  self.execute(Command::sismember(key, value))
}

///|
pub async fn Client::smismember(
  self : Client,
  key : String,
  members : ArrayView[String],
) -> Array[Bool] {
  self.execute(Command::smismember(key, members))
}

///|
pub async fn Client::scard(self : Client, key : String) -> Int {
  self.execute(Command::scard(key))
}

///|
pub async fn Client::spop(self : Client, key : String) -> String? {
  self.execute(Command::spop(key))
}

///|
pub async fn Client::spop_count(
  self : Client,
  key : String,
  count : Int,
) -> @hashset.HashSet[String] {
  self.execute(Command::spop_count(key, count))
}

///|
pub async fn Client::srandmember(self : Client, key : String) -> String? {
  self.execute(Command::srandmember(key))
}

///|
pub async fn Client::srandmember_count(
  self : Client,
  key : String,
  count : Int,
) -> Array[String] {
  self.execute(Command::srandmember_count(key, count))
}

///|
pub async fn Client::smove(
  self : Client,
  source : String,
  destination : String,
  value : String,
) -> Bool {
  self.execute(Command::smove(source, destination, value))
}

///|
pub async fn Client::sdiff(
  self : Client,
  keys : ArrayView[String],
) -> @hashset.HashSet[String] {
  self.execute(Command::sdiff(keys))
}

///|
pub async fn Client::sinter(
  self : Client,
  keys : ArrayView[String],
) -> @hashset.HashSet[String] {
  self.execute(Command::sinter(keys))
}

///|
pub async fn Client::sunion(
  self : Client,
  keys : ArrayView[String],
) -> @hashset.HashSet[String] {
  self.execute(Command::sunion(keys))
}

///|
pub async fn Client::sdiffstore(
  self : Client,
  destination : String,
  keys : ArrayView[String],
) -> Int {
  self.execute(Command::sdiffstore(destination, keys))
}

///|
pub async fn Client::sinterstore(
  self : Client,
  destination : String,
  keys : ArrayView[String],
) -> Int {
  self.execute(Command::sinterstore(destination, keys))
}

///|
pub async fn Client::sunionstore(
  self : Client,
  destination : String,
  keys : ArrayView[String],
) -> Int {
  self.execute(Command::sunionstore(destination, keys))
}

///|
pub async fn Client::sscan(
  self : Client,
  key : String,
  cursor : String,
  pattern? : String,
  count? : Int,
) -> (String, @hashset.HashSet[String]) {
  self.execute(Command::sscan(key, cursor, pattern?, count?))
}

///|
/// Adds members with scores to a sorted set.
///
/// Example:
/// ```moonbit nocheck
/// ignore(client.zadd("rank", [("alice", 10.0), ("bob", 8.0)]))
/// ```
pub async fn Client::zadd(
  self : Client,
  key : String,
  items : ArrayView[(String, Double)],
) -> Int {
  self.execute(Command::zadd(key, items))
}

///|
pub async fn Client::zrem(
  self : Client,
  key : String,
  members : ArrayView[String],
) -> Int {
  self.execute(Command::zrem(key, members))
}

///|
pub async fn Client::zscore(
  self : Client,
  key : String,
  value : String,
) -> Double? {
  self.execute(Command::zscore(key, value))
}

///|
pub async fn Client::zcard(self : Client, key : String) -> Int {
  self.execute(Command::zcard(key))
}

///|
pub async fn Client::zcount(
  self : Client,
  key : String,
  min : Double,
  max : Double,
) -> Int {
  self.execute(Command::zcount(key, min, max))
}

///|
pub async fn Client::zrank(self : Client, key : String, value : String) -> Int? {
  self.execute(Command::zrank(key, value))
}

///|
pub async fn Client::zrevrank(
  self : Client,
  key : String,
  value : String,
) -> Int? {
  self.execute(Command::zrevrank(key, value))
}

///|
/// Reads sorted set members by rank.
///
/// Example:
/// ```moonbit nocheck
/// let top = client.zrange("rank", 0, 9)
/// ```
pub async fn Client::zrange(
  self : Client,
  key : String,
  start : Int,
  stop : Int,
) -> Array[String] {
  self.execute(Command::zrange(key, start, stop))
}

///|
pub async fn Client::zrange_with_scores(
  self : Client,
  key : String,
  start : Int,
  stop : Int,
) -> Array[(String, Double)] {
  self.execute(Command::zrange_with_scores(key, start, stop))
}

///|
pub async fn Client::zrevrange(
  self : Client,
  key : String,
  start : Int,
  stop : Int,
) -> Array[String] {
  self.execute(Command::zrevrange(key, start, stop))
}

///|
pub async fn Client::zrevrange_with_scores(
  self : Client,
  key : String,
  start : Int,
  stop : Int,
) -> Array[(String, Double)] {
  self.execute(Command::zrevrange_with_scores(key, start, stop))
}

///|
pub async fn Client::zrangebyscore(
  self : Client,
  key : String,
  min : Double,
  max : Double,
  offset? : Int,
  count? : Int,
) -> Array[String] {
  self.execute(Command::zrangebyscore(key, min, max, offset?, count?))
}

///|
pub async fn Client::zrangebyscore_with_scores(
  self : Client,
  key : String,
  min : Double,
  max : Double,
  offset? : Int,
  count? : Int,
) -> Array[(String, Double)] {
  self.execute(
    Command::zrangebyscore_with_scores(key, min, max, offset?, count?),
  )
}

///|
pub async fn Client::zincrby(
  self : Client,
  key : String,
  increment : Double,
  value : String,
) -> Double {
  self.execute(Command::zincrby(key, increment, value))
}

///|
pub async fn Client::zremrangebyrank(
  self : Client,
  key : String,
  start : Int,
  stop : Int,
) -> Int {
  self.execute(Command::zremrangebyrank(key, start, stop))
}

///|
pub async fn Client::zremrangebyscore(
  self : Client,
  key : String,
  min : Double,
  max : Double,
) -> Int {
  self.execute(Command::zremrangebyscore(key, min, max))
}

///|
pub async fn Client::zpopmin(
  self : Client,
  key : String,
  count? : Int,
) -> Array[(String, Double)] {
  self.execute(Command::zpopmin(key, count?))
}

///|
pub async fn Client::zpopmax(
  self : Client,
  key : String,
  count? : Int,
) -> Array[(String, Double)] {
  self.execute(Command::zpopmax(key, count?))
}

///|
pub async fn Client::zscan(
  self : Client,
  key : String,
  cursor : String,
  pattern? : String,
  count? : Int,
) -> (String, Array[(String, Double)]) {
  self.execute(Command::zscan(key, cursor, pattern?, count?))
}