UNPKG

lakutata

Version:

An IoC-based universal application framework.

653 lines (641 loc) 19 kB
import { createClient as t, createCluster as e } from "@redis/client"; export { createClient, createCluster } from "@redis/client"; import { K as s } from "./Package.65.mjs"; import r from "cluster-key-slot"; import "buffer"; var i = class { _eventListeners; _maxListeners; _logger; constructor(t) { this._eventListeners = new Map, this._maxListeners = 100, this._logger = t?.logger; } once(t, e) { let s = (...r) => { this.off(t, s), e(...r); }; return this.on(t, s), this; } listenerCount(t) { if (!t) return this.getAllListeners().length; let e = this._eventListeners.get(t); return e ? e.length : 0; } eventNames() { return [ ...this._eventListeners.keys() ]; } rawListeners(t) { return t ? this._eventListeners.get(t) ?? [] : this.getAllListeners(); } prependListener(t, e) { let s = this._eventListeners.get(t) ?? []; return s.unshift(e), this._eventListeners.set(t, s), this; } prependOnceListener(t, e) { let s = (...r) => { this.off(t, s), e(...r); }; return this.prependListener(t, s), this; } maxListeners() { return this._maxListeners; } addListener(t, e) { return this.on(t, e), this; } on(t, e) { this._eventListeners.has(t) || this._eventListeners.set(t, []); let s = this._eventListeners.get(t); return s && (s.length >= this._maxListeners && console.warn(`MaxListenersExceededWarning: Possible event memory leak detected. ${s.length + 1} ${t} listeners added. Use setMaxListeners() to increase limit.`), s.push(e)), this; } removeListener(t, e) { return this.off(t, e), this; } off(t, e) { let s = this._eventListeners.get(t) ?? [], r = s.indexOf(e); return r !== -1 && s.splice(r, 1), s.length === 0 && this._eventListeners.delete(t), this; } emit(t, ...e) { let s = !1, r = this._eventListeners.get(t); if (r && r.length > 0) for (let t of r) t(...e), s = !0; return s; } listeners(t) { return this._eventListeners.get(t) ?? []; } removeAllListeners(t) { return t ? this._eventListeners.delete(t) : this._eventListeners.clear(), this; } setMaxListeners(t) { this._maxListeners = t; for (let e of this._eventListeners.values()) e.length > t && e.splice(t); } getAllListeners() { let t = new Array; for (let e of this._eventListeners.values()) t = [ ...t, ...e ]; return t; } }; var n = class extends i { _hooks; _throwHookErrors=!1; constructor(t) { super({ logger: t?.logger }), this._hooks = new Map, t?.throwHookErrors !== void 0 && (this._throwHookErrors = t.throwHookErrors); } get hooks() { return this._hooks; } get throwHookErrors() { return this._throwHookErrors; } set throwHookErrors(t) { this._throwHookErrors = t; } get logger() { return this._logger; } set logger(t) { this._logger = t; } onHook(t, e) { let s = this._hooks.get(t); s ? s.push(e) : this._hooks.set(t, [ e ]); } addHook(t, e) { this.onHook(t, e); } onHooks(t) { for (let e of t) this.onHook(e.event, e.handler); } prependHook(t, e) { let s = this._hooks.get(t); s ? s.unshift(e) : this._hooks.set(t, [ e ]); } prependOnceHook(t, e) { let s = async (...r) => (this.removeHook(t, s), e(...r)); this.prependHook(t, s); } onceHook(t, e) { let s = async (...r) => (this.removeHook(t, s), e(...r)); this.onHook(t, s); } removeHook(t, e) { let s = this._hooks.get(t); if (s) { let t = s.indexOf(e); t !== -1 && s.splice(t, 1); } } removeHooks(t) { for (let e of t) this.removeHook(e.event, e.handler); } async hook(t, ...e) { let s = this._hooks.get(t); if (s) for (let r of s) try { await r(...e); } catch (e) { let s = `${t}: ${e.message}`; if (this.emit("error", new Error(s)), this._logger && this._logger.error(s), this._throwHookErrors) throw new Error(s); } } async callHook(t, ...e) { await this.hook(t, ...e); } getHooks(t) { return this._hooks.get(t); } clearHooks() { this._hooks.clear(); } }; var o = (t => { t["RedisClientNotConnectedThrown"] = "Redis client is not connected or has failed to connect. This is thrown because throwOnConnectError is set to true."; return t; })(o || {}); var a = t => { const e = Math.min(2 ** t * 100, 2e3); const s = (Math.random() - .5) * 100; return e + s; }; var c = class extends n { _client=t(); _namespace; _keyPrefixSeparator="::"; _clearBatchSize=1e3; _useUnlink=true; _noNamespaceAffectsAll=false; _throwOnConnectError=true; _throwErrors=false; _connectionTimeout; constructor(s, r) { super(); const i = { reconnectStrategy: a }; if (s) { if (typeof s === "string") { this._client = t({ url: s, socket: i }); } else if (s.connect !== void 0) { this._client = this.isClientCluster(s) ? s : s; } else if (s instanceof Object) { this._client = s.rootNodes === void 0 ? t(s) : e(s); } } this.setOptions(r); this.initClient(); } get client() { return this._client; } set client(t) { this._client = t; this.initClient(); } get opts() { let t = "redis://localhost:6379"; if (this._client.options) { const e = this._client.options?.url; if (e) { t = e; } } const e = { namespace: this._namespace, keyPrefixSeparator: this._keyPrefixSeparator, clearBatchSize: this._clearBatchSize, noNamespaceAffectsAll: this._noNamespaceAffectsAll, useUnlink: this._useUnlink, throwOnConnectError: this._throwOnConnectError, throwErrors: this._throwErrors, connectionTimeout: this._connectionTimeout, dialect: "redis", url: t }; return e; } set opts(t) { this.setOptions(t); } get namespace() { return this._namespace; } set namespace(t) { this._namespace = t; } get keyPrefixSeparator() { return this._keyPrefixSeparator; } set keyPrefixSeparator(t) { this._keyPrefixSeparator = t; } get clearBatchSize() { return this._clearBatchSize; } set clearBatchSize(t) { if (t > 0) { this._clearBatchSize = t; } else { this.emit("error", "clearBatchSize must be greater than 0"); } } get useUnlink() { return this._useUnlink; } set useUnlink(t) { this._useUnlink = t; } get noNamespaceAffectsAll() { return this._noNamespaceAffectsAll; } set noNamespaceAffectsAll(t) { this._noNamespaceAffectsAll = t; } get throwOnConnectError() { return this._throwOnConnectError; } set throwOnConnectError(t) { this._throwOnConnectError = t; } get throwErrors() { return this._throwErrors; } set throwErrors(t) { this._throwErrors = t; } get connectionTimeout() { return this._connectionTimeout; } set connectionTimeout(t) { this._connectionTimeout = t; } async getClient() { if (this._client.isOpen) { return this._client; } try { if (this._connectionTimeout === void 0) { await this._client.connect(); } else { await Promise.race([ this._client.connect(), this.createTimeoutPromise(this._connectionTimeout) ]); } } catch (t) { this.emit("error", t); if (this._throwOnConnectError) { throw new Error("Redis client is not connected or has failed to connect. This is thrown because throwOnConnectError is set to true."); } await this.disconnect(true); } this.initClient(); return this._client; } async set(t, e, s) { const r = await this.getClient(); try { t = this.createKeyPrefix(t, this._namespace); if (s) { await r.set(t, e, { PX: s }); } else { await r.set(t, e); } } catch (t) { this.emit("error", t); if (this._throwErrors) { throw t; } } } async setMany(t) { const e = await this.getClient(); try { const s = e.multi(); for (const {key: e, value: r, ttl: i} of t) { const t = this.createKeyPrefix(e, this._namespace); if (i) { s.set(t, r, { PX: i }); } else { s.set(t, r); } } await s.exec(); } catch (t) { this.emit("error", t); if (this._throwErrors) { throw t; } } } async has(t) { const e = await this.getClient(); try { t = this.createKeyPrefix(t, this._namespace); const s = await e.exists(t); return s === 1; } catch (t) { this.emit("error", t); if (this._throwErrors) { throw t; } return false; } } async hasMany(t) { const e = await this.getClient(); try { const s = e.multi(); for (const e of t) { const t = this.createKeyPrefix(e, this._namespace); s.exists(t); } const r = await s.exec(); return r.map((t => t === 1)); } catch (e) { this.emit("error", e); if (this._throwErrors) { throw e; } return Array.from({ length: t.length }).fill(false); } } async get(t) { const e = await this.getClient(); try { t = this.createKeyPrefix(t, this._namespace); const s = await e.get(t); if (s === null) { return void 0; } return s; } catch (t) { this.emit("error", t); if (this._throwErrors) { throw t; } return void 0; } } async getMany(t) { if (t.length === 0) { return []; } t = t.map((t => this.createKeyPrefix(t, this._namespace))); try { const e = await this.mget(t); return e; } catch (e) { this.emit("error", e); if (this._throwErrors) { throw e; } return Array.from({ length: t.length }).fill(void 0); } } async delete(t) { const e = await this.getClient(); try { t = this.createKeyPrefix(t, this._namespace); let s = 0; s = await (this._useUnlink ? e.unlink(t) : e.del(t)); return s > 0; } catch (t) { this.emit("error", t); if (this._throwErrors) { throw t; } return false; } } async deleteMany(t) { let e = false; const s = await this.getClient(); try { const r = s.multi(); for (const e of t) { const t = this.createKeyPrefix(e, this._namespace); if (this._useUnlink) { r.unlink(t); } else { r.del(t); } } const i = await r.exec(); for (const t of i) { if (typeof t === "number" && t > 0) { e = true; } } } catch (t) { this.emit("error", t); if (this._throwErrors) { throw t; } } return e; } async disconnect(t) { if (this._client.isOpen) { await (t ? this._client.disconnect() : this._client.quit()); } } createKeyPrefix(t, e) { if (e) { return `${e}${this._keyPrefixSeparator}${t}`; } return t; } getKeyWithoutPrefix(t, e) { if (e) { return t.replace(`${e}${this._keyPrefixSeparator}`, ""); } return t; } isCluster() { return this.isClientCluster(this._client); } async getMasterNodes() { if (this.isCluster()) { const t = await this.getClient(); return Promise.all(t.masters.map((async e => t.nodeClient(e)))); } return [ await this.getClient() ]; } async* iterator(t) { const e = await this.getMasterNodes(); for (const s of e) { const e = t ? `${t}${this._keyPrefixSeparator}*` : "*"; let r = "0"; do { const i = await s.scan(Number.parseInt(r, 10), { MATCH: e, TYPE: "string" }); r = i.cursor.toString(); let {keys: n} = i; if (!t && !this._noNamespaceAffectsAll) { n = n.filter((t => !t.includes(this._keyPrefixSeparator))); } if (n.length > 0) { const e = await this.mget(n); for (const s of n.keys()) { const r = this.getKeyWithoutPrefix(n[s], t); const i = e[s]; yield [ r, i ]; } } } while (r !== "0"); } } async clear() { try { const t = await this.getMasterNodes(); await Promise.all(t.map((async t => { if (!this._namespace && this._noNamespaceAffectsAll) { await t.flushDb(); return; } let e = "0"; const s = this._clearBatchSize; const r = this._namespace ? `${this._namespace}${this._keyPrefixSeparator}*` : "*"; const i = []; do { const n = await t.scan(Number.parseInt(e, 10), { MATCH: r, COUNT: s, TYPE: "string" }); e = n.cursor.toString(); let {keys: o} = n; if (o.length === 0) { continue; } if (!this._namespace) { o = o.filter((t => !t.includes(this._keyPrefixSeparator))); } i.push(this.clearWithClusterSupport(o)); } while (e !== "0"); await Promise.all(i); }))); } catch (t) { this.emit("error", t); } } async mget(t) { const e = this.getSlotMap(t); const s = new Map; await Promise.all(Array.from(e.entries(), (async ([t, e]) => { const r = await this.getSlotMaster(t); const i = await r.mGet(e); for (const [t, r] of i.entries()) { s.set(e[t], r ?? void 0); } }))); return t.map((t => s.get(t))); } async clearWithClusterSupport(t) { if (t.length > 0) { const e = this.getSlotMap(t); await Promise.all(Array.from(e.entries(), (async ([t, e]) => { const s = await this.getSlotMaster(t); return this._useUnlink ? s.unlink(e) : s.del(e); }))); } } async getSlotMaster(t) { const e = await this.getClient(); if (this.isCluster()) { const s = e; const r = s.slots[t].master; return s.nodeClient(r); } return e; } getSlotMap(t) { const e = new Map; if (this.isCluster()) { for (const s of t) { const t = r(s); const i = e.get(t) ?? []; i.push(s); e.set(t, i); } } else { e.set(0, t); } return e; } isClientCluster(t) { if (t.options === void 0 && t.scan === void 0) { return true; } return false; } setOptions(t) { if (!t) { return; } if (t.namespace) { this._namespace = t.namespace; } if (t.keyPrefixSeparator !== void 0) { this._keyPrefixSeparator = t.keyPrefixSeparator; } if (t.clearBatchSize !== void 0 && t.clearBatchSize > 0) { this._clearBatchSize = t.clearBatchSize; } if (t.useUnlink !== void 0) { this._useUnlink = t.useUnlink; } if (t.noNamespaceAffectsAll !== void 0) { this._noNamespaceAffectsAll = t.noNamespaceAffectsAll; } if (t.throwOnConnectError !== void 0) { this._throwOnConnectError = t.throwOnConnectError; } if (t.throwErrors !== void 0) { this._throwErrors = t.throwErrors; } if (t.connectionTimeout !== void 0) { this._connectionTimeout = t.connectionTimeout; } } initClient() { this._client.on("connect", (() => { this.emit("connect", this._client); })); this._client.on("disconnect", (() => { this.emit("disconnect", this._client); })); this._client.on("reconnecting", (t => { this.emit("reconnecting", t); })); } async createTimeoutPromise(t) { return new Promise(((e, s) => setTimeout((() => { s(new Error(`Redis timed out after ${t}ms`)); }), t))); } }; function h(t, e) { t ??= "redis://localhost:6379"; const r = new c(t, e); const i = new s(r, { namespace: e?.namespace, useKeyPrefix: false }); return i; } export { s as Keyv, o as RedisErrorMessages, h as createKeyv, c as default, a as defaultReconnectStrategy };