UNPKG

lakutata

Version:

An IoC-based universal application framework.

847 lines (833 loc) 23.6 kB
/* Build Date: Mon Jan 05 2026 23:52:23 GMT+0800 (China Standard Time) */ "use strict"; const t = require("buffer"); var e = (s, i = true) => { if (s === void 0 || s === null) { return "null"; } if (typeof s === "string") { return JSON.stringify(i && s.startsWith(":") ? `:${s}` : s); } if (t.Buffer.isBuffer(s)) { return JSON.stringify(`:base64:${s.toString("base64")}`); } if (s?.toJSON) { s = s.toJSON(); } if (typeof s === "object") { let t = ""; const r = Array.isArray(s); t = r ? "[" : "{"; let o = true; for (const a in s) { const n = typeof s[a] === "function" || !r && s[a] === void 0; if (!Object.hasOwn(s, a) || n) { continue; } if (!o) { t += ","; } o = false; if (r) { t += e(s[a], i); } else if (s[a] !== void 0) { t += `${e(a, false)}:${e(s[a], i)}`; } } t += r ? "]" : "}"; return t; } return JSON.stringify(s); }; var s = t => e(t, true); exports.defaultDeserialize = e => JSON.parse(e, (e, s) => { if (typeof s === "string") { if (s.startsWith(":base64:")) { return t.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(t, e) { this.on(t, e); } on(t, e) { if (!this._eventListeners.has(t)) { this._eventListeners.set(t, []); } const s = this._eventListeners.get(t); if (s) { if (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); } return this; } removeListener(t, e) { this.off(t, e); } off(t, e) { const s = this._eventListeners.get(t) ?? []; const i = s.indexOf(e); if (i !== -1) { s.splice(i, 1); } if (s.length === 0) { this._eventListeners.delete(t); } } once(t, e) { const s = (...i) => { e(...i); this.off(t, s); }; this.on(t, s); } emit(t, ...e) { const s = this._eventListeners.get(t); if (s && s.length > 0) { for (const t of s) { t(...e); } } } listeners(t) { return this._eventListeners.get(t) ?? []; } removeAllListeners(t) { if (t) { this._eventListeners.delete(t); } else { this._eventListeners.clear(); } } setMaxListeners(t) { this._maxListeners = t; } }; var r = i; var o = class extends r { _hookHandlers; constructor() { super(); this._hookHandlers = new Map; } addHandler(t, e) { const s = this._hookHandlers.get(t); if (s) { s.push(e); } else { this._hookHandlers.set(t, [ e ]); } } removeHandler(t, e) { const s = this._hookHandlers.get(t); if (s) { const t = s.indexOf(e); if (t !== -1) { s.splice(t, 1); } } } trigger(t, e) { const s = this._hookHandlers.get(t); if (s) { for (const i of s) { try { i(e); } catch (e) { this.emit("error", new Error(`Error in hook handler for event "${t}": ${e.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(t) { super(); if (t !== void 0) { this.enabled = t; } 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++; } } hitsOrMisses(t) { for (const e of t) { if (e === void 0) { this.miss(); } else { this.hit(); } } } reset() { this.hits = 0; this.misses = 0; this.sets = 0; this.deletes = 0; this.errors = 0; } }; var h = n; var l = [ "sqlite", "postgres", "mysql", "mongo", "redis", "valkey", "etcd" ]; exports.Keyv = class Keyv extends r { opts; iterator; hooks=new a; stats=new h(false); _ttl; _namespace; _store=new Map; _serialize=s; _deserialize=exports.defaultDeserialize; _compression; _useKeyPrefix=true; _throwOnErrors=false; constructor(t, e) { super(); e ??= {}; t ??= {}; this.opts = { namespace: "keyv", serialize: s, deserialize: exports.defaultDeserialize, emitErrors: true, store: new Map, ...e }; if (t && t.get) { this.opts.store = t; } else { this.opts = { ...this.opts, ...t }; } 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", t => this.emit("error", t)); } 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; } if (this.opts.throwOnErrors !== void 0) { this._throwOnErrors = this.opts.throwOnErrors; } } get store() { return this._store; } set store(t) { if (this._isValidStorageAdapter(t)) { this._store = t; this.opts.store = t; if (typeof t.on === "function") { t.on("error", t => this.emit("error", t)); } if (this._namespace) { this._store.namespace = this._namespace; } if (typeof t[Symbol.iterator] === "function" && t instanceof Map) { this.iterator = this.generateIterator(t); } else if ("iterator" in t && t.opts && this._checkIterableAdapter()) { this.iterator = this.generateIterator(t.iterator?.bind(t)); } } else { throw new Error("Invalid storage adapter"); } } get compression() { return this._compression; } set compression(t) { this._compression = t; } get namespace() { return this._namespace; } set namespace(t) { this._namespace = t; this.opts.namespace = t; this._store.namespace = t; if (this.opts.store) { this.opts.store.namespace = t; } } get ttl() { return this._ttl; } set ttl(t) { this.opts.ttl = t; this._ttl = t; } get serialize() { return this._serialize; } set serialize(t) { this.opts.serialize = t; this._serialize = t; } get deserialize() { return this._deserialize; } set deserialize(t) { this.opts.deserialize = t; this._deserialize = t; } get useKeyPrefix() { return this._useKeyPrefix; } set useKeyPrefix(t) { this._useKeyPrefix = t; this.opts.useKeyPrefix = t; } get throwOnErrors() { return this._throwOnErrors; } set throwOnErrors(t) { this._throwOnErrors = t; this.opts.throwOnErrors = t; } generateIterator(t) { const e = async function*() { for await (const [e, s] of typeof t === "function" ? t(this._store.namespace) : t) { const t = await this.deserializeData(s); if (this._useKeyPrefix && this._store.namespace && !e.includes(this._store.namespace)) { continue; } if (typeof t.expires === "number" && Date.now() > t.expires) { this.delete(e); continue; } yield [ this._getKeyUnprefix(e), t.value ]; } }; return e.bind(this); } _checkIterableAdapter() { return l.includes(this._store.opts.dialect) || l.some(t => this._store.opts.url.includes(t)); } _getKeyPrefix(t) { if (!this._useKeyPrefix) { return t; } if (!this._namespace) { return t; } return `${this._namespace}:${t}`; } _getKeyPrefixArray(t) { if (!this._useKeyPrefix) { return t; } if (!this._namespace) { return t; } return t.map(t => `${this._namespace}:${t}`); } _getKeyUnprefix(t) { if (!this._useKeyPrefix) { return t; } return t.split(":").splice(1).join(":"); } _isValidStorageAdapter(t) { return t instanceof Map || typeof t.get === "function" && typeof t.set === "function" && typeof t.delete === "function" && typeof t.clear === "function"; } async get(t, e) { const {store: s} = this.opts; const i = Array.isArray(t); const r = i ? this._getKeyPrefixArray(t) : this._getKeyPrefix(t); const o = t => typeof t.expires === "number" && Date.now() > t.expires; if (i) { if (e?.raw === true) { return this.getMany(t, { raw: true }); } return this.getMany(t, { raw: false }); } this.hooks.trigger("preGet", { key: r }); let a; try { a = await s.get(r); } catch (t) { if (this.throwOnErrors) { throw t; } } const n = typeof a === "string" || this.opts.compression ? await this.deserializeData(a) : a; if (n === void 0 || n === null) { this.hooks.trigger("postGet", { key: r, value: void 0 }); this.stats.miss(); return void 0; } if (o(n)) { await this.delete(t); this.hooks.trigger("postGet", { key: r, value: void 0 }); this.stats.miss(); return void 0; } this.hooks.trigger("postGet", { key: r, value: n }); this.stats.hit(); return e?.raw ? n : n.value; } async getMany(t, e) { const {store: s} = this.opts; const i = this._getKeyPrefixArray(t); const r = t => typeof t.expires === "number" && Date.now() > t.expires; this.hooks.trigger("preGetMany", { keys: i }); if (s.getMany === void 0) { const t = i.map(async t => { const i = await s.get(t); 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(t); return void 0; } return e?.raw ? o : o.value; }); const o = await Promise.allSettled(t); const a = o.map(t => t.value); this.hooks.trigger("postGetMany", a); if (a.length > 0) { this.stats.hit(); } return a; } const o = await s.getMany(i); const a = []; const n = []; 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)) { n.push(t[s]); a.push(void 0); continue; } const h = e?.raw ? i : i.value; a.push(h); } if (n.length > 0) { await this.deleteMany(n); } this.hooks.trigger("postGetMany", a); if (a.length > 0) { this.stats.hit(); } return a; } async getRaw(t) { const {store: e} = this.opts; const s = this._getKeyPrefix(t); this.hooks.trigger("preGetRaw", { key: s }); const i = await e.get(s); if (i === void 0 || i === null) { this.hooks.trigger("postGetRaw", { key: s, value: void 0 }); this.stats.miss(); return void 0; } const r = typeof i === "string" || this.opts.compression ? await this.deserializeData(i) : i; if (r !== void 0 && r.expires !== void 0 && r.expires !== null && r.expires < Date.now()) { this.hooks.trigger("postGetRaw", { key: s, value: void 0 }); this.stats.miss(); await this.delete(t); return void 0; } this.stats.hit(); this.hooks.trigger("postGetRaw", { key: s, value: r }); return r; } async getManyRaw(t) { const {store: e} = this.opts; const s = this._getKeyPrefixArray(t); if (t.length === 0) { const e = Array.from({ length: t.length }).fill(void 0); this.stats.misses += t.length; this.hooks.trigger("postGetManyRaw", { keys: s, values: e }); return e; } let i = []; if (e.getMany === void 0) { const t = s.map(async t => { const s = await e.get(t); if (s !== void 0 && s !== null) { return this.deserializeData(s); } return void 0; }); const r = await Promise.allSettled(t); i = r.map(t => t.value); } else { const t = await e.getMany(s); for (const e of t) { if (e !== void 0 && e !== null) { i.push(await this.deserializeData(e)); } else { i.push(void 0); } } } const r = []; const o = t => typeof t.expires === "number" && Date.now() > t.expires; for (const [t, e] of i.entries()) { if (e !== void 0 && o(e)) { r.push(s[t]); i[t] = void 0; } } if (r.length > 0) { await this.deleteMany(r); } this.stats.hitsOrMisses(i); this.hooks.trigger("postGetManyRaw", { keys: s, values: i }); return i; } async set(t, e, s) { const i = { key: t, value: e, 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 t = await o.set(r, h, i.ttl); if (typeof t === "boolean") { l = t; } } catch (t) { l = false; this.emit("error", t); if (this._throwOnErrors) { throw t; } } this.hooks.trigger("postSet", { key: r, value: h, ttl: s }); this.stats.set(); return l; } async setMany(t) { let e = []; try { if (this._store.setMany === void 0) { const s = []; for (const e of t) { s.push(this.set(e.key, e.value, e.ttl)); } const i = await Promise.all(s); e = i; } else { const s = await Promise.all(t.map(async ({key: t, value: e, ttl: s}) => { s ??= this._ttl; if (s === 0) { s = void 0; } const i = typeof s === "number" ? Date.now() + s : void 0; if (typeof e === "symbol") { this.emit("error", "symbol cannot be serialized"); throw new Error("symbol cannot be serialized"); } const r = { value: e, expires: i }; const o = await this.serializeData(r); const a = this._getKeyPrefix(t); return { key: a, value: o, ttl: s }; })); e = await this._store.setMany(s); } } catch (s) { this.emit("error", s); if (this._throwOnErrors) { throw s; } e = t.map(() => false); } return e; } async delete(t) { const {store: e} = this.opts; if (Array.isArray(t)) { return this.deleteMany(t); } const s = this._getKeyPrefix(t); this.hooks.trigger("preDelete", { key: s }); let i = true; try { const t = await e.delete(s); if (typeof t === "boolean") { i = t; } } catch (t) { i = false; this.emit("error", t); if (this._throwOnErrors) { throw t; } } this.hooks.trigger("postDelete", { key: s, value: i }); this.stats.delete(); return i; } async deleteMany(t) { try { const {store: e} = this.opts; const s = this._getKeyPrefixArray(t); this.hooks.trigger("preDelete", { key: s }); if (e.deleteMany !== void 0) { return await e.deleteMany(s); } const i = s.map(async t => e.delete(t)); const r = await Promise.all(i); const o = r.every(Boolean); this.hooks.trigger("postDelete", { key: s, value: o }); return o; } catch (t) { this.emit("error", t); if (this._throwOnErrors) { throw t; } return false; } } async clear() { this.emit("clear"); const {store: t} = this.opts; try { await t.clear(); } catch (t) { this.emit("error", t); if (this._throwOnErrors) { throw t; } } } async has(t) { if (Array.isArray(t)) { return this.hasMany(t); } const e = this._getKeyPrefix(t); const {store: s} = this.opts; if (s.has !== void 0 && !(s instanceof Map)) { return s.has(e); } let i; try { i = await s.get(e); } catch (t) { this.emit("error", t); if (this._throwOnErrors) { throw t; } return false; } if (i) { const t = await this.deserializeData(i); if (t) { if (t.expires === void 0 || t.expires === null) { return true; } return t.expires > Date.now(); } } return false; } async hasMany(t) { const e = this._getKeyPrefixArray(t); const {store: s} = this.opts; if (s.hasMany !== void 0) { return s.hasMany(e); } const i = []; for (const e of t) { i.push(await this.has(e)); } return i; } async disconnect() { const {store: t} = this.opts; this.emit("disconnect"); if (typeof t.disconnect === "function") { return t.disconnect(); } } emit(t, ...e) { if (t === "error" && !this.opts.emitErrors) { return; } super.emit(t, ...e); } async serializeData(t) { if (!this._serialize) { return t; } if (this._compression?.compress) { return this._serialize({ value: await this._compression.compress(t.value), expires: t.expires }); } return this._serialize(t); } async deserializeData(t) { if (!this._deserialize) { return t; } if (this._compression?.decompress && typeof t === "string") { const e = await this._deserialize(t); return { value: await this._compression.decompress(e?.value), expires: e?.expires }; } if (typeof t === "string") { return this._deserialize(t); } return void 0; } }; exports.index_default = exports.Keyv;