UNPKG

@fedify/fedify

Version:

An ActivityPub server framework

93 lines (92 loc) 2.65 kB
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 };