Skip to content

Instantly share code, notes, and snippets.

@qwtel
Last active November 8, 2021 01:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save qwtel/8f1ab50722b928af8d4ccb71fde2c484 to your computer and use it in GitHub Desktop.
Save qwtel/8f1ab50722b928af8d4ccb71fde2c484 to your computer and use it in GitHub Desktop.
kv-storage implementation for Cloudflare Workers
import { Base64Encoder, Base64Decoder } from 'base64-encoding';
const PREFIX = 'data:application/octet-stream;base64,';
const b64e = new Base64Encoder();
const b64d = new Base64Decoder();
const encodeKey = (key: string | BufferSource) => typeof key !== 'string' ? PREFIX + b64e.encode(key) : key;
const decodeKey = (key: string) => key.startsWith(PREFIX) ? b64d.decode(key.substr(PREFIX.length)) : key;
async function* __paginationHelper(db: KVNamespace) {
let keys: { name: string; expiration?: number; metadata?: unknown }[];
let done: boolean;
let cursor: string;
do {
({ keys, list_complete: done, cursor } = await db.list({ ...cursor ? { cursor } : {} }));
for (const { name } of keys) yield name;
} while (!done);
}
export class StorageArea {
db: KVNamespace;
constructor(name: string) {
this.db = Reflect.get(self, name);
}
async get(key: string | BufferSource) {
return this.db.get(encodeKey(key));
}
async set(key: string | BufferSource, value: string): Promise<void> {
this.db.put(encodeKey(key), value);
}
async delete(key: string | BufferSource) {
return this.db.delete(encodeKey(key));
}
async clear() {
for await (const key of __paginationHelper(this.db)) {
await this.db.delete(key)
}
}
async *keys(): AsyncGenerator<string | BufferSource> {
for await (let key of __paginationHelper(this.db)) {
yield decodeKey(key);
}
}
async *values(): AsyncGenerator<string> {
for await (let key of __paginationHelper(this.db)) {
yield this.db.get(key);
}
}
async *entries(): AsyncGenerator<[string | BufferSource, string]> {
for await (let key of __paginationHelper(this.db)) {
yield [decodeKey(key), await this.db.get(key)];
}
}
}
@qwtel
Copy link
Author

qwtel commented Dec 30, 2020

Update:

A better implementation is now available as a standalone module here: https://github.com/worker-utils/cloudflare-kv-storage

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment