@fedify/fedify
Version:
An ActivityPub server framework
93 lines (92 loc) • 2.65 kB
JavaScript
import { Temporal } from "@js-temporal/polyfill";
import "urlpattern-polyfill";
globalThis.addEventListener = () => {};
import { isEqual } from "es-toolkit";
//#region src/federation/kv.ts
/**
* A key–value store that stores values in memory.
* Do not use this in production as it does not persist values.
*
* @since 0.5.0
*/
var MemoryKvStore = class {
#values = {};
#encodeKey(key) {
return JSON.stringify(key);
}
/**
* {@inheritDoc KvStore.get}
*/
get(key) {
const encodedKey = this.#encodeKey(key);
const entry = this.#values[encodedKey];
if (entry == null) return Promise.resolve(void 0);
const [value, expiration] = entry;
if (expiration != null && Temporal.Now.instant().until(expiration).sign < 0) {
delete this.#values[encodedKey];
return Promise.resolve(void 0);
}
return Promise.resolve(value);
}
/**
* {@inheritDoc KvStore.set}
*/
set(key, value, options) {
const encodedKey = this.#encodeKey(key);
const expiration = options?.ttl == null ? null : Temporal.Now.instant().add(options.ttl.round({ largestUnit: "hour" }));
this.#values[encodedKey] = [value, expiration];
return Promise.resolve();
}
/**
* {@inheritDoc KvStore.delete}
*/
delete(key) {
const encodedKey = this.#encodeKey(key);
delete this.#values[encodedKey];
return Promise.resolve();
}
/**
* {@inheritDoc KvStore.cas}
*/
cas(key, expectedValue, newValue, options) {
const encodedKey = this.#encodeKey(key);
const entry = this.#values[encodedKey];
let currentValue;
if (entry == null) currentValue = void 0;
else {
const [value, expiration] = entry;
if (expiration != null && Temporal.Now.instant().until(expiration).sign < 0) {
delete this.#values[encodedKey];
currentValue = void 0;
} else currentValue = value;
}
if (!isEqual(currentValue, expectedValue)) return Promise.resolve(false);
const expiration = options?.ttl == null ? null : Temporal.Now.instant().add(options.ttl.round({ largestUnit: "hour" }));
this.#values[encodedKey] = [newValue, expiration];
return Promise.resolve(true);
}
/**
* {@inheritDoc KvStore.list}
*/
async *list(prefix) {
const now = Temporal.Now.instant();
for (const [encodedKey, entry] of Object.entries(this.#values)) {
const key = JSON.parse(encodedKey);
if (prefix != null) {
if (key.length < prefix.length) continue;
if (!prefix.every((p, i) => key[i] === p)) continue;
}
const [value, expiration] = entry;
if (expiration != null && now.until(expiration).sign < 0) {
delete this.#values[encodedKey];
continue;
}
yield {
key,
value
};
}
}
};
//#endregion
export { MemoryKvStore as t };