@upstash/redis 1.0.0-alpha.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 (264) 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-RYSRH3HC.mjs → chunk-ZIB6XPPC.mjs} +4 -27
  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 +3 -2
  12. package/dist/commands.js +1 -1
  13. package/dist/commands.mjs +2 -1
  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 +5 -1003
  21. package/dist/index.js +62 -72
  22. package/dist/index.mjs +8 -857
  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-462de5d3.d.ts → zunionstore-dffa797d.d.ts} +2 -27
  29. package/jest.config.js +195 -0
  30. package/package.json +1 -1
  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 +100 -0
  263. package/tsconfig.module.json +8 -0
  264. package/tsup.config.ts +16 -0
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/decrby
5
+ */
6
+ export class DecrByCommand extends Command<number, number> {
7
+ constructor(key: string, decrement: number) {
8
+ super(["decrby", key, decrement])
9
+ }
10
+ }
@@ -0,0 +1,38 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+
3
+ import { DelCommand } from "./del"
4
+ import { SetCommand } from "./set"
5
+ import { describe, it, expect, afterAll } from "@jest/globals"
6
+
7
+ const client = newHttpClient()
8
+
9
+ const { newKey, cleanup } = keygen()
10
+ afterAll(cleanup)
11
+
12
+ describe("when key does not exist", () => {
13
+ it("does nothing", async () => {
14
+ const key = newKey()
15
+
16
+ const res = await new DelCommand(key).exec(client)
17
+ expect(res).toEqual(0)
18
+ })
19
+ })
20
+ describe("when key does exist", () => {
21
+ it("deletes the key", async () => {
22
+ const key = newKey()
23
+ await new SetCommand(key, "value").exec(client)
24
+ const res = await new DelCommand(key).exec(client)
25
+ expect(res).toEqual(1)
26
+ })
27
+ })
28
+ describe("with multiple keys", () => {
29
+ describe("when one does not exist", () => {
30
+ it("deletes all keys", async () => {
31
+ const key1 = newKey()
32
+ const key2 = newKey()
33
+ await new SetCommand(key1, "value").exec(client)
34
+ const res = await new DelCommand(key1, key2).exec(client)
35
+ expect(res).toEqual(1)
36
+ })
37
+ })
38
+ })
@@ -0,0 +1,11 @@
1
+ import { NonEmptyArray } from "../types"
2
+ import { Command } from "../command"
3
+
4
+ /**
5
+ * @see https://redis.io/commands/del
6
+ */
7
+ export class DelCommand extends Command<number, number> {
8
+ constructor(...keys: NonEmptyArray<string>) {
9
+ super(["del", ...keys])
10
+ }
11
+ }
@@ -0,0 +1,11 @@
1
+ import { newHttpClient } from "../test-utils"
2
+ import { randomUUID } from "crypto"
3
+ import { it, expect } from "@jest/globals"
4
+ import { EchoCommand } from "./echo"
5
+ const client = newHttpClient()
6
+
7
+ it("returns the message", async () => {
8
+ const message = randomUUID()
9
+ const res = await new EchoCommand(message).exec(client)
10
+ expect(res).toBe(message)
11
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/echo
5
+ */
6
+ export class EchoCommand extends Command<string, string> {
7
+ constructor(message: string) {
8
+ super(["echo", message])
9
+ }
10
+ }
@@ -0,0 +1,37 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { ExistsCommand } from "./exists"
3
+ import { describe, it, expect, afterAll } from "@jest/globals"
4
+ import { SetCommand } from "./set"
5
+
6
+ const client = newHttpClient()
7
+
8
+ const { newKey, cleanup } = keygen()
9
+ afterAll(cleanup)
10
+
11
+ describe("when the key does not eist", () => {
12
+ it("it returns 1", async () => {
13
+ const key = newKey()
14
+
15
+ const res = await new ExistsCommand(key).exec(client)
16
+ expect(res).toEqual(0)
17
+ })
18
+ })
19
+ describe("when the key exists", () => {
20
+ it("it returns 1", async () => {
21
+ const key = newKey()
22
+ await new SetCommand(key, "value").exec(client)
23
+ const res = await new ExistsCommand(key).exec(client)
24
+ expect(res).toEqual(1)
25
+ })
26
+ })
27
+ describe("with multiple keys", () => {
28
+ it("it returns the number of found keys", async () => {
29
+ const key1 = newKey()
30
+ const key2 = newKey()
31
+ const key3 = newKey()
32
+ await new SetCommand(key1, "value").exec(client)
33
+ await new SetCommand(key2, "value").exec(client)
34
+ const res = await new ExistsCommand(key1, key2, key3).exec(client)
35
+ expect(res).toEqual(2)
36
+ })
37
+ })
@@ -0,0 +1,11 @@
1
+ import { NonEmptyArray } from "../types"
2
+ import { Command } from "../command"
3
+
4
+ /**
5
+ * @see https://redis.io/commands/exists
6
+ */
7
+ export class ExistsCommand extends Command<0 | 1, "0" | "1"> {
8
+ constructor(...keys: NonEmptyArray<string>) {
9
+ super(["exists", ...keys])
10
+ }
11
+ }
@@ -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 { SetCommand } from "./set"
5
+ import { ExpireCommand } from "./expire"
6
+ import { GetCommand } from "./get"
7
+ const client = newHttpClient()
8
+
9
+ const { newKey, cleanup } = keygen()
10
+ afterAll(cleanup)
11
+
12
+ it("expires a key correctly", async () => {
13
+ const key = newKey()
14
+ const value = randomUUID()
15
+ await new SetCommand(key, value).exec(client)
16
+ const res = await new ExpireCommand(key, 1).exec(client)
17
+ expect(res).toEqual(1)
18
+ await new Promise((res) => setTimeout(res, 2000))
19
+ const res2 = await new GetCommand(key).exec(client)
20
+
21
+ expect(res2).toBeNull()
22
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/expire
5
+ */
6
+ export class ExpireCommand extends Command<0 | 1, "0" | "1"> {
7
+ constructor(key: string, seconds: number) {
8
+ super(["expire", key, seconds])
9
+ }
10
+ }
@@ -0,0 +1,24 @@
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 { GetCommand } from "./get"
6
+ import { ExpireAtCommand } from "./expireat"
7
+ const client = newHttpClient()
8
+
9
+ const { newKey, cleanup } = keygen()
10
+ afterAll(cleanup)
11
+
12
+ describe("without options", () => {
13
+ it("expires the key", async () => {
14
+ const key = newKey()
15
+ const value = randomUUID()
16
+ await new SetCommand(key, value).exec(client)
17
+
18
+ const res = await new ExpireAtCommand(key, 1).exec(client)
19
+ expect(res).toEqual(1)
20
+ await new Promise((res) => setTimeout(res, 2000))
21
+ const res2 = await new GetCommand(key).exec(client)
22
+ expect(res2).toBeNull
23
+ })
24
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/expireat
5
+ */
6
+ export class ExpireAtCommand extends Command<0 | 1, "0" | "1"> {
7
+ constructor(key: string, unix: number) {
8
+ super(["expireat", key, unix])
9
+ }
10
+ }
@@ -0,0 +1,17 @@
1
+ import { newHttpClient } from "../test-utils"
2
+ import { describe, it, expect } from "@jest/globals"
3
+ import { FlushAllCommand } from "./flushall"
4
+ const client = newHttpClient()
5
+
6
+ describe("without options", () => {
7
+ it("flushes the db", async () => {
8
+ const res = await new FlushAllCommand().exec(client)
9
+ expect(res).toBe("OK")
10
+ })
11
+ })
12
+ describe("async", () => {
13
+ it("flushes the db", async () => {
14
+ const res = await new FlushAllCommand({ async: true }).exec(client)
15
+ expect(res).toBe("OK")
16
+ })
17
+ })
@@ -0,0 +1,13 @@
1
+ import { Command } from "../command"
2
+ /**
3
+ * @see https://redis.io/commands/flushall
4
+ */
5
+ export class FlushAllCommand extends Command<"OK", "OK"> {
6
+ constructor(opts?: { async?: boolean }) {
7
+ const command = ["flushall"]
8
+ if (opts?.async) {
9
+ command.push("async")
10
+ }
11
+ super(command)
12
+ }
13
+ }
@@ -0,0 +1,17 @@
1
+ import { newHttpClient } from "../test-utils"
2
+ import { describe, it, expect } from "@jest/globals"
3
+ import { FlushDBCommand } from "./flushdb"
4
+ const client = newHttpClient()
5
+
6
+ describe("without options", () => {
7
+ it("flushes the db", async () => {
8
+ const res = await new FlushDBCommand().exec(client)
9
+ expect(res).toBe("OK")
10
+ })
11
+ })
12
+ describe("async", () => {
13
+ it("flushes the db", async () => {
14
+ const res = await new FlushDBCommand({ async: true }).exec(client)
15
+ expect(res).toBe("OK")
16
+ })
17
+ })
@@ -0,0 +1,13 @@
1
+ import { Command } from "../command"
2
+ /**
3
+ * @see https://redis.io/commands/flushdb
4
+ */
5
+ export class FlushDBCommand extends Command<"OK", "OK"> {
6
+ constructor(opts?: { async?: boolean }) {
7
+ const command = ["flushdb"]
8
+ if (opts?.async) {
9
+ command.push("async")
10
+ }
11
+ super(command)
12
+ }
13
+ }
@@ -0,0 +1,34 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { randomUUID } from "crypto"
3
+ import { it, expect, afterAll } from "@jest/globals"
4
+ import { SetCommand } from "./set"
5
+ import { GetCommand } from "./get"
6
+ const client = newHttpClient()
7
+
8
+ const { newKey, cleanup } = keygen()
9
+ afterAll(cleanup)
10
+
11
+ it("gets an exiting value", async () => {
12
+ const key = newKey()
13
+ const value = randomUUID()
14
+ await new SetCommand(key, value).exec(client)
15
+ const res = await new GetCommand(key).exec(client)
16
+
17
+ expect(res).toEqual(value)
18
+ })
19
+
20
+ it("gets a non-existing value", async () => {
21
+ const key = newKey()
22
+ const res = await new GetCommand(key).exec(client)
23
+
24
+ expect(res).toBeNull()
25
+ })
26
+
27
+ it("gets an object", async () => {
28
+ const key = newKey()
29
+ const value = { v: randomUUID() }
30
+ await new SetCommand(key, value).exec(client)
31
+ const res = await new GetCommand(key).exec(client)
32
+
33
+ expect(res).toEqual(value)
34
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/get
5
+ */
6
+ export class GetCommand<TData = string> extends Command<TData | null, unknown | null> {
7
+ constructor(key: string) {
8
+ super(["get", key])
9
+ }
10
+ }
@@ -0,0 +1,16 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { it, expect, afterAll } from "@jest/globals"
3
+ import { SetBitCommand } from "./setbit"
4
+ import { GetBitCommand } from "./getbit"
5
+ const client = newHttpClient()
6
+
7
+ const { newKey, cleanup } = keygen()
8
+ afterAll(cleanup)
9
+
10
+ it("returns the bit at offset", async () => {
11
+ const key = newKey()
12
+
13
+ await new SetBitCommand(key, 0, 1).exec(client)
14
+ const res = await new GetBitCommand(key, 0).exec(client)
15
+ expect(res).toBe(1)
16
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/getbit
5
+ */
6
+ export class GetBitCommand extends Command<0 | 1, "0" | "1"> {
7
+ constructor(key: string, offset: number) {
8
+ super(["getbit", key, offset])
9
+ }
10
+ }
@@ -0,0 +1,25 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { it, expect, afterAll } from "@jest/globals"
3
+ import { GetRangeCommand } from "./getrange"
4
+ import { SetCommand } from "./set"
5
+ const client = newHttpClient()
6
+
7
+ const { newKey, cleanup } = keygen()
8
+ afterAll(cleanup)
9
+
10
+ it("gets an exiting value", async () => {
11
+ const key = newKey()
12
+ const value = "Hello World"
13
+ await new SetCommand(key, value).exec(client)
14
+ const res = await new GetRangeCommand(key, 2, 4).exec(client)
15
+
16
+ expect(res).toBeDefined()
17
+ expect(res!).toEqual(value.slice(2, 5))
18
+ })
19
+
20
+ it("gets a non-existing value", async () => {
21
+ const key = newKey()
22
+ const res = await new GetRangeCommand(key, 10, 24).exec(client)
23
+
24
+ expect(res).toEqual("")
25
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/getrange
5
+ */
6
+ export class GetRangeCommand extends Command<string, string> {
7
+ constructor(key: string, start: number, end: number) {
8
+ super(["getrange", key, start, end])
9
+ }
10
+ }
@@ -0,0 +1,33 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { randomUUID } from "crypto"
3
+ import { it, expect, afterAll } from "@jest/globals"
4
+ import { GetSetCommand } from "./getset"
5
+ import { SetCommand } from "./set"
6
+ import { GetCommand } from "./get"
7
+ const client = newHttpClient()
8
+
9
+ const { newKey, cleanup } = keygen()
10
+ afterAll(cleanup)
11
+
12
+ it("overwrites the original value", async () => {
13
+ const key = newKey()
14
+ const value = randomUUID()
15
+ const newValue = randomUUID()
16
+ await new SetCommand(key, value).exec(client)
17
+ const res = await new GetSetCommand(key, newValue).exec(client)
18
+
19
+ expect(res).toEqual(value)
20
+ const res2 = await new GetCommand(key).exec(client)
21
+
22
+ expect(res2).toEqual(newValue)
23
+ })
24
+ it("sets a new value if empty", async () => {
25
+ const key = newKey()
26
+ const newValue = randomUUID()
27
+ const res = await new GetSetCommand(key, newValue).exec(client)
28
+
29
+ expect(res).toBeNull()
30
+ const res2 = await new GetCommand(key).exec(client)
31
+
32
+ expect(res2).toEqual(newValue)
33
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/getset
5
+ */
6
+ export class GetSetCommand<TData = string> extends Command<TData | null, unknown | null> {
7
+ constructor(key: string, value: TData) {
8
+ super(["getset", key, value])
9
+ }
10
+ }
@@ -0,0 +1,30 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { randomUUID } from "crypto"
3
+ import { it, expect, afterAll } from "@jest/globals"
4
+ import { HDelCommand } from "./hdel"
5
+ import { HSetCommand } from "./hset"
6
+ import { HGetCommand } from "./hget"
7
+ const client = newHttpClient()
8
+
9
+ const { newKey, cleanup } = keygen()
10
+ afterAll(cleanup)
11
+
12
+ it("deletes a hash that does not exist", async () => {
13
+ const key = newKey()
14
+ const field = randomUUID()
15
+ const res = await new HDelCommand(key, field).exec(client)
16
+
17
+ expect(res).toEqual(0)
18
+ })
19
+
20
+ it("deletes a field that exists", async () => {
21
+ const key = newKey()
22
+ const field = randomUUID()
23
+ await new HSetCommand(key, field, randomUUID()).exec(client)
24
+ const res = await new HDelCommand(key, field).exec(client)
25
+
26
+ expect(res).toEqual(1)
27
+ const res2 = await new HGetCommand(key, field).exec(client)
28
+
29
+ expect(res2).toEqual(null)
30
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/hdel
5
+ */
6
+ export class HDelCommand extends Command<0 | 1, "0" | "1"> {
7
+ constructor(key: string, field: string) {
8
+ super(["hdel", key, field])
9
+ }
10
+ }
@@ -0,0 +1,31 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { randomUUID } from "crypto"
3
+ import { it, expect, afterAll } from "@jest/globals"
4
+ import { HSetCommand } from "./hset"
5
+ import { HExistsCommand } from "./hexists"
6
+
7
+ const client = newHttpClient()
8
+
9
+ const { newKey, cleanup } = keygen()
10
+ afterAll(cleanup)
11
+
12
+ it("returns 1 for an existing field", async () => {
13
+ const key = newKey()
14
+ const field = randomUUID()
15
+ await new HSetCommand(key, field, randomUUID()).exec(client)
16
+ const res = await new HExistsCommand(key, field).exec(client)
17
+ expect(res).toEqual(1)
18
+ })
19
+ it("returns 0 if field does not exist", async () => {
20
+ const key = newKey()
21
+ await new HSetCommand(key, randomUUID(), randomUUID()).exec(client)
22
+
23
+ const res = await new HExistsCommand(key, "not-existing-field").exec(client)
24
+ expect(res).toEqual(0)
25
+ })
26
+ it("returns 0 if hash does not exist", async () => {
27
+ const key = newKey()
28
+ const field = randomUUID()
29
+ const res = await new HExistsCommand(key, field).exec(client)
30
+ expect(res).toEqual(0)
31
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/hexists
5
+ */
6
+ export class HExistsCommand extends Command<number, number> {
7
+ constructor(key: string, field: string) {
8
+ super(["hexists", key, field])
9
+ }
10
+ }
@@ -0,0 +1,47 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { randomUUID } from "crypto"
3
+ import { it, expect, afterAll } from "@jest/globals"
4
+ import { HSetCommand } from "./hset"
5
+ import { HGetCommand } from "./hget"
6
+
7
+ const client = newHttpClient()
8
+
9
+ const { newKey, cleanup } = keygen()
10
+ afterAll(cleanup)
11
+
12
+ it("gets an exiting value", async () => {
13
+ const key = newKey()
14
+ const field = randomUUID()
15
+ const value = randomUUID()
16
+ await new HSetCommand(key, field, value).exec(client)
17
+ const res = await new HGetCommand(key, field).exec(client)
18
+
19
+ expect(res).toEqual(value)
20
+ })
21
+
22
+ it("gets a non-existing hash", async () => {
23
+ const key = newKey()
24
+ const field = randomUUID()
25
+ const res = await new HGetCommand(key, field).exec(client)
26
+
27
+ expect(res).toBeNull()
28
+ })
29
+
30
+ it("gets a non-existing field", async () => {
31
+ const key = newKey()
32
+ const field = randomUUID()
33
+ await new HSetCommand(key, randomUUID(), randomUUID()).exec(client)
34
+ const res = await new HGetCommand(key, field).exec(client)
35
+
36
+ expect(res).toBeNull()
37
+ })
38
+
39
+ it("gets an object", async () => {
40
+ const key = newKey()
41
+ const field = randomUUID()
42
+ const value = { v: randomUUID() }
43
+ await new HSetCommand(key, field, value).exec(client)
44
+ const res = await new HGetCommand(key, field).exec(client)
45
+
46
+ expect(res).toEqual(value)
47
+ })
@@ -0,0 +1,10 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ * @see https://redis.io/commands/hget
5
+ */
6
+ export class HGetCommand<TData> extends Command<TData | null, unknown | null> {
7
+ constructor(key: string, field: string) {
8
+ super(["hget", key, field])
9
+ }
10
+ }
@@ -0,0 +1,32 @@
1
+ import { keygen, newHttpClient } from "../test-utils"
2
+ import { randomUUID } from "crypto"
3
+ import { describe, it, expect, afterAll } from "@jest/globals"
4
+ import { HSetCommand } from "./hset"
5
+ import { HGetAllCommand } from "./hgetall"
6
+
7
+ const client = newHttpClient()
8
+
9
+ const { newKey, cleanup } = keygen()
10
+ afterAll(cleanup)
11
+ it("returns all fields", async () => {
12
+ const key = newKey()
13
+ const field2 = randomUUID()
14
+ const field1 = randomUUID()
15
+ const value1 = false
16
+ const value2 = randomUUID()
17
+ await new HSetCommand(key, field1, value1).exec(client)
18
+ await new HSetCommand(key, field2, value2).exec(client)
19
+ const res = await new HGetAllCommand(key).exec(client)
20
+
21
+ const obj = {
22
+ [field1]: value1,
23
+ [field2]: value2,
24
+ }
25
+ expect(res).toEqual(obj)
26
+ })
27
+ describe("when hash does not exist", () => {
28
+ it("it returns null", async () => {
29
+ const res = await new HGetAllCommand(randomUUID()).exec(client)
30
+ expect(res).toBeNull()
31
+ })
32
+ })
@@ -0,0 +1,35 @@
1
+ import { Command } from "../command"
2
+
3
+ /**
4
+ *
5
+ * @param result De
6
+ * @returns
7
+ */
8
+ function deserialize<TData extends Record<string, unknown>>(result: string[]): TData | null {
9
+ if (result.length === 0) {
10
+ return null
11
+ }
12
+ const obj: Record<string, unknown> = {}
13
+ while (result.length >= 2) {
14
+ const key = result.shift()!
15
+ const value = result.shift()!
16
+ try {
17
+ obj[key] = JSON.parse(value)
18
+ } catch {
19
+ obj[key] = value
20
+ }
21
+ }
22
+ return obj as TData
23
+ }
24
+
25
+ /**
26
+ * @see https://redis.io/commands/hgetall
27
+ */
28
+ export class HGetAllCommand<TData extends Record<string, unknown>> extends Command<
29
+ TData | null,
30
+ unknown | null
31
+ > {
32
+ constructor(key: string) {
33
+ super(["hgetall", key], { deserialize: (result) => deserialize<TData>(result as string[]) })
34
+ }
35
+ }