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