first commit

This commit is contained in:
2026-07-12 15:55:18 +05:30
commit ee98026cc5
404 changed files with 44522 additions and 0 deletions
+37
View File
@@ -0,0 +1,37 @@
import { test, expect } from "bun:test";
import { createPubSub } from "../src/index.ts";
test("publish reaches exact + wildcard subscribers", async () => {
const bus = createPubSub();
const got: string[] = [];
bus.subscribe("order:created", (m: { id: number }) => {
got.push(`exact:${m.id}`);
});
bus.subscribe("order:*", (_m, topic) => {
got.push(`prefix:${topic}`);
});
bus.subscribe("*", (_m, topic) => {
got.push(`all:${topic}`);
});
await bus.publish("order:created", { id: 7 });
await bus.publish("user:login", { id: 1 });
expect(got).toContain("exact:7");
expect(got).toContain("prefix:order:created");
expect(got).toContain("all:order:created");
expect(got).toContain("all:user:login");
expect(got).not.toContain("prefix:user:login"); // order:* doesn't match user:*
});
test("unsubscribe stops delivery", async () => {
const bus = createPubSub();
let n = 0;
const off = bus.subscribe("t", () => {
n++;
});
await bus.publish("t", 1);
off();
await bus.publish("t", 2);
expect(n).toBe(1);
});
+33
View File
@@ -0,0 +1,33 @@
import { afterEach, expect, test } from "bun:test";
import { redisDriver } from "../src/redis.ts";
const bun = globalThis.Bun as typeof Bun & { connect: (options: unknown) => Promise<unknown> };
const originalConnect = bun.connect;
afterEach(() => {
bun.connect = originalConnect;
});
test("rediss URLs enable TLS and decode credentials", () => {
const options: Array<Record<string, unknown>> = [];
bun.connect = ((value: Record<string, unknown>) => {
options.push(value);
return new Promise(() => {});
}) as typeof bun.connect;
const driver = redisDriver("rediss://user:p%40ss@redis.example.com:6380/2");
expect(options).toHaveLength(2);
expect(options[0]).toMatchObject({ hostname: "redis.example.com", port: 6380, tls: true });
driver.close();
});
test("rejects invalid Redis URLs before connecting", () => {
expect(() => redisDriver("http://localhost:6379")).toThrow("redis:// or rediss://");
expect(() => redisDriver("redis://localhost/not-a-db")).toThrow("database");
});
test("bounds writes queued while Redis is unavailable", () => {
bun.connect = (() => new Promise(() => {})) as typeof bun.connect;
const driver = redisDriver("redis://localhost:6379");
for (let index = 0; index < 1000; index++) driver.publish("topic", index);
expect(() => driver.publish("topic", "overflow")).toThrow("queue is full");
driver.close();
});
+51
View File
@@ -0,0 +1,51 @@
import { test, expect } from "bun:test";
import { encodeCommand, parseReply, concat } from "../src/resp.ts";
const enc = new TextEncoder();
const dec = new TextDecoder();
test("encodeCommand produces a RESP array of bulk strings", () => {
const bytes = encodeCommand(["PUBLISH", "order:created", '{"id":7}']);
expect(dec.decode(bytes)).toBe(
'*3\r\n$7\r\nPUBLISH\r\n$13\r\norder:created\r\n$8\r\n{"id":7}\r\n',
);
});
test("parseReply reads a Redis message push", () => {
const wire = enc.encode("*3\r\n$7\r\nmessage\r\n$5\r\ntopic\r\n$5\r\nhello\r\n");
const r = parseReply(wire);
expect(r).not.toBeNull();
expect(r!.value).toEqual(["message", "topic", "hello"]);
expect(r!.next).toBe(wire.length);
});
test("parseReply reads a pmessage push (pattern, channel, payload)", () => {
const wire = enc.encode(
"*4\r\n$8\r\npmessage\r\n$6\r\norder:*\r\n$13\r\norder:created\r\n$2\r\n{}\r\n".replace(
"$6\r\norder:*",
"$7\r\norder:*",
),
);
const r = parseReply(wire)!;
expect(r.value).toEqual(["pmessage", "order:*", "order:created", "{}"]);
});
test("parseReply returns null for an incomplete buffer, then completes", () => {
const full = enc.encode("*1\r\n$5\r\nhello\r\n");
// Half the bytes → incomplete.
expect(parseReply(full.subarray(0, 8))).toBeNull();
// Full → parses.
expect(parseReply(full)!.value).toEqual(["hello"]);
});
test("parseReply handles integers and simple strings (subscribe confirmations)", () => {
const sub = enc.encode("*3\r\n$9\r\nsubscribe\r\n$5\r\ntopic\r\n:1\r\n");
expect(parseReply(sub)!.value).toEqual(["subscribe", "topic", 1]);
const ok = enc.encode("+OK\r\n");
expect(parseReply(ok)!.value).toBe("OK");
});
test("concat joins byte chunks in order", () => {
const joined = concat([enc.encode("ab"), enc.encode("cd")]);
expect(dec.decode(joined)).toBe("abcd");
});