-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
68 lines (61 loc) · 2.31 KB
/
Copy pathindex.js
File metadata and controls
68 lines (61 loc) · 2.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/**
* valkey-http — a zero-dependency Valkey client that talks over HTTP.
*
* Runs anywhere `fetch` exists: Node, Deno, Bun, browsers, and edge runtimes
* (Cloudflare Workers, Vercel Edge) where raw TCP clients like iovalkey cannot.
* It sends each command to a `valkey-http-server` proxy, which runs it on Valkey.
*/
export class Valkey {
/**
* @param {{ url: string, token?: string }} options
* url - base URL of the valkey-http-server proxy (e.g. "https://proxy.example.com")
* token - bearer token the proxy expects
*/
constructor({ url, token } = {}) {
if (!url) throw new TypeError("valkey-http: `url` is required");
this.url = url.replace(/\/+$/, ""); // strip trailing slashes once
this.token = token;
}
get #headers() {
return {
"content-type": "application/json",
...(this.token ? { authorization: `Bearer ${this.token}` } : {}),
};
}
async #post(path, payload) {
const res = await fetch(`${this.url}/${path}`, {
method: "POST",
headers: this.#headers,
body: JSON.stringify(payload),
});
const data = await res.json().catch(() => null);
if (!res.ok) {
throw new Error(data?.error || `valkey-http: HTTP ${res.status}`);
}
return data;
}
/** Run a single command and return its result. */
async #call(...command) {
return (await this.#post("", command)).result;
}
/**
* Run a batch of commands in one round-trip.
* @param {Array<Array<any>>} commands e.g. [["SET","a","1"],["GET","a"]]
* @returns {Promise<Array<{ result: any, error: string|null }>>}
*/
pipeline(commands) {
return this.#post("pipeline", commands);
}
// Sugar for the common commands. Everything else goes through `call()`.
get(key) { return this.#call("GET", key); }
set(key, value, ...opts) { return this.#call("SET", key, value, ...opts); }
del(...keys) { return this.#call("DEL", ...keys); }
exists(...keys) { return this.#call("EXISTS", ...keys); }
incr(key) { return this.#call("INCR", key); }
decr(key) { return this.#call("DECR", key); }
expire(key, seconds) { return this.#call("EXPIRE", key, seconds); }
ttl(key) { return this.#call("TTL", key); }
/** Escape hatch: run any command, e.g. valkey.call("HSET", "h", "f", "v"). */
call(...command) { return this.#call(...command); }
}
export default Valkey;