@upstash/redis 0.2.1 → 1.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. package/.eslintrc.js +49 -0
  2. package/.prettierrc.js +7 -0
  3. package/dist/chunk-7YUZYRJS.mjs +29 -0
  4. package/dist/chunk-FJSI5EBJ.mjs +38 -0
  5. package/dist/chunk-U7OXAQMQ.mjs +37 -0
  6. package/dist/chunk-Y5TC4HX2.mjs +798 -0
  7. package/dist/chunk-ZIB6XPPC.mjs +1061 -0
  8. package/dist/cloudflare.d.ts +38 -0
  9. package/dist/cloudflare.js +1738 -0
  10. package/dist/cloudflare.mjs +35 -0
  11. package/dist/commands.d.ts +206 -0
  12. package/dist/commands.js +1201 -0
  13. package/dist/commands.mjs +219 -0
  14. package/dist/fastly.d.ts +44 -0
  15. package/dist/fastly.js +1728 -0
  16. package/dist/fastly.mjs +25 -0
  17. package/dist/http.d.ts +29 -0
  18. package/dist/http.js +84 -0
  19. package/dist/http.mjs +7 -0
  20. package/dist/index.d.ts +13 -0
  21. package/dist/index.js +1744 -0
  22. package/dist/index.mjs +13 -0
  23. package/dist/nodejs.d.ts +47 -0
  24. package/dist/nodejs.js +1742 -0
  25. package/dist/nodejs.mjs +10 -0
  26. package/dist/package.json +1 -0
  27. package/dist/redis-dd052782.d.ts +962 -0
  28. package/dist/zunionstore-dffa797d.d.ts +670 -0
  29. package/jest.config.js +194 -4
  30. package/package.json +1 -75
  31. package/pkg/cloudflare.ts +77 -0
  32. package/pkg/command.ts +40 -0
  33. package/pkg/commands/append.test.ts +28 -0
  34. package/pkg/commands/append.ts +10 -0
  35. package/pkg/commands/bitcount.test.ts +36 -0
  36. package/pkg/commands/bitcount.ts +19 -0
  37. package/pkg/commands/bitop.test.ts +44 -0
  38. package/pkg/commands/bitop.ts +22 -0
  39. package/pkg/commands/bitpos.test.ts +26 -0
  40. package/pkg/commands/bitpos.ts +10 -0
  41. package/pkg/commands/dbsize.test.ts +17 -0
  42. package/pkg/commands/dbsize.ts +10 -0
  43. package/pkg/commands/decr.test.ts +22 -0
  44. package/pkg/commands/decr.ts +10 -0
  45. package/pkg/commands/decrby.test.ts +23 -0
  46. package/pkg/commands/decrby.ts +10 -0
  47. package/pkg/commands/del.test.ts +38 -0
  48. package/pkg/commands/del.ts +11 -0
  49. package/pkg/commands/echo.test.ts +11 -0
  50. package/pkg/commands/echo.ts +10 -0
  51. package/pkg/commands/exists.test.ts +37 -0
  52. package/pkg/commands/exists.ts +11 -0
  53. package/pkg/commands/expire.test.ts +22 -0
  54. package/pkg/commands/expire.ts +10 -0
  55. package/pkg/commands/expireat.test.ts +24 -0
  56. package/pkg/commands/expireat.ts +10 -0
  57. package/pkg/commands/flushall.test.ts +17 -0
  58. package/pkg/commands/flushall.ts +13 -0
  59. package/pkg/commands/flushdb.test.ts +17 -0
  60. package/pkg/commands/flushdb.ts +13 -0
  61. package/pkg/commands/get.test.ts +34 -0
  62. package/pkg/commands/get.ts +10 -0
  63. package/pkg/commands/getbit.test.ts +16 -0
  64. package/pkg/commands/getbit.ts +10 -0
  65. package/pkg/commands/getrange.test.ts +25 -0
  66. package/pkg/commands/getrange.ts +10 -0
  67. package/pkg/commands/getset.test.ts +33 -0
  68. package/pkg/commands/getset.ts +10 -0
  69. package/pkg/commands/hdel.test.ts +30 -0
  70. package/pkg/commands/hdel.ts +10 -0
  71. package/pkg/commands/hexists.test.ts +31 -0
  72. package/pkg/commands/hexists.ts +10 -0
  73. package/pkg/commands/hget.test.ts +47 -0
  74. package/pkg/commands/hget.ts +10 -0
  75. package/pkg/commands/hgetall.test.ts +32 -0
  76. package/pkg/commands/hgetall.ts +35 -0
  77. package/pkg/commands/hincrby.test.ts +27 -0
  78. package/pkg/commands/hincrby.ts +10 -0
  79. package/pkg/commands/hincrbyfloat.test.ts +25 -0
  80. package/pkg/commands/hincrbyfloat.ts +10 -0
  81. package/pkg/commands/hkeys.test.ts +22 -0
  82. package/pkg/commands/hkeys.ts +10 -0
  83. package/pkg/commands/hlen.test.ts +24 -0
  84. package/pkg/commands/hlen.ts +10 -0
  85. package/pkg/commands/hmget.test.ts +48 -0
  86. package/pkg/commands/hmget.ts +41 -0
  87. package/pkg/commands/hmset.test.ts +24 -0
  88. package/pkg/commands/hmset.ts +10 -0
  89. package/pkg/commands/hscan.test.ts +46 -0
  90. package/pkg/commands/hscan.ts +22 -0
  91. package/pkg/commands/hset.test.ts +21 -0
  92. package/pkg/commands/hset.ts +10 -0
  93. package/pkg/commands/hsetnx.test.ts +37 -0
  94. package/pkg/commands/hsetnx.ts +10 -0
  95. package/pkg/commands/hstrlen.test.ts +24 -0
  96. package/pkg/commands/hstrlen.ts +10 -0
  97. package/pkg/commands/hvals.test.ts +23 -0
  98. package/pkg/commands/hvals.ts +10 -0
  99. package/pkg/commands/incr.test.ts +23 -0
  100. package/pkg/commands/incr.ts +10 -0
  101. package/pkg/commands/incrby.test.ts +23 -0
  102. package/pkg/commands/incrby.ts +10 -0
  103. package/pkg/commands/incrbyfloat.test.ts +24 -0
  104. package/pkg/commands/incrbyfloat.ts +10 -0
  105. package/pkg/commands/index.ts +107 -0
  106. package/pkg/commands/keys.test.ts +17 -0
  107. package/pkg/commands/keys.ts +10 -0
  108. package/pkg/commands/lindex.test.ts +33 -0
  109. package/pkg/commands/lindex.ts +7 -0
  110. package/pkg/commands/linsert.test.ts +19 -0
  111. package/pkg/commands/linsert.ts +6 -0
  112. package/pkg/commands/llen.test.ts +26 -0
  113. package/pkg/commands/llen.ts +10 -0
  114. package/pkg/commands/lpop.test.ts +27 -0
  115. package/pkg/commands/lpop.ts +10 -0
  116. package/pkg/commands/lpush.test.ts +17 -0
  117. package/pkg/commands/lpush.ts +11 -0
  118. package/pkg/commands/lpushx.test.ts +29 -0
  119. package/pkg/commands/lpushx.ts +11 -0
  120. package/pkg/commands/lrange.test.ts +22 -0
  121. package/pkg/commands/lrange.ts +7 -0
  122. package/pkg/commands/lrem.test.ts +19 -0
  123. package/pkg/commands/lrem.ts +6 -0
  124. package/pkg/commands/lset.test.ts +40 -0
  125. package/pkg/commands/lset.ts +7 -0
  126. package/pkg/commands/ltrim.test.ts +29 -0
  127. package/pkg/commands/ltrim.ts +7 -0
  128. package/pkg/commands/mget.test.ts +44 -0
  129. package/pkg/commands/mget.ts +9 -0
  130. package/pkg/commands/mset.test.ts +24 -0
  131. package/pkg/commands/mset.ts +10 -0
  132. package/pkg/commands/msetnx.test.ts +46 -0
  133. package/pkg/commands/msetnx.ts +10 -0
  134. package/pkg/commands/persist.test.ts +22 -0
  135. package/pkg/commands/persist.ts +10 -0
  136. package/pkg/commands/pexpire.test.ts +24 -0
  137. package/pkg/commands/pexpire.ts +10 -0
  138. package/pkg/commands/pexpireat.test.ts +24 -0
  139. package/pkg/commands/pexpireat.ts +10 -0
  140. package/pkg/commands/ping.test.ts +19 -0
  141. package/pkg/commands/ping.ts +13 -0
  142. package/pkg/commands/psetex.test.ts +23 -0
  143. package/pkg/commands/psetex.ts +10 -0
  144. package/pkg/commands/pttl.test.ts +17 -0
  145. package/pkg/commands/pttl.ts +10 -0
  146. package/pkg/commands/randomkey.test.ts +17 -0
  147. package/pkg/commands/randomkey.ts +10 -0
  148. package/pkg/commands/rename.test.ts +18 -0
  149. package/pkg/commands/rename.ts +10 -0
  150. package/pkg/commands/renamenx.test.ts +32 -0
  151. package/pkg/commands/renamenx.ts +10 -0
  152. package/pkg/commands/rpop.test.ts +27 -0
  153. package/pkg/commands/rpop.ts +10 -0
  154. package/pkg/commands/rpush.test.ts +17 -0
  155. package/pkg/commands/rpush.ts +11 -0
  156. package/pkg/commands/rpushx.test.ts +29 -0
  157. package/pkg/commands/rpushx.ts +11 -0
  158. package/pkg/commands/sadd.test.ts +16 -0
  159. package/pkg/commands/sadd.ts +11 -0
  160. package/pkg/commands/scan.test.ts +50 -0
  161. package/pkg/commands/scan.ts +21 -0
  162. package/pkg/commands/scard.test.ts +15 -0
  163. package/pkg/commands/scard.ts +9 -0
  164. package/pkg/commands/sdiff.test.ts +20 -0
  165. package/pkg/commands/sdiff.ts +9 -0
  166. package/pkg/commands/sdiffstore.test.ts +21 -0
  167. package/pkg/commands/sdiffstore.ts +10 -0
  168. package/pkg/commands/set.test.ts +112 -0
  169. package/pkg/commands/set.ts +53 -0
  170. package/pkg/commands/setbit.test.ts +16 -0
  171. package/pkg/commands/setbit.ts +10 -0
  172. package/pkg/commands/setex.test.ts +22 -0
  173. package/pkg/commands/setex.ts +10 -0
  174. package/pkg/commands/setnx.test.ts +27 -0
  175. package/pkg/commands/setnx.ts +10 -0
  176. package/pkg/commands/setrange.test.ts +25 -0
  177. package/pkg/commands/setrange.ts +10 -0
  178. package/pkg/commands/sinter.test.ts +36 -0
  179. package/pkg/commands/sinter.ts +9 -0
  180. package/pkg/commands/sinterstore.test.ts +21 -0
  181. package/pkg/commands/sinterstore.ts +9 -0
  182. package/pkg/commands/sismember.test.ts +30 -0
  183. package/pkg/commands/sismember.ts +9 -0
  184. package/pkg/commands/smembers.test.ts +22 -0
  185. package/pkg/commands/smembers.ts +10 -0
  186. package/pkg/commands/smove.test.ts +18 -0
  187. package/pkg/commands/smove.ts +9 -0
  188. package/pkg/commands/spop.test.ts +35 -0
  189. package/pkg/commands/spop.ts +13 -0
  190. package/pkg/commands/srandmember.test.ts +32 -0
  191. package/pkg/commands/srandmember.ts +13 -0
  192. package/pkg/commands/srem.test.ts +18 -0
  193. package/pkg/commands/srem.ts +10 -0
  194. package/pkg/commands/sscan.test.ts +50 -0
  195. package/pkg/commands/sscan.ts +22 -0
  196. package/pkg/commands/strlen.test.ts +16 -0
  197. package/pkg/commands/strlen.ts +10 -0
  198. package/pkg/commands/sunion.test.ts +22 -0
  199. package/pkg/commands/sunion.ts +10 -0
  200. package/pkg/commands/sunionstore.test.ts +29 -0
  201. package/pkg/commands/sunionstore.ts +10 -0
  202. package/pkg/commands/time.test.ts +11 -0
  203. package/pkg/commands/time.ts +9 -0
  204. package/pkg/commands/touch.test.ts +20 -0
  205. package/pkg/commands/touch.ts +10 -0
  206. package/pkg/commands/ttl.test.ts +17 -0
  207. package/pkg/commands/ttl.ts +10 -0
  208. package/pkg/commands/type.test.ts +72 -0
  209. package/pkg/commands/type.ts +11 -0
  210. package/pkg/commands/unlink.test.ts +21 -0
  211. package/pkg/commands/unlink.ts +10 -0
  212. package/pkg/commands/zadd.test.ts +177 -0
  213. package/pkg/commands/zadd.ts +64 -0
  214. package/pkg/commands/zcard.test.ts +15 -0
  215. package/pkg/commands/zcard.ts +10 -0
  216. package/pkg/commands/zcount.test.ts +15 -0
  217. package/pkg/commands/zcount.ts +9 -0
  218. package/pkg/commands/zincrby.test.ts +20 -0
  219. package/pkg/commands/zincrby.ts +9 -0
  220. package/pkg/commands/zinterstore.test.ts +239 -0
  221. package/pkg/commands/zinterstore.ts +55 -0
  222. package/pkg/commands/zlexcount.test.ts +22 -0
  223. package/pkg/commands/zlexcount.ts +9 -0
  224. package/pkg/commands/zpopmax.test.ts +45 -0
  225. package/pkg/commands/zpopmax.ts +13 -0
  226. package/pkg/commands/zpopmin.test.ts +49 -0
  227. package/pkg/commands/zpopmin.ts +13 -0
  228. package/pkg/commands/zrange.test.ts +52 -0
  229. package/pkg/commands/zrange.ts +22 -0
  230. package/pkg/commands/zrank.test.ts +22 -0
  231. package/pkg/commands/zrank.ts +10 -0
  232. package/pkg/commands/zrem.test.ts +20 -0
  233. package/pkg/commands/zrem.ts +10 -0
  234. package/pkg/commands/zremrangebylex.test.ts +26 -0
  235. package/pkg/commands/zremrangebylex.ts +9 -0
  236. package/pkg/commands/zremrangebyrank.test.ts +27 -0
  237. package/pkg/commands/zremrangebyrank.ts +9 -0
  238. package/pkg/commands/zremrangebyscore.test.ts +24 -0
  239. package/pkg/commands/zremrangebyscore.ts +9 -0
  240. package/pkg/commands/zrevrank.test.ts +22 -0
  241. package/pkg/commands/zrevrank.ts +10 -0
  242. package/pkg/commands/zscan.test.ts +50 -0
  243. package/pkg/commands/zscan.ts +22 -0
  244. package/pkg/commands/zscore.test.ts +18 -0
  245. package/pkg/commands/zscore.ts +10 -0
  246. package/pkg/commands/zunionstore.test.ts +215 -0
  247. package/pkg/commands/zunionstore.ts +55 -0
  248. package/pkg/commands/zz.ts +1 -0
  249. package/pkg/error.ts +9 -0
  250. package/pkg/fastly.ts +54 -0
  251. package/pkg/http.test.ts +34 -0
  252. package/pkg/http.ts +62 -0
  253. package/pkg/index.ts +2 -0
  254. package/pkg/nodejs.ts +83 -0
  255. package/pkg/pipeline.test.ts +177 -0
  256. package/pkg/pipeline.ts +999 -0
  257. package/pkg/redis.ts +930 -0
  258. package/pkg/test-utils.ts +41 -0
  259. package/pkg/types.ts +4 -0
  260. package/pkg/util.ts +22 -0
  261. package/pnpm-lock.yaml +3940 -0
  262. package/tsconfig.json +96 -16
  263. package/tsup.config.ts +16 -0
  264. package/README.md +0 -63
  265. package/dist/main/client.d.ts +0 -21
  266. package/dist/main/client.js +0 -564
  267. package/dist/main/index-cjs.d.ts +0 -1
  268. package/dist/main/index-cjs.js +0 -120
  269. package/dist/main/types.d.ts +0 -179
  270. package/dist/main/types.js +0 -2
  271. package/dist/module/client.d.ts +0 -21
  272. package/dist/module/client.js +0 -559
  273. package/dist/module/index.d.ts +0 -3
  274. package/dist/module/index.js +0 -3
  275. package/dist/module/types.d.ts +0 -179
  276. package/dist/module/types.js +0 -1
  277. package/src/client.ts +0 -626
  278. package/src/index-cjs.ts +0 -117
  279. package/src/index.ts +0 -118
  280. package/src/types.ts +0 -410
