@crvouga/mockingbird-service-redis 0.1.0

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.
package/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # @crvouga/mockingbird-service-redis
2
+
3
+ > Familiar calls. Faithful echoes. Part of [Mockingbird](https://github.com/crvouga/mockingbird).
4
+
5
+ In-process Redis for tests. `createRedis()` is a pure TypeScript RESP store: call commands on
6
+ `redis.client()`, or speak RESP to the TCP server (`mockingbird-redis`, or `serve` from
7
+ `@crvouga/mockingbird-service-redis/server`). It is not an HTTP API mock and has no `createRuntime`.
8
+ `./server` also exports `serveTarget`, so `serve --config` can boot it: `GET /health` reports
9
+ `service: redis`, and RESP listens on an ephemeral `redis://127.0.0.1:<port>` printed at startup.
10
+ `mockingbird-redis` still binds `6379` unless `--port` is set.
11
+
12
+ Replies follow the Redis command reference for a single standalone node and were spot-checked
13
+ against Redis 8.4.0. The advertised version is Redis 7.2.4 so clients do not probe Redis 8 modules.
14
+ This package is a work in progress.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ npm install -D @crvouga/mockingbird-service-redis
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```ts
25
+ import { createRedis, manualClock } from "@crvouga/mockingbird-service-redis"
26
+
27
+ const clock = manualClock(1_700_000_000_000)
28
+ const redis = createRedis({ clock })
29
+ const client = redis.client()
30
+ const set = await client.call("SET", "lock", "token", "PX", 1000)
31
+ console.log(set)
32
+ redis.advance(1000)
33
+ ```
34
+
35
+ Two `createRedis()` instances never share keys. `SELECT` isolates logical databases 0–15 inside
36
+ one instance. `redis.advance(ms)` moves an injected clock. `redis.inspect()`, `redis.fault()`,
37
+ `redis.pauseConsumers()`, `redis.reset()`, and `redis.waiterCount()` are the test controls.
38
+
39
+ `ioredis` can connect to the TCP server unchanged. Cluster `MOVED` / `ASK` is not implemented:
40
+ `CLUSTER` and `READONLY` answer that cluster support is disabled.
41
+
42
+ ## API
43
+
44
+ - `createRedis(options?)` returns a `Redis` instance.
45
+ - `Redis` holds the store, the clock, and the test controls (`client`, `advance`, `fault`, `inspect`, `pauseConsumers`, `reset`, `waiterCount`, `close`).
46
+ - `RedisClient` is one connection: `call`, `raw`, `pipeline`, `quit`, `onPush`, and `protocol`.
47
+ - `RedisPipeline` queues `call`s and runs them in `exec`.
48
+ - `RedisConnectionError` is a dropped connection, a timeout fault, or a closed server.
49
+ - `RedisReplyError` is a Redis error reply raised by `call`.
50
+ - `manualClock(start)` moves only when `advance` is called. `wallClock` follows `Date.now()`.
51
+ - `encodeReply(reply, protocol)` writes a RESP2 or RESP3 frame.
52
+
53
+ ## Deliberately not modelled
54
+
55
+ - Cluster redirects (`MOVED`, `ASK`) and replica replication. `ROLE` stays `master`.
56
+ - Redis 8 modules, and the full Redis command set.
57
+ - Full Lua 5.1, `cmsgpack`, and BullMQ beyond the script subset (`cjson`, `redis.call` / `pcall`).
58
+ - `XADD` / `XTRIM` `MAXLEN ~` trims exactly.
59
+ - Set members are returned in byte order so results stay deterministic.
package/SUPPORT.md ADDED
@@ -0,0 +1,23 @@
1
+ # Redis (Mockingbird subset) — command support
2
+
3
+ Work in progress. Replies are checked against the Redis command reference and local Redis 8.4.0
4
+ spot checks. The server reports `redis_version` 7.2.4 and `redis_mode:standalone`.
5
+
6
+ | area | commands | notes |
7
+ | --- | --- | --- |
8
+ | connection | `AUTH`, `HELLO`, `PING`, `QUIT`, `RESET`, `SELECT`, `CLIENT`, `INFO`, `ECHO` | RESP2 and RESP3. `HELLO 3` switches before its map reply. |
9
+ | strings | `GET`, `SET`, `MGET`, `MSET`, `INCR`, `DECR`, `APPEND`, `GETSET`, `GETDEL`, `GETEX` | `NX` `XX` `EX` `PX` `EXAT` `PXAT` `KEEPTTL` `GET`. |
10
+ | expiration | `EXPIRE`, `PEXPIRE`, `EXPIREAT`, `PEXPIREAT`, `TTL`, `PTTL`, `PERSIST` | Injected clock. Negative `EXPIRE` deletes an existing key. |
11
+ | keys | `DEL`, `EXISTS`, `TYPE`, `SCAN`, `KEYS`, `RENAME`, `FLUSHDB`, `FLUSHALL` | `SCAN` cursor is a bulk string. |
12
+ | hashes | `HSET`, `HGET`, `HMGET`, `HGETALL`, `HDEL`, `HINCRBY` | |
13
+ | lists | `LPUSH`, `RPUSH`, `LPOP`, `RPOP`, `LRANGE`, `LMOVE`, `BLPOP`, `BRPOP` | Blocking waits release the command queue. |
14
+ | sets | `SADD`, `SREM`, `SMEMBERS`, `SISMEMBER`, `SPOP` | Members are ordered bytewise. |
15
+ | sorted sets | `ZADD`, `ZRANGE`, `ZPOPMIN`, `BZPOPMIN`, `ZINCRBY` | Integer scores encode without a trailing `.0`. |
16
+ | streams | `XADD`, `XREAD`, `XGROUP`, `XREADGROUP`, `XACK`, `XPENDING`, `XCLAIM`, `XAUTOCLAIM` | Consumer-group pending entries and claim. |
17
+ | transactions | `MULTI`, `EXEC`, `DISCARD`, `WATCH`, `UNWATCH` | A watched key change makes `EXEC` a null array. |
18
+ | pub/sub | `SUBSCRIBE`, `UNSUBSCRIBE`, `PSUBSCRIBE`, `PUBLISH`, `PUBSUB` | |
19
+ | scripts | `EVAL`, `EVALSHA`, `SCRIPT LOAD`, `SCRIPT EXISTS`, `SCRIPT FLUSH` | Lua subset plus `cjson`. No `cmsgpack`. |
20
+ | cluster | `CLUSTER`, `READONLY`, `ASKING` | Single node: cluster support disabled. |
21
+
22
+ Out of scope for this pass: Redis Cluster, Redis 8 modules, a complete Lua 5.1 runtime, and full
23
+ BullMQ compatibility.