cfw-bindings-wrangler-bridge
Version:
This bridge makes it possible to interact with **remote** Cloudflare Workers bindings(like KV, D1, etc...) **from anywhere** you want.
73 lines (56 loc) • 1.91 kB
JavaScript
// @ts-check
import { stringify, parse } from "devalue";
/** @param {string} key */
const decodeKey = (key) => decodeURIComponent(key);
/**
* @param {any} binding
* @returns {binding is KVNamespace}
*/
export const isKVBinding = (binding) =>
binding.constructor.name === "KvNamespace";
/**
* @param {KVNamespace} KV
* @param {Request} req
*/
export const handleKVDispatch = async (KV, req) => {
const { operation, parameters } = parse(
req.headers.get("X-BRIDGE-KV-Dispatch") ?? "{}",
);
if (operation === "KVNamespace.list") {
const [options] = parameters;
const result = await KV.list(options);
return Response.json(result);
}
if (operation === "KVNamespace.put") {
const [encodedKey, options] = parameters;
const key = decodeKey(encodedKey);
const value = req.body ?? "Only for TS, never happens";
// Need to await here, otherwise already sent error
await KV.put(key, value, options);
return new Response();
}
if (operation === "KVNamespace.getWithMetadata") {
const [encodedKey, typeOrOptions] = parameters;
const key = decodeKey(encodedKey);
const { value, metadata, cacheStatus } = await KV.getWithMetadata(key, {
...(typeof typeOrOptions !== "string" ? typeOrOptions : {}),
// Override it to respond over our bridge.
// `stream` is fastest and type conversion is done by bridge module.
type: "stream",
});
return new Response(value, {
headers: {
"X-BRIDGE-KV-ValueIsNull": `${value === null}`,
"X-BRIDGE-KV-Metadata": stringify(metadata),
"X-BRIDGE-KV-CacheStatus": stringify(cacheStatus),
},
});
}
if (operation === "KVNamespace.delete") {
const [encodedKey] = parameters;
const key = decodeKey(encodedKey);
await KV.delete(key);
return new Response();
}
throw new Error(`${operation}() is not supported.`);
};