UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

72 lines (71 loc) • 1.98 kB
import crypto from "node:crypto"; //#region src/shared/one-time-ticket-store.ts function createOneTimeTicketStore(opts) { const now = opts.now ?? (() => Date.now()); const entries = /* @__PURE__ */ new Map(); const remove = (token) => { const entry = entries.get(token); if (entry) { entries.delete(token); clearTimeout(entry.timer); entry.revokeSignal?.removeEventListener("abort", entry.onRevoke); } return entry; }; const expire = (token) => { const entry = remove(token); if (entry) opts.onExpire?.(entry.payload, token); }; return { mint(payload, options = {}) { const token = crypto.randomBytes(24).toString("hex"); const ttlMs = options.ttlMs ?? opts.ttlMs; const expiresAtMs = (options.nowMs ?? now()) + ttlMs; const timer = setTimeout(() => expire(token), ttlMs); timer.unref?.(); const { revokeSignal } = options; const onRevoke = () => { remove(token); }; entries.set(token, { payload, expiresAtMs, timer, revokeSignal, onRevoke }); revokeSignal?.addEventListener("abort", onRevoke, { once: true }); if (revokeSignal?.aborted) remove(token); return { token, expiresAtMs }; }, consume(token, nowMs, accept) { const currentTimeMs = nowMs ?? now(); const normalized = token.trim(); if (!/^[a-f0-9]{48}$/u.test(normalized)) return; if (accept) { const pending = entries.get(normalized); if (pending && pending.expiresAtMs > currentTimeMs && (!accept(pending.payload) || entries.get(normalized) !== pending)) return; } const entry = remove(normalized); if (entry && entry.expiresAtMs <= currentTimeMs) { opts.onExpire?.(entry.payload, normalized); return; } return entry?.payload; }, delete(token) { return remove(token) !== void 0; }, clear() { for (const token of entries.keys()) expire(token); }, get size() { return entries.size; } }; } //#endregion export { createOneTimeTicketStore as t };