UNPKG

lakutata

Version:

An IoC-based universal application framework.

717 lines (700 loc) 19.6 kB
"use strict"; const e = require("buffer"); var t = s => { if (s === void 0 || s === null) { return "null"; } if (typeof s === "string") { return JSON.stringify(s.startsWith(":") ? ":" + s : s); } if (e.Buffer.isBuffer(s)) { return JSON.stringify(":base64:" + s.toString("base64")); } if (s?.toJSON) { s = s.toJSON(); } if (typeof s === "object") { let e = ""; const i = Array.isArray(s); e = i ? "[" : "{"; let r = true; for (const o in s) { const a = typeof s[o] === "function" || !i && s[o] === void 0; if (!Object.hasOwn(s, o) || a) { continue; } if (!r) { e += ","; } r = false; if (i) { e += t(s[o]); } else if (s[o] !== void 0) { e += t(o) + ":" + t(s[o]); } } e += i ? "]" : "}"; return e; } return JSON.stringify(s); }; var s = t => JSON.parse(t, ((t, s) => { if (typeof s === "string") { if (s.startsWith(":base64:")) { return e.Buffer.from(s.slice(8), "base64"); } return s.startsWith(":") ? s.slice(1) : s; } return s; })); var i = class { _eventListeners; _maxListeners; constructor() { this._eventListeners = new Map; this._maxListeners = 100; } maxListeners() { return this._maxListeners; } addListener(e, t) { this.on(e, t); } on(e, t) { if (!this._eventListeners.has(e)) { this._eventListeners.set(e, []); } const s = this._eventListeners.get(e); if (s) { if (s.length >= this._maxListeners) { console.warn(`MaxListenersExceededWarning: Possible event memory leak detected. ${s.length + 1} ${e} listeners added. Use setMaxListeners() to increase limit.`); } s.push(t); } return this; } removeListener(e, t) { this.off(e, t); } off(e, t) { const s = this._eventListeners.get(e) ?? []; const i = s.indexOf(t); if (i !== -1) { s.splice(i, 1); } if (s.length === 0) { this._eventListeners.delete(e); } } once(e, t) { const s = (...i) => { t(...i); this.off(e, s); }; this.on(e, s); } emit(e, ...t) { const s = this._eventListeners.get(e); if (s && s.length > 0) { for (const e of s) { e(...t); } } } listeners(e) { return this._eventListeners.get(e) ?? []; } removeAllListeners(e) { if (e) { this._eventListeners.delete(e); } else { this._eventListeners.clear(); } } setMaxListeners(e) { this._maxListeners = e; } }; var r = i; var o = class extends r { _hookHandlers; constructor() { super(); this._hookHandlers = new Map; } addHandler(e, t) { const s = this._hookHandlers.get(e); if (s) { s.push(t); } else { this._hookHandlers.set(e, [ t ]); } } removeHandler(e, t) { const s = this._hookHandlers.get(e); if (s) { const e = s.indexOf(t); if (e !== -1) { s.splice(e, 1); } } } trigger(e, t) { const s = this._hookHandlers.get(e); if (s) { for (const i of s) { try { i(t); } catch (t) { this.emit("error", new Error(`Error in hook handler for event "${e}": ${t.message}`)); } } } } get handlers() { return new Map(this._hookHandlers); } }; var a = o; var n = class extends r { enabled=true; hits=0; misses=0; sets=0; deletes=0; errors=0; constructor(e) { super(); if (e !== void 0) { this.enabled = e; } this.reset(); } hit() { if (this.enabled) { this.hits++; } } miss() { if (this.enabled) { this.misses++; } } set() { if (this.enabled) { this.sets++; } } delete() { if (this.enabled) { this.deletes++; } } reset() { this.hits = 0; this.misses = 0; this.sets = 0; this.deletes = 0; this.errors = 0; } }; var h = n; var l = (e => { e["PRE_SET"] = "preSet"; e["POST_SET"] = "postSet"; e["PRE_GET"] = "preGet"; e["POST_GET"] = "postGet"; e["PRE_GET_MANY"] = "preGetMany"; e["POST_GET_MANY"] = "postGetMany"; e["PRE_DELETE"] = "preDelete"; e["POST_DELETE"] = "postDelete"; return e; })(l || {}); var c = [ "sqlite", "postgres", "mysql", "mongo", "redis", "valkey", "etcd" ]; var f = class extends r { opts; iterator; hooks=new a; stats=new h(false); _ttl; _namespace; _store=new Map; _serialize=t; _deserialize=s; _compression; _useKeyPrefix=true; constructor(e, i) { super(); i ??= {}; e ??= {}; this.opts = { namespace: "keyv", serialize: t, deserialize: s, emitErrors: true, store: new Map, ...i }; if (e && e.get) { this.opts.store = e; } else { this.opts = { ...this.opts, ...e }; } this._store = this.opts.store ?? new Map; this._compression = this.opts.compression; this._serialize = this.opts.serialize; this._deserialize = this.opts.deserialize; if (this.opts.namespace) { this._namespace = this.opts.namespace; } if (this._store) { if (!this._isValidStorageAdapter(this._store)) { throw new Error("Invalid storage adapter"); } if (typeof this._store.on === "function") { this._store.on("error", (e => this.emit("error", e))); } this._store.namespace = this._namespace; if (typeof this._store[Symbol.iterator] === "function" && this._store instanceof Map) { this.iterator = this.generateIterator(this._store); } else if ("iterator" in this._store && this._store.opts && this._checkIterableAdapter()) { this.iterator = this.generateIterator(this._store.iterator.bind(this._store)); } } if (this.opts.stats) { this.stats.enabled = this.opts.stats; } if (this.opts.ttl) { this._ttl = this.opts.ttl; } if (this.opts.useKeyPrefix !== void 0) { this._useKeyPrefix = this.opts.useKeyPrefix; } } get store() { return this._store; } set store(e) { if (this._isValidStorageAdapter(e)) { this._store = e; this.opts.store = e; if (typeof e.on === "function") { e.on("error", (e => this.emit("error", e))); } if (this._namespace) { this._store.namespace = this._namespace; } if (typeof e[Symbol.iterator] === "function" && e instanceof Map) { this.iterator = this.generateIterator(e); } else if ("iterator" in e && e.opts && this._checkIterableAdapter()) { this.iterator = this.generateIterator(e.iterator.bind(e)); } } else { throw new Error("Invalid storage adapter"); } } get compression() { return this._compression; } set compression(e) { this._compression = e; } get namespace() { return this._namespace; } set namespace(e) { this._namespace = e; this.opts.namespace = e; this._store.namespace = e; if (this.opts.store) { this.opts.store.namespace = e; } } get ttl() { return this._ttl; } set ttl(e) { this.opts.ttl = e; this._ttl = e; } get serialize() { return this._serialize; } set serialize(e) { this.opts.serialize = e; this._serialize = e; } get deserialize() { return this._deserialize; } set deserialize(e) { this.opts.deserialize = e; this._deserialize = e; } get useKeyPrefix() { return this._useKeyPrefix; } set useKeyPrefix(e) { this._useKeyPrefix = e; this.opts.useKeyPrefix = e; } generateIterator(e) { const t = async function*() { for await (const [t, s] of typeof e === "function" ? e(this._store.namespace) : e) { const e = await this.deserializeData(s); if (this._useKeyPrefix && this._store.namespace && !t.includes(this._store.namespace)) { continue; } if (typeof e.expires === "number" && Date.now() > e.expires) { this.delete(t); continue; } yield [ this._getKeyUnprefix(t), e.value ]; } }; return t.bind(this); } _checkIterableAdapter() { return c.includes(this._store.opts.dialect) || c.some((e => this._store.opts.url.includes(e))); } _getKeyPrefix(e) { if (!this._useKeyPrefix) { return e; } if (!this._namespace) { return e; } return `${this._namespace}:${e}`; } _getKeyPrefixArray(e) { if (!this._useKeyPrefix) { return e; } if (!this._namespace) { return e; } return e.map((e => `${this._namespace}:${e}`)); } _getKeyUnprefix(e) { if (!this._useKeyPrefix) { return e; } return e.split(":").splice(1).join(":"); } _isValidStorageAdapter(e) { return e instanceof Map || typeof e.get === "function" && typeof e.set === "function" && typeof e.delete === "function" && typeof e.clear === "function"; } async get(e, t) { const {store: s} = this.opts; const i = Array.isArray(e); const r = i ? this._getKeyPrefixArray(e) : this._getKeyPrefix(e); const o = e => typeof e.expires === "number" && Date.now() > e.expires; if (i) { if (t?.raw === true) { return this.getMany(e, { raw: true }); } return this.getMany(e, { raw: false }); } this.hooks.trigger("preGet", { key: r }); const a = await s.get(r); const n = typeof a === "string" || this.opts.compression ? await this.deserializeData(a) : a; if (n === void 0 || n === null) { this.stats.miss(); return void 0; } if (o(n)) { await this.delete(e); this.stats.miss(); return void 0; } this.hooks.trigger("postGet", { key: r, value: n }); this.stats.hit(); return t?.raw ? n : n.value; } async getMany(e, t) { const {store: s} = this.opts; const i = this._getKeyPrefixArray(e); const r = e => typeof e.expires === "number" && Date.now() > e.expires; this.hooks.trigger("preGetMany", { keys: i }); if (s.getMany === void 0) { const e = i.map((async e => { const i = await s.get(e); const o = typeof i === "string" || this.opts.compression ? await this.deserializeData(i) : i; if (o === void 0 || o === null) { return void 0; } if (r(o)) { await this.delete(e); return void 0; } return t?.raw ? o : o.value; })); const o = await Promise.allSettled(e); const a = o.map((e => e.value)); this.hooks.trigger("postGetMany", a); if (a.length > 0) { this.stats.hit(); } return a; } const o = await s.getMany(i); const a = []; for (const s in o) { let i = o[s]; if (typeof i === "string") { i = await this.deserializeData(i); } if (i === void 0 || i === null) { a.push(void 0); continue; } if (r(i)) { await this.delete(e[s]); a.push(void 0); continue; } const n = t?.raw ? i : i.value; a.push(n); } this.hooks.trigger("postGetMany", a); if (a.length > 0) { this.stats.hit(); } return a; } async set(e, t, s) { const i = { key: e, value: t, ttl: s }; this.hooks.trigger("preSet", i); const r = this._getKeyPrefix(i.key); i.ttl ??= this._ttl; if (i.ttl === 0) { i.ttl = void 0; } const {store: o} = this.opts; const a = typeof i.ttl === "number" ? Date.now() + i.ttl : void 0; if (typeof i.value === "symbol") { this.emit("error", "symbol cannot be serialized"); throw new Error("symbol cannot be serialized"); } const n = { value: i.value, expires: a }; const h = await this.serializeData(n); let l = true; try { const e = await o.set(r, h, i.ttl); if (typeof e === "boolean") { l = e; } } catch (e) { l = false; this.emit("error", e); } this.hooks.trigger("postSet", { key: r, value: h, ttl: s }); this.stats.set(); return l; } async setMany(e) { let t = []; try { if (this._store.setMany !== void 0) { const s = await Promise.all(e.map((async ({key: e, value: t, ttl: s}) => { s ??= this._ttl; if (s === 0) { s = void 0; } const i = typeof s === "number" ? Date.now() + s : void 0; if (typeof t === "symbol") { this.emit("error", "symbol cannot be serialized"); throw new Error("symbol cannot be serialized"); } const r = { value: t, expires: i }; const o = await this.serializeData(r); return { key: e, value: o, ttl: s }; }))); t = await this._store.setMany(s); } const s = []; for (const t of e) { s.push(this.set(t.key, t.value, t.ttl)); } const i = await Promise.allSettled(s); t = i.map((e => e.value)); } catch (s) { this.emit("error", s); t = e.map((() => false)); } return t; } async delete(e) { const {store: t} = this.opts; if (Array.isArray(e)) { return this.deleteMany(e); } const s = this._getKeyPrefix(e); this.hooks.trigger("preDelete", { key: s }); let i = true; try { const e = await t.delete(s); if (typeof e === "boolean") { i = e; } } catch (e) { i = false; this.emit("error", e); } this.hooks.trigger("postDelete", { key: s, value: i }); this.stats.delete(); return i; } async deleteMany(e) { try { const {store: t} = this.opts; const s = this._getKeyPrefixArray(e); this.hooks.trigger("preDelete", { key: s }); if (t.deleteMany !== void 0) { return await t.deleteMany(s); } const i = s.map((async e => t.delete(e))); const r = await Promise.allSettled(i); const o = r.every((e => e.value === true)); this.hooks.trigger("postDelete", { key: s, value: o }); return o; } catch (e) { this.emit("error", e); return false; } } async clear() { this.emit("clear"); const {store: e} = this.opts; try { await e.clear(); } catch (e) { this.emit("error", e); } } async has(e) { if (Array.isArray(e)) { return this.hasMany(e); } const t = this._getKeyPrefix(e); const {store: s} = this.opts; if (s.has !== void 0 && !(s instanceof Map)) { return s.has(t); } let i; try { i = await s.get(t); } catch (e) { this.emit("error", e); } if (i) { const e = await this.deserializeData(i); if (e) { if (e.expires === void 0 || e.expires === null) { return true; } return e.expires > Date.now(); } } return false; } async hasMany(e) { const t = this._getKeyPrefixArray(e); const {store: s} = this.opts; if (s.hasMany !== void 0) { return s.hasMany(t); } const i = []; for (const e of t) { i.push(await this.has(e)); } return i; } async disconnect() { const {store: e} = this.opts; this.emit("disconnect"); if (typeof e.disconnect === "function") { return e.disconnect(); } } emit(e, ...t) { if (e === "error" && !this.opts.emitErrors) { return; } super.emit(e, ...t); } async serializeData(e) { if (!this._serialize) { return e; } if (this._compression?.compress) { return this._serialize({ value: await this._compression.compress(e.value), expires: e.expires }); } return this._serialize(e); } async deserializeData(e) { if (!this._deserialize) { return e; } if (this._compression?.decompress && typeof e === "string") { const t = await this._deserialize(e); return { value: await this._compression.decompress(t?.value), expires: t?.expires }; } if (typeof e === "string") { return this._deserialize(e); } return void 0; } }; var p = f; exports.Keyv = f; exports.defaultDeserialize = s; exports.index_default = p;