lakutata
Version:
An IoC-based universal application framework.
847 lines (833 loc) • 23.6 kB
JavaScript
/* 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;