|
1 | | -# @alloc/redis-on-workers |
| 1 | +# thin-redis |
2 | 2 |
|
3 | | -Connect to your Redis server using `cloudflare:sockets`. |
| 3 | +Redis/Valkey client for Node.js and Cloudflare Workers. |
4 | 4 |
|
5 | | -This package is designed to work with Cloudflare Workers, but it can also be used in node.js thanks to the implementation of [`cloudflare:sockets` for node.js](https://github.com/Ethan-Arrowood/socket). |
| 5 | +- Modular design: choose which commands you need |
| 6 | +- Impeccable TypeScript support |
| 7 | +- Runtime type validation with `@sinclair/typebox` |
| 8 | +- Install `@arrowood.dev/socket` for Node.js support |
| 9 | +- Binary values with `sendRaw` |
| 10 | +- Secure connection with TLS and Authentication |
| 11 | +- RESP2 parser / serializer |
6 | 12 |
|
7 | | -> [!NOTE] |
8 | | -> This is a fork of [redis-on-workers](https://github.com/kane50613/redis-on-workers) with some improvements: |
9 | | -> |
10 | | -> - Modular commands and key types for tree-shakeable type safety. |
11 | | -> - Integrated with `@sinclair/typebox` for static type-checking and runtime validation. |
12 | | -> - Supports pub-sub with `subscribe` method, including pattern matching, keyspace notifications, and keyevent notifications. |
| 13 | +## Supported features |
13 | 14 |
|
14 | | -## Installation |
| 15 | +**Most commands are not implemented yet.** |
15 | 16 |
|
16 | | -```sh |
17 | | -pnpm add @alloc/redis-on-workers |
18 | | -``` |
| 17 | +Supported features include: |
19 | 18 |
|
20 | | -## Usage |
21 | | - |
22 | | -### Minimal |
23 | | - |
24 | | -This is the minimal example to connect to a Redis server. |
25 | | - |
26 | | -```ts |
27 | | -import { RedisClient, RedisKey, GET, SET } from "@alloc/redis-on-workers"; |
28 | | -import { Type } from "@sinclair/typebox"; |
29 | | - |
30 | | -const redis = new RedisClient({ |
31 | | - url: "redis://<username>:<password>@<host>:<port>", |
32 | | -}); |
33 | | -const key = new RedisKey("foo", Type.String()); |
34 | | - |
35 | | -await redis.send(SET(key, "bar")); |
36 | | - |
37 | | -const value = await redis.send(GET(key)); |
38 | | - |
39 | | -console.log(value); // bar |
40 | | - |
41 | | -// remember to close the connection after use, or use `redis.sendOnce`. |
42 | | -await redis.close(); |
43 | | -``` |
44 | | - |
45 | | -### Raw Uint8Array |
46 | | - |
47 | | -This is useful if you want to store binary data. For example, you can store protobuf messages in Redis. |
48 | | - |
49 | | -```ts |
50 | | -import { RedisClient } from "@alloc/redis-on-workers"; |
51 | | - |
52 | | -const redis = new RedisClient({ |
53 | | - url: "redis://<username>:<password>@<host>:<port>", |
54 | | -}); |
55 | | - |
56 | | -await redis.sendRaw("SET", "foo", "bar"); |
57 | | - |
58 | | -const value = await redis.sendRawOnce("GET", "foo"); |
59 | | - |
60 | | -const decoder = new TextDecoder(); |
61 | | - |
62 | | -console.log(decoder.decode(value)); // bar |
63 | | -``` |
64 | | - |
65 | | -### Node.js |
66 | | - |
67 | | -Please install the node.js polyfill for `cloudflare:sockets` to use this package in node.js. |
68 | | - |
69 | | -```sh |
70 | | -pnpm add @arrowood.dev/socket |
71 | | -``` |
72 | | - |
73 | | -## API |
74 | | - |
75 | | -### `new RedisClient(options: RedisClientOptions)` |
76 | | - |
77 | | -Create a new Redis client, does NOT connect to the server yet, the connection will be established when the first command is sent. |
78 | | - |
79 | | -Or you can start connection immediately by using `redis.startConnection()`. |
80 | | - |
81 | | -### `RedisClientOptions` |
82 | | - |
83 | | -- `url` (string): The URL of the Redis server. |
84 | | -- `tls` (boolean): Whether to use TLS. Default: `false`. |
85 | | -- `connectFn` (function): Polyfill for `cloudflare:sockets`'s `connect` function if you're using it in node.js. Default: `undefined`. |
86 | | -- `onReply` (function): Callback for Redis replies. Default: `undefined`. |
| 19 | +- [x] CRUD operations |
| 20 | +- [ ] [Pub/Sub](https://redis.io/docs/latest/develop/interact/pubsub/) (basic) |
| 21 | + - [x] [Key-space notifications](https://redis.io/docs/latest/develop/use/keyspace-notifications/) |
| 22 | + - [x] [Key-event notifications](https://redis.io/docs/latest/develop/use/keyspace-notifications/) |
| 23 | +- [ ] [Streams](https://redis.io/docs/latest/develop/data-types/streams/) (basic) |
| 24 | +- [ ] [JSON](https://redis.io/docs/latest/develop/data-types/json/) (basic) |
| 25 | +- [ ] [Hashes](https://redis.io/docs/latest/develop/data-types/hashes/) (basic) |
| 26 | +- [ ] [Sets](https://redis.io/docs/latest/develop/data-types/sets/) (basic) |
| 27 | +- [ ] [Full-text search](https://redis.io/docs/latest/develop/interact/search-and-query/query/full-text/) (basic) |
87 | 28 |
|
88 | 29 | ## Commands |
89 | 30 |
|
90 | | -It's relatively straight-forward to add more commands (see [here](https://github.com/alloc/redis-on-workers/blob/master/src/commands.ts) for examples). If one is missing that you need, please add it and submit a PR. |
91 | | - |
92 | | -- `GET(key)` |
93 | | - Get the value of a key. |
94 | | -- `GETEX(key, ...modifiers)` |
95 | | - Get the value of a key and optionally set its expiration. |
96 | | -- `SET(key, value, ...modifiers)` |
97 | | - Set the value of a key and optionally set its expiration. |
98 | | -- `DEL(key, ...keys)` |
99 | | - Delete a key or multiple keys. |
100 | | -- `INCR(key)` |
101 | | - Increment the value of a key by 1. |
102 | | -- `DECR(key)` |
103 | | - Decrement the value of a key by 1. |
104 | | -- `INCRBY(key, amount)` |
105 | | - Increment the value of a key by a specific amount. |
106 | | -- `DECRBY(key, amount)` |
107 | | - Decrement the value of a key by a specific amount. |
108 | | -- `KEYS(pattern)` |
109 | | - Get all keys that match the given pattern. |
110 | | -- `HGET(key, field)` |
111 | | - Get the value of a field in a hash. |
112 | | -- `HSET(key, field, value)` |
113 | | - Set the value of a field in a hash. |
114 | | -- `HSET(key, values)` |
115 | | - Set the values of multiple fields in a hash. |
116 | | -- `PUBLISH(channel, message)` |
117 | | - Publish a message to a channel. |
118 | | - |
119 | | -### Modifiers |
120 | | - |
121 | | -- `NX()` |
122 | | - Only set the key if it does not already exist. |
123 | | -- `XX()` |
124 | | - Only set the key if it already exists. |
125 | | -- `EX(seconds)` |
126 | | - Set the expiration time of a key in seconds. |
127 | | -- `PX(milliseconds)` |
128 | | - Set the expiration time of a key in milliseconds. |
129 | | -- `EXAT(timestamp)` |
130 | | - Set the expiration time of a key at a specific Unix time. |
131 | | -- `PXAT(timestamp)` |
132 | | - Set the expiration time of a key at a specific Unix time in milliseconds. |
133 | | -- `KEEPTTL()` |
134 | | - Retain the time to live associated with the key. |
135 | | -- `PERSIST()` |
136 | | - Remove the time to live associated with the key. |
137 | | - |
138 | | -## Development |
139 | | - |
140 | | -To run the tests, first install [Redis Stack](https://redis.io/docs/latest/operate/oss_and_stack/install/install-stack/). If you don't use Homebrew, you need to update `redis.conf` in this repository to use the correct path to the `redisearch.so` binary. |
141 | | - |
142 | | -```sh |
143 | | -brew install redis-stack |
144 | | -``` |
145 | | - |
146 | | -Then start the Redis server from the root directory: |
147 | | - |
148 | | -```sh |
149 | | -redis-stack-server redis.conf |
150 | | -``` |
151 | | - |
152 | | -Then run the tests. 🥳 |
153 | | - |
154 | | -```sh |
155 | | -pnpm test |
156 | | -``` |
| 31 | +Contributions welcome! Only the commands I've needed so far are implemented. |
| 32 | + |
| 33 | +- [DECR](https://redis.io/docs/latest/commands/DECR/) |
| 34 | +- [DECRBY](https://redis.io/docs/latest/commands/DECRBY/) |
| 35 | +- [DEL](https://redis.io/docs/latest/commands/DEL/) |
| 36 | +- [EXPIRE](https://redis.io/docs/latest/commands/EXPIRE/) |
| 37 | +- [FLUSHALL](https://redis.io/docs/latest/commands/FLUSHALL/) |
| 38 | +- [GET](https://redis.io/docs/latest/commands/GET/) |
| 39 | +- [GETEX](https://redis.io/docs/latest/commands/GETEX/) |
| 40 | +- [HGET](https://redis.io/docs/latest/commands/HGET/) |
| 41 | +- [HSET](https://redis.io/docs/latest/commands/HSET/) |
| 42 | +- [INCR](https://redis.io/docs/latest/commands/INCR/) |
| 43 | +- [INCRBY](https://redis.io/docs/latest/commands/INCRBY/) |
| 44 | +- [KEYS](https://redis.io/docs/latest/commands/KEYS/) |
| 45 | +- [PING](https://redis.io/docs/latest/commands/PING/) |
| 46 | +- [PUBLISH](https://redis.io/docs/latest/commands/PUBLISH/) |
| 47 | +- [SADD](https://redis.io/docs/latest/commands/SADD/) |
| 48 | +- [SCARD](https://redis.io/docs/latest/commands/SCARD/) |
| 49 | +- [SDIFF](https://redis.io/docs/latest/commands/SDIFF/) |
| 50 | +- [SET](https://redis.io/docs/latest/commands/SET/) |
| 51 | +- [SINTER](https://redis.io/docs/latest/commands/SINTER/) |
| 52 | +- [SISMEMBER](https://redis.io/docs/latest/commands/SISMEMBER/) |
| 53 | +- [SMEMBERS](https://redis.io/docs/latest/commands/SMEMBERS/) |
| 54 | +- [SPOP](https://redis.io/docs/latest/commands/SPOP/) |
| 55 | +- [SREM](https://redis.io/docs/latest/commands/SREM/) |
| 56 | +- [SUNION](https://redis.io/docs/latest/commands/SUNION/) |
| 57 | +- [XACK](https://redis.io/docs/latest/commands/XACK/) |
| 58 | +- [XADD](https://redis.io/docs/latest/commands/XADD/) |
| 59 | +- [XDEL](https://redis.io/docs/latest/commands/XDEL/) |
| 60 | +- [XREAD](https://redis.io/docs/latest/commands/XREAD/) |
| 61 | +- [XREADGROUP](https://redis.io/docs/latest/commands/XREADGROUP/) |
0 commit comments