@@ -0,0 +1,22 @@
1
+ import { ScanCommandOptions } from "./scan"
2
+ import { Command } from "../command"
3
+
4
+ /**
5
+ * @see https://redis.io/commands/sscan
6
+ */
7
+ export class SScanCommand extends Command<
8
+ [number, (string | number)[]],
9
+ [number, (string | number)[]]
10
+ > {
11
+ constructor(key: string, cursor: number, opts?: ScanCommandOptions) {
12
+ const command = ["sscan", key, cursor]
13
+ if (opts?.match) {
14
+ command.push("match", opts.match)
15
+ }
16
+ if (typeof opts?.count === "number") {
17
+ command.push("count", opts.count)
18
+ }
19
+
20
+ super(command)
21
+ }
22
+ }
@@ -0,0 +1,16 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { it, expect, afterAll } from "@jest/globals"
3
+ import { SetCommand } from "./set"
4
+ import { StrLenCommand } from "./strlen"
5
+ const client = newHttpClient()
6
+
7
+ const { newKey, cleanup } = keygen()
8
+ afterAll(cleanup)
9
+
10
+ it("returns the correct length", async () => {
11
+ const key = newKey()
12
+ const value = "abcd"
13
+ await new SetCommand(key, value).exec(client)
14
+ const res = await new StrLenCommand(key).exec(client)
15
+ expect(res).toBe(value.length)
16
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/strlen
5
+ */
6
+ export class StrLenCommand extends Command<number, number> {
7
+ constructor(key: string) {
8
+ super(["strlen", key])
9
+ }
10
+ }
@@ -0,0 +1,22 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { randomUUID } from "crypto"
3
+ import { it, expect, afterAll } from "@jest/globals"
4
+ import { SAddCommand } from "./sadd"
5
+ import { SUnionCommand } from "./sunion"
6
+ const client = newHttpClient()
7
+
8
+ const { newKey, cleanup } = keygen()
9
+ afterAll(cleanup)
10
+
11
+ it("returns the union", async () => {
12
+ const key1 = newKey()
13
+ const key2 = newKey()
14
+
15
+ const member1 = randomUUID()
16
+ const member2 = randomUUID()
17
+
18
+ await new SAddCommand(key1, member1).exec(client)
19
+ await new SAddCommand(key2, member2).exec(client)
20
+ const res = await new SUnionCommand(key1, key2).exec(client)
21
+ expect(res?.sort()).toEqual([member1, member2].sort())
22
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/sunion
5
+ */
6
+ export class SUnionCommand<TData> extends Command<TData[], string[]> {
7
+ constructor(key: string, ...keys: string[]) {
8
+ super(["sunion", key, ...keys])
9
+ }
10
+ }
@@ -0,0 +1,29 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { randomUUID } from "crypto"
3
+ import { it, expect, afterAll } from "@jest/globals"
4
+ import { SAddCommand } from "./sadd"
5
+ import { SUnionStoreCommand } from "./sunionstore"
6
+ import { SMembersCommand } from "./smembers"
7
+ const client = newHttpClient()
8
+
9
+ const { newKey, cleanup } = keygen()
10
+ afterAll(cleanup)
11
+
12
+ it("writes the union to destination", async () => {
13
+ const key1 = newKey()
14
+ const key2 = newKey()
15
+ const dest = newKey()
16
+
17
+ const member1 = randomUUID()
18
+ const member2 = randomUUID()
19
+
20
+ await new SAddCommand(key1, member1).exec(client)
21
+ await new SAddCommand(key2, member2).exec(client)
22
+ const res = await new SUnionStoreCommand(dest, key1, key2).exec(client)
23
+ expect(res).toBe(2)
24
+
25
+ const res2 = await new SMembersCommand(dest).exec(client)
26
+
27
+ expect(res2).toBeDefined()
28
+ expect(res2!.sort()).toEqual([member1, member2].sort())
29
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/sunionstore
5
+ */
6
+ export class SUnionStoreCommand extends Command<number, number> {
7
+ constructor(destination: string, key: string, ...keys: string[]) {
8
+ super(["sunionstore", destination, key, ...keys])
9
+ }
10
+ }
@@ -0,0 +1,11 @@
1
+ import { newHttpClient } from "../test-utils"
2
+ import { it, expect } from "@jest/globals"
3
+ import { TimeCommand } from "./time"
4
+ const client = newHttpClient()
5
+
6
+ it("returns the time", async () => {
7
+ const res = await new TimeCommand().exec(client)
8
+ expect(res).toBeDefined()
9
+ expect(typeof res[0]).toBe("number")
10
+ expect(typeof res[1]).toBe("number")
11
+ })
@@ -0,0 +1,9 @@
1
+ import { Command } from "../command"
2
+ /**
3
+ * @see https://redis.io/commands/time
4
+ */
5
+ export class TimeCommand extends Command<[number, number], [number, number]> {
6
+ constructor() {
7
+ super(["time"])
8
+ }
9
+ }
@@ -0,0 +1,20 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { randomUUID } from "crypto"
3
+ import { it, expect, afterAll } from "@jest/globals"
4
+ import { MSetCommand } from "./mset"
5
+ import { TouchCommand } from "./touch"
6
+ const client = newHttpClient()
7
+
8
+ const { newKey, cleanup } = keygen()
9
+ afterAll(cleanup)
10
+
11
+ it("returns the number of touched keys", async () => {
12
+ const key1 = newKey()
13
+ const key2 = newKey()
14
+ const kv: Record<string, string> = {}
15
+ kv[key1] = randomUUID()
16
+ kv[key2] = randomUUID()
17
+ await new MSetCommand(kv).exec(client)
18
+ const res = await new TouchCommand(key1, key2).exec(client)
19
+ expect(res).toBe(2)
20
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/touch
5
+ */
6
+ export class TouchCommand extends Command<number, number> {
7
+ constructor(...keys: string[]) {
8
+ super(["touch", ...keys])
9
+ }
10
+ }
@@ -0,0 +1,17 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+
3
+ import { it, expect, afterAll } from "@jest/globals"
4
+ import { SetExCommand } from "./setex"
5
+ import { TtlCommand } from "./ttl"
6
+ const client = newHttpClient()
7
+
8
+ const { newKey, cleanup } = keygen()
9
+ afterAll(cleanup)
10
+
11
+ it("returns the ttl on a key", async () => {
12
+ const key = newKey()
13
+ const ttl = 60
14
+ await new SetExCommand(key, ttl, "value").exec(client)
15
+ const res = await new TtlCommand(key).exec(client)
16
+ expect(res).toBeLessThanOrEqual(ttl)
17
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/ttl
5
+ */
6
+ export class TtlCommand extends Command<number, number> {
7
+ constructor(key: string) {
8
+ super(["ttl", key])
9
+ }
10
+ }
@@ -0,0 +1,72 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { randomUUID } from "crypto"
3
+ import { describe, it, expect, afterAll } from "@jest/globals"
4
+ import { SetCommand } from "./set"
5
+ import { TypeCommand } from "./type"
6
+ import { LPushCommand } from "./lpush"
7
+ import { HSetCommand } from "./hset"
8
+ import { SAddCommand } from "./sadd"
9
+ import { ZAddCommand } from "./zadd"
10
+ const client = newHttpClient()
11
+
12
+ const { newKey, cleanup } = keygen()
13
+ afterAll(cleanup)
14
+
15
+ describe("string", () => {
16
+ it("returns the correct type", async () => {
17
+ const key = newKey()
18
+ const value = randomUUID()
19
+ await new SetCommand(key, value).exec(client)
20
+ const res = await new TypeCommand(key).exec(client)
21
+ expect(res).toEqual("string")
22
+ })
23
+ })
24
+
25
+ describe("list", () => {
26
+ it("returns the correct type", async () => {
27
+ const key = newKey()
28
+ const value = randomUUID()
29
+ await new LPushCommand(key, value).exec(client)
30
+ const res = await new TypeCommand(key).exec(client)
31
+ expect(res).toEqual("list")
32
+ })
33
+ })
34
+
35
+ describe("set", () => {
36
+ it("returns the correct type", async () => {
37
+ const key = newKey()
38
+ const value = randomUUID()
39
+ await new SAddCommand(key, value).exec(client)
40
+ const res = await new TypeCommand(key).exec(client)
41
+ expect(res).toEqual("set")
42
+ })
43
+ })
44
+
45
+ describe("hash", () => {
46
+ it("returns the correct type", async () => {
47
+ const key = newKey()
48
+ const field = randomUUID()
49
+ const value = randomUUID()
50
+ await new HSetCommand(key, field, value).exec(client)
51
+ const res = await new TypeCommand(key).exec(client)
52
+ expect(res).toEqual("hash")
53
+ })
54
+ })
55
+
56
+ describe("zset", () => {
57
+ it("returns the correct type", async () => {
58
+ const key = newKey()
59
+ const member = randomUUID()
60
+ await new ZAddCommand(key, { score: 0, member }).exec(client)
61
+ const res = await new TypeCommand(key).exec(client)
62
+ expect(res).toEqual("zset")
63
+ })
64
+ })
65
+
66
+ describe("none", () => {
67
+ it("returns the correct type", async () => {
68
+ const key = newKey()
69
+ const res = await new TypeCommand(key).exec(client)
70
+ expect(res).toEqual("none")
71
+ })
72
+ })
@@ -0,0 +1,11 @@
1
+ import { Command } from "../command"
2
+
3
+ export type Type = "string" | "list" | "set" | "zset" | "hash" | "none"
4
+ /**
5
+ * @see https://redis.io/commands/type
6
+ */
7
+ export class TypeCommand extends Command<Type, Type> {
8
+ constructor(key: string) {
9
+ super(["type", key])
10
+ }
11
+ }
@@ -0,0 +1,21 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { randomUUID } from "crypto"
3
+ import { it, expect, afterAll } from "@jest/globals"
4
+ import { MSetCommand } from "./mset"
5
+ import { UnlinkCommand } from "./unlink"
6
+ const client = newHttpClient()
7
+
8
+ const { newKey, cleanup } = keygen()
9
+ afterAll(cleanup)
10
+
11
+ it("unlinks the keys", async () => {
12
+ const key1 = newKey()
13
+ const key2 = newKey()
14
+ const key3 = newKey()
15
+ const kv: Record<string, string> = {}
16
+ kv[key1] = randomUUID()
17
+ kv[key2] = randomUUID()
18
+ await new MSetCommand(kv).exec(client)
19
+ const res = await new UnlinkCommand(key1, key2, key3).exec(client)
20
+ expect(res).toEqual(2)
21
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/unlink
5
+ */
6
+ export class UnlinkCommand extends Command<number, number> {
7
+ constructor(...keys: string[]) {
8
+ super(["unlink", ...keys])
9
+ }
10
+ }
@@ -0,0 +1,177 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { randomInt, randomUUID } from "crypto"
3
+ import { describe, it, expect, afterAll } from "@jest/globals"
4
+ import { ZAddCommand } from "./zadd"
5
+ import { ZScoreCommand } from "./zscore"
6
+ const client = newHttpClient()
7
+
8
+ const { newKey, cleanup } = keygen()
9
+ afterAll(cleanup)
10
+
11
+ describe("command format", () => {
12
+ describe("without options", () => {
13
+ it("build the correct command", () => {
14
+ expect(new ZAddCommand("key", { score: 0, member: "member" }).command).toEqual([
15
+ "zadd",
16
+ "key",
17
+ "0",
18
+ "member",
19
+ ])
20
+ })
21
+ })
22
+ describe("with nx", () => {
23
+ it("build the correct command", () => {
24
+ expect(new ZAddCommand("key", { nx: true }, { score: 0, member: "member" }).command).toEqual([
25
+ "zadd",
26
+ "key",
27
+ "nx",
28
+ "0",
29
+ "member",
30
+ ])
31
+ })
32
+ })
33
+ describe("with xx", () => {
34
+ it("build the correct command", () => {
35
+ expect(new ZAddCommand("key", { xx: true }, { score: 0, member: "member" }).command).toEqual([
36
+ "zadd",
37
+ "key",
38
+ "xx",
39
+ "0",
40
+ "member",
41
+ ])
42
+ })
43
+ })
44
+ describe("with ch", () => {
45
+ it("build the correct command", () => {
46
+ expect(new ZAddCommand("key", { ch: true }, { score: 0, member: "member" }).command).toEqual([
47
+ "zadd",
48
+ "key",
49
+ "ch",
50
+ "0",
51
+ "member",
52
+ ])
53
+ })
54
+ })
55
+ describe("with incr", () => {
56
+ it("build the correct command", () => {
57
+ expect(
58
+ new ZAddCommand("key", { incr: true }, { score: 0, member: "member" }).command,
59
+ ).toEqual(["zadd", "key", "incr", "0", "member"])
60
+ })
61
+ })
62
+ describe("with nx and ch", () => {
63
+ it("build the correct command", () => {
64
+ expect(
65
+ new ZAddCommand("key", { nx: true, ch: true }, { score: 0, member: "member" }).command,
66
+ ).toEqual(["zadd", "key", "nx", "ch", "0", "member"])
67
+ })
68
+ })
69
+ describe("with nx,ch and incr", () => {
70
+ it("build the correct command", () => {
71
+ expect(
72
+ new ZAddCommand("key", { nx: true, ch: true, incr: true }, { score: 0, member: "member" })
73
+ .command,
74
+ ).toEqual(["zadd", "key", "nx", "ch", "incr", "0", "member"])
75
+ })
76
+ })
77
+ describe("with nx and multiple members", () => {
78
+ it("build the correct command", () => {
79
+ expect(
80
+ new ZAddCommand(
81
+ "key",
82
+ { nx: true },
83
+ { score: 0, member: "member" },
84
+ { score: 1, member: "member1" },
85
+ ).command,
86
+ ).toEqual(["zadd", "key", "nx", "0", "member", "1", "member1"])
87
+ })
88
+ })
89
+ })
90
+
91
+ describe("without options", () => {
92
+ it("adds the member", async () => {
93
+ const key = newKey()
94
+ const member = randomUUID()
95
+ const score = randomInt(10)
96
+ const res = await new ZAddCommand(key, { score, member }).exec(client)
97
+ expect(res).toBe(1)
98
+ })
99
+ })
100
+
101
+ describe("xx", () => {
102
+ describe("when the element exists", () => {
103
+ it("updates the element", async () => {
104
+ const key = newKey()
105
+ const member = randomUUID()
106
+ const score = randomInt(10)
107
+ await new ZAddCommand(key, { score, member }).exec(client)
108
+ const newScore = score + 1
109
+ const res = await new ZAddCommand(key, { xx: true }, { score: newScore, member }).exec(client)
110
+ expect(res).toBe(0)
111
+
112
+ const res2 = await new ZScoreCommand(key, member).exec(client)
113
+ expect(res2).toBe(newScore)
114
+ })
115
+ })
116
+ describe("when the element does not exist", () => {
117
+ it("does nothing", async () => {
118
+ const key = newKey()
119
+ const member = randomUUID()
120
+ const score = randomInt(10)
121
+ await new ZAddCommand(key, { score, member }).exec(client)
122
+ const newScore = score + 1
123
+ const res = await new ZAddCommand(key, { xx: true }, { score: newScore, member }).exec(client)
124
+ expect(res).toBe(0)
125
+ })
126
+ })
127
+ })
128
+
129
+ describe("nx", () => {
130
+ describe("when the element exists", () => {
131
+ it("does nothing", async () => {
132
+ const key = newKey()
133
+ const member = randomUUID()
134
+ const score = randomInt(10)
135
+ await new ZAddCommand(key, { score, member }).exec(client)
136
+ const newScore = score + 1
137
+ const res = await new ZAddCommand(key, { nx: true }, { score: newScore, member }).exec(client)
138
+ expect(res).toBe(0)
139
+
140
+ const res2 = await new ZScoreCommand(key, member).exec(client)
141
+ expect(res2).toBe(score)
142
+ })
143
+ })
144
+ describe("when the element does not exist", () => {
145
+ it("creates element", async () => {
146
+ const key = newKey()
147
+ const member = randomUUID()
148
+ const score = randomInt(10)
149
+ const res = await new ZAddCommand(key, { nx: true }, { score, member }).exec(client)
150
+ expect(res).toBe(1)
151
+ })
152
+ })
153
+ })
154
+
155
+ describe("ch", () => {
156
+ it("returns the number of changed elements", async () => {
157
+ const key = newKey()
158
+ const member = randomUUID()
159
+ const score = randomInt(10)
160
+ await new ZAddCommand(key, { score, member }).exec(client)
161
+ const newScore = score + 1
162
+ const res = await new ZAddCommand(key, { ch: true }, { score: newScore, member }).exec(client)
163
+ expect(res).toBe(1)
164
+ })
165
+ })
166
+
167
+ describe("incr", () => {
168
+ it("returns the number of changed elements", async () => {
169
+ const key = newKey()
170
+ const member = randomUUID()
171
+ const score = randomInt(10)
172
+ await new ZAddCommand(key, { score, member }).exec(client)
173
+ const newScore = score + 1
174
+ const res = await new ZAddCommand(key, { ch: true }, { score: newScore, member }).exec(client)
175
+ expect(res).toBe(1)
176
+ })
177
+ })
@@ -0,0 +1,64 @@
1
+ import { Command } from "../command"
2
+
3
+ export type ZAddCommandOptions = (
4
+ | {
5
+ nx: true
6
+ xx?: never
7
+ }
8
+ | {
9
+ nx?: never
10
+ xx: true
11
+ }
12
+ | { nx?: never; xx?: never }
13
+ ) & { ch?: true }
14
+
15
+ export type ZAddCommandOptionsWithIncr = ZAddCommandOptions & {
16
+ incr: true
17
+ }
18
+
19
+ export type ScoreMember<TData> = {
20
+ score: number
21
+ member: TData
22
+ }
23
+ /**
24
+ * @see https://redis.io/commands/zadd
25
+ */
26
+ export class ZAddCommand<TData = string> extends Command<number | null, number | null> {
27
+ constructor(
28
+ key: string,
29
+ scoreMember: ScoreMember<TData>,
30
+ ...scoreMemberPairs: ScoreMember<TData>[]
31
+ )
32
+ constructor(
33
+ key: string,
34
+ opts: ZAddCommandOptions | ZAddCommandOptionsWithIncr,
35
+ ...scoreMemberPairs: [ScoreMember<TData>, ...ScoreMember<TData>[]]
36
+ )
37
+ constructor(
38
+ key: string,
39
+ arg1: ScoreMember<TData> | ZAddCommandOptions | ZAddCommandOptionsWithIncr,
40
+ ...arg2: ScoreMember<TData>[]
41
+ ) {
42
+ const command: unknown[] = ["zadd", key]
43
+
44
+ if ("nx" in arg1 && arg1.nx) {
45
+ command.push("nx")
46
+ } else if ("xx" in arg1 && arg1.xx) {
47
+ command.push("xx")
48
+ }
49
+ if ("ch" in arg1 && arg1.ch) {
50
+ command.push("ch")
51
+ }
52
+ if ("incr" in arg1 && arg1.incr) {
53
+ command.push("incr")
54
+ }
55
+
56
+ if ("score" in arg1 && "member" in arg1) {
57
+ command.push(arg1.score, arg1.member)
58
+ }
59
+
60
+ command.push(...arg2.flatMap(({ score, member }) => [score, member]))
61
+
62
+ super(command)
63
+ }
64
+ }
@@ -0,0 +1,15 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { it, expect, afterAll } from "@jest/globals"
3
+ import { ZAddCommand } from "./zadd"
4
+ import { ZCardCommand } from "./zcard"
5
+ const client = newHttpClient()
6
+
7
+ const { newKey, cleanup } = keygen()
8
+ afterAll(cleanup)
9
+
10
+ it("returns the cardinality", async () => {
11
+ const key = newKey()
12
+ await new ZAddCommand(key, { score: 1, member: "member1" }).exec(client)
13
+ const res = await new ZCardCommand(key).exec(client)
14
+ expect(res).toBe(1)
15
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/zcard
5
+ */
6
+ export class ZCardCommand extends Command<number, number> {
7
+ constructor(key: string) {
8
+ super(["zcard", key])
9
+ }
10
+ }
@@ -0,0 +1,15 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { it, expect, afterAll } from "@jest/globals"
3
+ import { ZAddCommand } from "./zadd"
4
+ import { ZCountCommand } from "./zcount"
5
+ const client = newHttpClient()
6
+
7
+ const { newKey, cleanup } = keygen()
8
+ afterAll(cleanup)
9
+
10
+ it("returns the cardinality", async () => {
11
+ const key = newKey()
12
+ await new ZAddCommand(key, { score: 1, member: "member1" }).exec(client)
13
+ const res = await new ZCountCommand(key, 0, 2).exec(client)
14
+ expect(res).toBe(1)
15
+ })
@@ -0,0 +1,9 @@
1
+ import { Command } from "../command"
2
+ /**
3
+ * @see https://redis.io/commands/zcount
4
+ */
5
+ export class ZCountCommand extends Command<number, number> {
6
+ constructor(key: string, min: number | string, max: number | string) {
7
+ super(["zcount", key, min, max])
8
+ }
9
+ }
@@ -0,0 +1,20 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { it, expect, afterAll } from "@jest/globals"
3
+ import { ZIncrByComand } from "./zincrby"
4
+ import { ZAddCommand } from "./zadd"
5
+ import { randomUUID } from "crypto"
6
+
7
+ const client = newHttpClient()
8
+
9
+ const { newKey, cleanup } = keygen()
10
+ afterAll(cleanup)
11
+
12
+ it("increments and existing value", async () => {
13
+ const key = newKey()
14
+ const score = 1
15
+ const member = randomUUID()
16
+ await new ZAddCommand(key, { score, member }).exec(client)
17
+ const res = await new ZIncrByComand(key, 2, member).exec(client)
18
+
19
+ expect(res).toEqual(3)
20
+ })
@@ -0,0 +1,9 @@
1
+ import { Command } from "../command"
2
+ /**
3
+ * @see https://redis.io/commands/zincrby
4
+ */
5
+ export class ZIncrByComand<TData> extends Command<number, number> {
6
+ constructor(key: string, increment: number, member: TData) {
7
+ super(["zincrby", key, increment, member])
8
+ }
9
+ }