keyv 5.4.0 → 5.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -1
- package/dist/index.cjs +178 -28
- package/dist/index.d.cts +23 -6
- package/dist/index.d.ts +23 -6
- package/dist/index.js +179 -29
- package/package.json +12 -22
package/README.md
CHANGED
|
@@ -49,6 +49,8 @@ There are a few existing modules similar to Keyv, however Keyv is different beca
|
|
|
49
49
|
- [.setMany(entries)](#setmanyentries)
|
|
50
50
|
- [.get(key, [options])](#getkey-options)
|
|
51
51
|
- [.getMany(keys, [options])](#getmanykeys-options)
|
|
52
|
+
- [.getRaw(key)](#getrawkey)
|
|
53
|
+
- [.getManyRaw(keys)](#getmanyrawkeys)
|
|
52
54
|
- [.delete(key)](#deletekey)
|
|
53
55
|
- [.deleteMany(keys)](#deletemanykeys)
|
|
54
56
|
- [.clear()](#clear)
|
|
@@ -469,7 +471,7 @@ Returns a promise which resolves to the retrieved value.
|
|
|
469
471
|
|
|
470
472
|
Returns a promise which resolves to an array of retrieved values.
|
|
471
473
|
|
|
472
|
-
### options.raw
|
|
474
|
+
### options.raw - (Will be deprecated in v6)
|
|
473
475
|
|
|
474
476
|
Type: `Boolean`<br />
|
|
475
477
|
Default: `false`
|
|
@@ -478,6 +480,16 @@ If set to true the raw DB object Keyv stores internally will be returned instead
|
|
|
478
480
|
|
|
479
481
|
This contains the TTL timestamp.
|
|
480
482
|
|
|
483
|
+
NOTE: This option will be deprecated in v6 and replaced with `.getRaw()` and `.getManyRaw()` methods.
|
|
484
|
+
|
|
485
|
+
## .getRaw(key)
|
|
486
|
+
|
|
487
|
+
Returns a promise which resolves to the raw stored data for the key or `undefined` if the key does not exist or is expired.
|
|
488
|
+
|
|
489
|
+
## .getManyRaw(keys)
|
|
490
|
+
|
|
491
|
+
Returns a promise which resolves to an array of raw stored data for the keys or `undefined` if the key does not exist or is expired.
|
|
492
|
+
|
|
481
493
|
## .delete(key)
|
|
482
494
|
|
|
483
495
|
Deletes an entry.
|
package/dist/index.cjs
CHANGED
|
@@ -49,7 +49,9 @@ var EventManager = class {
|
|
|
49
49
|
const listeners = this._eventListeners.get(event);
|
|
50
50
|
if (listeners) {
|
|
51
51
|
if (listeners.length >= this._maxListeners) {
|
|
52
|
-
console.warn(
|
|
52
|
+
console.warn(
|
|
53
|
+
`MaxListenersExceededWarning: Possible event memory leak detected. ${listeners.length + 1} ${event} listeners added. Use setMaxListeners() to increase limit.`
|
|
54
|
+
);
|
|
53
55
|
}
|
|
54
56
|
listeners.push(listener);
|
|
55
57
|
}
|
|
@@ -77,6 +79,7 @@ var EventManager = class {
|
|
|
77
79
|
this.on(event, onceListener);
|
|
78
80
|
}
|
|
79
81
|
// Emit an event
|
|
82
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
80
83
|
emit(event, ...arguments_) {
|
|
81
84
|
const listeners = this._eventListeners.get(event);
|
|
82
85
|
if (listeners && listeners.length > 0) {
|
|
@@ -131,6 +134,7 @@ var HooksManager = class extends event_manager_default {
|
|
|
131
134
|
}
|
|
132
135
|
}
|
|
133
136
|
// Triggers all handlers for a specific event with provided data
|
|
137
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
134
138
|
trigger(event, data) {
|
|
135
139
|
const eventHandlers = this._hookHandlers.get(event);
|
|
136
140
|
if (eventHandlers) {
|
|
@@ -138,7 +142,12 @@ var HooksManager = class extends event_manager_default {
|
|
|
138
142
|
try {
|
|
139
143
|
handler(data);
|
|
140
144
|
} catch (error) {
|
|
141
|
-
this.emit(
|
|
145
|
+
this.emit(
|
|
146
|
+
"error",
|
|
147
|
+
new Error(
|
|
148
|
+
`Error in hook handler for event "${event}": ${error.message}`
|
|
149
|
+
)
|
|
150
|
+
);
|
|
142
151
|
}
|
|
143
152
|
}
|
|
144
153
|
}
|
|
@@ -185,6 +194,15 @@ var StatsManager = class extends event_manager_default {
|
|
|
185
194
|
this.deletes++;
|
|
186
195
|
}
|
|
187
196
|
}
|
|
197
|
+
hitsOrMisses(array) {
|
|
198
|
+
for (const item of array) {
|
|
199
|
+
if (item === void 0) {
|
|
200
|
+
this.miss();
|
|
201
|
+
} else {
|
|
202
|
+
this.hit();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
188
206
|
reset() {
|
|
189
207
|
this.hits = 0;
|
|
190
208
|
this.misses = 0;
|
|
@@ -203,6 +221,10 @@ var KeyvHooks = /* @__PURE__ */ ((KeyvHooks2) => {
|
|
|
203
221
|
KeyvHooks2["POST_GET"] = "postGet";
|
|
204
222
|
KeyvHooks2["PRE_GET_MANY"] = "preGetMany";
|
|
205
223
|
KeyvHooks2["POST_GET_MANY"] = "postGetMany";
|
|
224
|
+
KeyvHooks2["PRE_GET_RAW"] = "preGetRaw";
|
|
225
|
+
KeyvHooks2["POST_GET_RAW"] = "postGetRaw";
|
|
226
|
+
KeyvHooks2["PRE_GET_MANY_RAW"] = "preGetManyRaw";
|
|
227
|
+
KeyvHooks2["POST_GET_MANY_RAW"] = "postGetManyRaw";
|
|
206
228
|
KeyvHooks2["PRE_DELETE"] = "preDelete";
|
|
207
229
|
KeyvHooks2["POST_DELETE"] = "postDelete";
|
|
208
230
|
return KeyvHooks2;
|
|
@@ -232,6 +254,7 @@ var Keyv = class extends event_manager_default {
|
|
|
232
254
|
/**
|
|
233
255
|
* Store
|
|
234
256
|
*/
|
|
257
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
235
258
|
_store = /* @__PURE__ */ new Map();
|
|
236
259
|
_serialize = import_serialize.defaultSerialize;
|
|
237
260
|
_deserialize = import_serialize.defaultDeserialize;
|
|
@@ -280,9 +303,14 @@ var Keyv = class extends event_manager_default {
|
|
|
280
303
|
}
|
|
281
304
|
this._store.namespace = this._namespace;
|
|
282
305
|
if (typeof this._store[Symbol.iterator] === "function" && this._store instanceof Map) {
|
|
283
|
-
this.iterator = this.generateIterator(
|
|
306
|
+
this.iterator = this.generateIterator(
|
|
307
|
+
this._store
|
|
308
|
+
);
|
|
284
309
|
} else if ("iterator" in this._store && this._store.opts && this._checkIterableAdapter()) {
|
|
285
|
-
this.iterator = this.generateIterator(
|
|
310
|
+
this.iterator = this.generateIterator(
|
|
311
|
+
// biome-ignore lint/style/noNonNullAssertion: need to fix
|
|
312
|
+
this._store.iterator.bind(this._store)
|
|
313
|
+
);
|
|
286
314
|
}
|
|
287
315
|
}
|
|
288
316
|
if (this.opts.stats) {
|
|
@@ -301,6 +329,7 @@ var Keyv = class extends event_manager_default {
|
|
|
301
329
|
/**
|
|
302
330
|
* Get the current store
|
|
303
331
|
*/
|
|
332
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
304
333
|
get store() {
|
|
305
334
|
return this._store;
|
|
306
335
|
}
|
|
@@ -308,6 +337,7 @@ var Keyv = class extends event_manager_default {
|
|
|
308
337
|
* Set the current store. This will also set the namespace, event error handler, and generate the iterator. If the store is not valid it will throw an error.
|
|
309
338
|
* @param {KeyvStoreAdapter | Map<any, any> | any} store the store to set
|
|
310
339
|
*/
|
|
340
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
311
341
|
set store(store) {
|
|
312
342
|
if (this._isValidStorageAdapter(store)) {
|
|
313
343
|
this._store = store;
|
|
@@ -319,9 +349,11 @@ var Keyv = class extends event_manager_default {
|
|
|
319
349
|
this._store.namespace = this._namespace;
|
|
320
350
|
}
|
|
321
351
|
if (typeof store[Symbol.iterator] === "function" && store instanceof Map) {
|
|
322
|
-
this.iterator = this.generateIterator(
|
|
352
|
+
this.iterator = this.generateIterator(
|
|
353
|
+
store
|
|
354
|
+
);
|
|
323
355
|
} else if ("iterator" in store && store.opts && this._checkIterableAdapter()) {
|
|
324
|
-
this.iterator = this.generateIterator(store.iterator
|
|
356
|
+
this.iterator = this.generateIterator(store.iterator?.bind(store));
|
|
325
357
|
}
|
|
326
358
|
} else {
|
|
327
359
|
throw new Error("Invalid storage adapter");
|
|
@@ -453,7 +485,9 @@ var Keyv = class extends event_manager_default {
|
|
|
453
485
|
return function_.bind(this);
|
|
454
486
|
}
|
|
455
487
|
_checkIterableAdapter() {
|
|
456
|
-
return iterableAdapters.includes(this._store.opts.dialect) || iterableAdapters.some(
|
|
488
|
+
return iterableAdapters.includes(this._store.opts.dialect) || iterableAdapters.some(
|
|
489
|
+
(element) => this._store.opts.url.includes(element)
|
|
490
|
+
);
|
|
457
491
|
}
|
|
458
492
|
_getKeyPrefix(key) {
|
|
459
493
|
if (!this._useKeyPrefix) {
|
|
@@ -479,6 +513,7 @@ var Keyv = class extends event_manager_default {
|
|
|
479
513
|
}
|
|
480
514
|
return key.split(":").splice(1).join(":");
|
|
481
515
|
}
|
|
516
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
482
517
|
_isValidStorageAdapter(store) {
|
|
483
518
|
return store instanceof Map || typeof store.get === "function" && typeof store.set === "function" && typeof store.delete === "function" && typeof store.clear === "function";
|
|
484
519
|
}
|
|
@@ -513,7 +548,10 @@ var Keyv = class extends event_manager_default {
|
|
|
513
548
|
this.stats.miss();
|
|
514
549
|
return void 0;
|
|
515
550
|
}
|
|
516
|
-
this.hooks.trigger("postGet" /* POST_GET */, {
|
|
551
|
+
this.hooks.trigger("postGet" /* POST_GET */, {
|
|
552
|
+
key: keyPrefixed,
|
|
553
|
+
value: deserializedData
|
|
554
|
+
});
|
|
517
555
|
this.stats.hit();
|
|
518
556
|
return options?.raw ? deserializedData : deserializedData.value;
|
|
519
557
|
}
|
|
@@ -536,7 +574,10 @@ var Keyv = class extends event_manager_default {
|
|
|
536
574
|
return options?.raw ? deserializedRow : deserializedRow.value;
|
|
537
575
|
});
|
|
538
576
|
const deserializedRows = await Promise.allSettled(promises);
|
|
539
|
-
const result2 = deserializedRows.map(
|
|
577
|
+
const result2 = deserializedRows.map(
|
|
578
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
579
|
+
(row) => row.value
|
|
580
|
+
);
|
|
540
581
|
this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result2);
|
|
541
582
|
if (result2.length > 0) {
|
|
542
583
|
this.stats.hit();
|
|
@@ -572,6 +613,95 @@ var Keyv = class extends event_manager_default {
|
|
|
572
613
|
}
|
|
573
614
|
return result;
|
|
574
615
|
}
|
|
616
|
+
/**
|
|
617
|
+
* Get the raw value of a key. This is the replacement for setting raw to true in the get() method.
|
|
618
|
+
* @param {string} key the key to get
|
|
619
|
+
* @returns {Promise<StoredDataRaw<Value> | undefined>} will return a StoredDataRaw<Value> or undefined if the key does not exist or is expired.
|
|
620
|
+
*/
|
|
621
|
+
async getRaw(key) {
|
|
622
|
+
const { store } = this.opts;
|
|
623
|
+
const keyPrefixed = this._getKeyPrefix(key);
|
|
624
|
+
this.hooks.trigger("preGetRaw" /* PRE_GET_RAW */, { key: keyPrefixed });
|
|
625
|
+
const rawData = await store.get(keyPrefixed);
|
|
626
|
+
if (rawData === void 0 || rawData === null) {
|
|
627
|
+
this.stats.miss();
|
|
628
|
+
return void 0;
|
|
629
|
+
}
|
|
630
|
+
const deserializedData = typeof rawData === "string" || this.opts.compression ? await this.deserializeData(rawData) : rawData;
|
|
631
|
+
if (deserializedData !== void 0 && deserializedData.expires !== void 0 && deserializedData.expires !== null && // biome-ignore lint/style/noNonNullAssertion: need to fix
|
|
632
|
+
deserializedData.expires < Date.now()) {
|
|
633
|
+
this.stats.miss();
|
|
634
|
+
await this.delete(key);
|
|
635
|
+
return void 0;
|
|
636
|
+
}
|
|
637
|
+
this.stats.hit();
|
|
638
|
+
this.hooks.trigger("postGetRaw" /* POST_GET_RAW */, {
|
|
639
|
+
key: keyPrefixed,
|
|
640
|
+
value: deserializedData
|
|
641
|
+
});
|
|
642
|
+
return deserializedData;
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Get the raw values of many keys. This is the replacement for setting raw to true in the getMany() method.
|
|
646
|
+
* @param {string[]} keys the keys to get
|
|
647
|
+
* @returns {Promise<Array<StoredDataRaw<Value>>>} will return an array of StoredDataRaw<Value> or undefined if the key does not exist or is expired.
|
|
648
|
+
*/
|
|
649
|
+
async getManyRaw(keys) {
|
|
650
|
+
const { store } = this.opts;
|
|
651
|
+
const keyPrefixed = this._getKeyPrefixArray(keys);
|
|
652
|
+
if (keys.length === 0) {
|
|
653
|
+
const result2 = Array.from({ length: keys.length }).fill(
|
|
654
|
+
void 0
|
|
655
|
+
);
|
|
656
|
+
this.stats.misses += keys.length;
|
|
657
|
+
this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, {
|
|
658
|
+
keys: keyPrefixed,
|
|
659
|
+
values: result2
|
|
660
|
+
});
|
|
661
|
+
return result2;
|
|
662
|
+
}
|
|
663
|
+
let result = [];
|
|
664
|
+
if (store.getMany === void 0) {
|
|
665
|
+
const promises = keyPrefixed.map(async (key) => {
|
|
666
|
+
const rawData = await store.get(key);
|
|
667
|
+
if (rawData !== void 0 && rawData !== null) {
|
|
668
|
+
return this.deserializeData(rawData);
|
|
669
|
+
}
|
|
670
|
+
return void 0;
|
|
671
|
+
});
|
|
672
|
+
const deserializedRows = await Promise.allSettled(promises);
|
|
673
|
+
result = deserializedRows.map(
|
|
674
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
675
|
+
(row) => row.value
|
|
676
|
+
);
|
|
677
|
+
} else {
|
|
678
|
+
const rawData = await store.getMany(keyPrefixed);
|
|
679
|
+
for (const row of rawData) {
|
|
680
|
+
if (row !== void 0 && row !== null) {
|
|
681
|
+
result.push(await this.deserializeData(row));
|
|
682
|
+
} else {
|
|
683
|
+
result.push(void 0);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
const expiredKeys = [];
|
|
688
|
+
const isDataExpired = (data) => typeof data.expires === "number" && Date.now() > data.expires;
|
|
689
|
+
for (const [index, row] of result.entries()) {
|
|
690
|
+
if (row !== void 0 && isDataExpired(row)) {
|
|
691
|
+
expiredKeys.push(keyPrefixed[index]);
|
|
692
|
+
result[index] = void 0;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
if (expiredKeys.length > 0) {
|
|
696
|
+
await this.deleteMany(expiredKeys);
|
|
697
|
+
}
|
|
698
|
+
this.stats.hitsOrMisses(result);
|
|
699
|
+
this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, {
|
|
700
|
+
keys: keyPrefixed,
|
|
701
|
+
values: result
|
|
702
|
+
});
|
|
703
|
+
return result;
|
|
704
|
+
}
|
|
575
705
|
/**
|
|
576
706
|
* Set an item to the store
|
|
577
707
|
* @param {string | Array<KeyvEntry>} key the key to use. If you pass in an array of KeyvEntry it will set many items
|
|
@@ -608,7 +738,11 @@ var Keyv = class extends event_manager_default {
|
|
|
608
738
|
throw error;
|
|
609
739
|
}
|
|
610
740
|
}
|
|
611
|
-
this.hooks.trigger("postSet" /* POST_SET */, {
|
|
741
|
+
this.hooks.trigger("postSet" /* POST_SET */, {
|
|
742
|
+
key: keyPrefixed,
|
|
743
|
+
value: serializedValue,
|
|
744
|
+
ttl
|
|
745
|
+
});
|
|
612
746
|
this.stats.set();
|
|
613
747
|
return result;
|
|
614
748
|
}
|
|
@@ -617,6 +751,7 @@ var Keyv = class extends event_manager_default {
|
|
|
617
751
|
* @param {Array<KeyvEntry>} entries the entries to set
|
|
618
752
|
* @returns {boolean[]} will return an array of booleans if it sets then it will return a true. On failure will return false.
|
|
619
753
|
*/
|
|
754
|
+
// biome-ignore lint/correctness/noUnusedVariables: type format
|
|
620
755
|
async setMany(entries) {
|
|
621
756
|
let results = [];
|
|
622
757
|
try {
|
|
@@ -628,20 +763,22 @@ var Keyv = class extends event_manager_default {
|
|
|
628
763
|
const promiseResults = await Promise.all(promises);
|
|
629
764
|
results = promiseResults;
|
|
630
765
|
} else {
|
|
631
|
-
const serializedEntries = await Promise.all(
|
|
632
|
-
ttl
|
|
633
|
-
|
|
634
|
-
ttl
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
766
|
+
const serializedEntries = await Promise.all(
|
|
767
|
+
entries.map(async ({ key, value, ttl }) => {
|
|
768
|
+
ttl ??= this._ttl;
|
|
769
|
+
if (ttl === 0) {
|
|
770
|
+
ttl = void 0;
|
|
771
|
+
}
|
|
772
|
+
const expires = typeof ttl === "number" ? Date.now() + ttl : void 0;
|
|
773
|
+
if (typeof value === "symbol") {
|
|
774
|
+
this.emit("error", "symbol cannot be serialized");
|
|
775
|
+
throw new Error("symbol cannot be serialized");
|
|
776
|
+
}
|
|
777
|
+
const formattedValue = { value, expires };
|
|
778
|
+
const serializedValue = await this.serializeData(formattedValue);
|
|
779
|
+
return { key, value: serializedValue, ttl };
|
|
780
|
+
})
|
|
781
|
+
);
|
|
645
782
|
results = await this._store.setMany(serializedEntries);
|
|
646
783
|
}
|
|
647
784
|
} catch (error) {
|
|
@@ -678,7 +815,10 @@ var Keyv = class extends event_manager_default {
|
|
|
678
815
|
throw error;
|
|
679
816
|
}
|
|
680
817
|
}
|
|
681
|
-
this.hooks.trigger("postDelete" /* POST_DELETE */, {
|
|
818
|
+
this.hooks.trigger("postDelete" /* POST_DELETE */, {
|
|
819
|
+
key: keyPrefixed,
|
|
820
|
+
value: result
|
|
821
|
+
});
|
|
682
822
|
this.stats.delete();
|
|
683
823
|
return result;
|
|
684
824
|
}
|
|
@@ -698,7 +838,10 @@ var Keyv = class extends event_manager_default {
|
|
|
698
838
|
const promises = keyPrefixed.map(async (key) => store.delete(key));
|
|
699
839
|
const results = await Promise.all(promises);
|
|
700
840
|
const returnResult = results.every(Boolean);
|
|
701
|
-
this.hooks.trigger("postDelete" /* POST_DELETE */, {
|
|
841
|
+
this.hooks.trigger("postDelete" /* POST_DELETE */, {
|
|
842
|
+
key: keyPrefixed,
|
|
843
|
+
value: returnResult
|
|
844
|
+
});
|
|
702
845
|
return returnResult;
|
|
703
846
|
} catch (error) {
|
|
704
847
|
this.emit("error", error);
|
|
@@ -782,6 +925,7 @@ var Keyv = class extends event_manager_default {
|
|
|
782
925
|
return store.disconnect();
|
|
783
926
|
}
|
|
784
927
|
}
|
|
928
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
785
929
|
emit(event, ...arguments_) {
|
|
786
930
|
if (event === "error" && !this.opts.emitErrors) {
|
|
787
931
|
return;
|
|
@@ -793,7 +937,10 @@ var Keyv = class extends event_manager_default {
|
|
|
793
937
|
return data;
|
|
794
938
|
}
|
|
795
939
|
if (this._compression?.compress) {
|
|
796
|
-
return this._serialize({
|
|
940
|
+
return this._serialize({
|
|
941
|
+
value: await this._compression.compress(data.value),
|
|
942
|
+
expires: data.expires
|
|
943
|
+
});
|
|
797
944
|
}
|
|
798
945
|
return this._serialize(data);
|
|
799
946
|
}
|
|
@@ -803,7 +950,10 @@ var Keyv = class extends event_manager_default {
|
|
|
803
950
|
}
|
|
804
951
|
if (this._compression?.decompress && typeof data === "string") {
|
|
805
952
|
const result = await this._deserialize(data);
|
|
806
|
-
return {
|
|
953
|
+
return {
|
|
954
|
+
value: await this._compression.decompress(result?.value),
|
|
955
|
+
expires: result?.expires
|
|
956
|
+
};
|
|
807
957
|
}
|
|
808
958
|
if (typeof data === "string") {
|
|
809
959
|
return this._deserialize(data);
|
package/dist/index.d.cts
CHANGED
|
@@ -37,6 +37,7 @@ declare class StatsManager extends EventManager {
|
|
|
37
37
|
miss(): void;
|
|
38
38
|
set(): void;
|
|
39
39
|
delete(): void;
|
|
40
|
+
hitsOrMisses<T>(array: Array<T | undefined>): void;
|
|
40
41
|
reset(): void;
|
|
41
42
|
}
|
|
42
43
|
|
|
@@ -59,6 +60,10 @@ declare enum KeyvHooks {
|
|
|
59
60
|
POST_GET = "postGet",
|
|
60
61
|
PRE_GET_MANY = "preGetMany",
|
|
61
62
|
POST_GET_MANY = "postGetMany",
|
|
63
|
+
PRE_GET_RAW = "preGetRaw",
|
|
64
|
+
POST_GET_RAW = "postGetRaw",
|
|
65
|
+
PRE_GET_MANY_RAW = "preGetManyRaw",
|
|
66
|
+
POST_GET_MANY_RAW = "postGetManyRaw",
|
|
62
67
|
PRE_DELETE = "preDelete",
|
|
63
68
|
POST_DELETE = "postDelete"
|
|
64
69
|
}
|
|
@@ -105,12 +110,12 @@ type KeyvOptions = {
|
|
|
105
110
|
/**
|
|
106
111
|
* Emit errors
|
|
107
112
|
* @default true
|
|
108
|
-
|
|
113
|
+
*/
|
|
109
114
|
emitErrors?: boolean;
|
|
110
115
|
/**
|
|
111
116
|
* Namespace for the current instance.
|
|
112
117
|
* @default 'keyv'
|
|
113
|
-
|
|
118
|
+
*/
|
|
114
119
|
namespace?: string;
|
|
115
120
|
/**
|
|
116
121
|
* A custom serialization function.
|
|
@@ -120,7 +125,7 @@ type KeyvOptions = {
|
|
|
120
125
|
/**
|
|
121
126
|
* A custom deserialization function.
|
|
122
127
|
* @default defaultDeserialize using JSON.parse
|
|
123
|
-
|
|
128
|
+
*/
|
|
124
129
|
deserialize?: Deserialize;
|
|
125
130
|
/**
|
|
126
131
|
* The storage adapter instance to be used by Keyv.
|
|
@@ -153,8 +158,8 @@ type KeyvOptions = {
|
|
|
153
158
|
*/
|
|
154
159
|
throwOnErrors?: boolean;
|
|
155
160
|
};
|
|
156
|
-
type KeyvOptions_ = Omit<KeyvOptions,
|
|
157
|
-
store: KeyvStoreAdapter | Map<any, any> & KeyvStoreAdapter;
|
|
161
|
+
type KeyvOptions_ = Omit<KeyvOptions, "store"> & {
|
|
162
|
+
store: KeyvStoreAdapter | (Map<any, any> & KeyvStoreAdapter);
|
|
158
163
|
};
|
|
159
164
|
type IteratorFunction = (argument: any) => AsyncGenerator<any, void>;
|
|
160
165
|
declare class Keyv<GenericValue = any> extends EventManager {
|
|
@@ -184,7 +189,7 @@ declare class Keyv<GenericValue = any> extends EventManager {
|
|
|
184
189
|
* @param {KeyvStoreAdapter | KeyvOptions | Map<any, any>} store to be provided or just the options
|
|
185
190
|
* @param {Omit<KeyvOptions, 'store'>} [options] if you provide the store you can then provide the Keyv Options
|
|
186
191
|
*/
|
|
187
|
-
constructor(store?: KeyvStoreAdapter | KeyvOptions | Map<any, any>, options?: Omit<KeyvOptions,
|
|
192
|
+
constructor(store?: KeyvStoreAdapter | KeyvOptions | Map<any, any>, options?: Omit<KeyvOptions, "store">);
|
|
188
193
|
/**
|
|
189
194
|
* Keyv Constructor
|
|
190
195
|
* @param {KeyvOptions} options to be provided
|
|
@@ -304,6 +309,18 @@ declare class Keyv<GenericValue = any> extends EventManager {
|
|
|
304
309
|
getMany<Value = GenericValue>(keys: string[], options?: {
|
|
305
310
|
raw: true;
|
|
306
311
|
}): Promise<Array<StoredDataRaw<Value>>>;
|
|
312
|
+
/**
|
|
313
|
+
* Get the raw value of a key. This is the replacement for setting raw to true in the get() method.
|
|
314
|
+
* @param {string} key the key to get
|
|
315
|
+
* @returns {Promise<StoredDataRaw<Value> | undefined>} will return a StoredDataRaw<Value> or undefined if the key does not exist or is expired.
|
|
316
|
+
*/
|
|
317
|
+
getRaw<Value = GenericValue>(key: string): Promise<StoredDataRaw<Value> | undefined>;
|
|
318
|
+
/**
|
|
319
|
+
* Get the raw values of many keys. This is the replacement for setting raw to true in the getMany() method.
|
|
320
|
+
* @param {string[]} keys the keys to get
|
|
321
|
+
* @returns {Promise<Array<StoredDataRaw<Value>>>} will return an array of StoredDataRaw<Value> or undefined if the key does not exist or is expired.
|
|
322
|
+
*/
|
|
323
|
+
getManyRaw<Value = GenericValue>(keys: string[]): Promise<Array<StoredDataRaw<Value>>>;
|
|
307
324
|
/**
|
|
308
325
|
* Set an item to the store
|
|
309
326
|
* @param {string | Array<KeyvEntry>} key the key to use. If you pass in an array of KeyvEntry it will set many items
|
package/dist/index.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ declare class StatsManager extends EventManager {
|
|
|
37
37
|
miss(): void;
|
|
38
38
|
set(): void;
|
|
39
39
|
delete(): void;
|
|
40
|
+
hitsOrMisses<T>(array: Array<T | undefined>): void;
|
|
40
41
|
reset(): void;
|
|
41
42
|
}
|
|
42
43
|
|
|
@@ -59,6 +60,10 @@ declare enum KeyvHooks {
|
|
|
59
60
|
POST_GET = "postGet",
|
|
60
61
|
PRE_GET_MANY = "preGetMany",
|
|
61
62
|
POST_GET_MANY = "postGetMany",
|
|
63
|
+
PRE_GET_RAW = "preGetRaw",
|
|
64
|
+
POST_GET_RAW = "postGetRaw",
|
|
65
|
+
PRE_GET_MANY_RAW = "preGetManyRaw",
|
|
66
|
+
POST_GET_MANY_RAW = "postGetManyRaw",
|
|
62
67
|
PRE_DELETE = "preDelete",
|
|
63
68
|
POST_DELETE = "postDelete"
|
|
64
69
|
}
|
|
@@ -105,12 +110,12 @@ type KeyvOptions = {
|
|
|
105
110
|
/**
|
|
106
111
|
* Emit errors
|
|
107
112
|
* @default true
|
|
108
|
-
|
|
113
|
+
*/
|
|
109
114
|
emitErrors?: boolean;
|
|
110
115
|
/**
|
|
111
116
|
* Namespace for the current instance.
|
|
112
117
|
* @default 'keyv'
|
|
113
|
-
|
|
118
|
+
*/
|
|
114
119
|
namespace?: string;
|
|
115
120
|
/**
|
|
116
121
|
* A custom serialization function.
|
|
@@ -120,7 +125,7 @@ type KeyvOptions = {
|
|
|
120
125
|
/**
|
|
121
126
|
* A custom deserialization function.
|
|
122
127
|
* @default defaultDeserialize using JSON.parse
|
|
123
|
-
|
|
128
|
+
*/
|
|
124
129
|
deserialize?: Deserialize;
|
|
125
130
|
/**
|
|
126
131
|
* The storage adapter instance to be used by Keyv.
|
|
@@ -153,8 +158,8 @@ type KeyvOptions = {
|
|
|
153
158
|
*/
|
|
154
159
|
throwOnErrors?: boolean;
|
|
155
160
|
};
|
|
156
|
-
type KeyvOptions_ = Omit<KeyvOptions,
|
|
157
|
-
store: KeyvStoreAdapter | Map<any, any> & KeyvStoreAdapter;
|
|
161
|
+
type KeyvOptions_ = Omit<KeyvOptions, "store"> & {
|
|
162
|
+
store: KeyvStoreAdapter | (Map<any, any> & KeyvStoreAdapter);
|
|
158
163
|
};
|
|
159
164
|
type IteratorFunction = (argument: any) => AsyncGenerator<any, void>;
|
|
160
165
|
declare class Keyv<GenericValue = any> extends EventManager {
|
|
@@ -184,7 +189,7 @@ declare class Keyv<GenericValue = any> extends EventManager {
|
|
|
184
189
|
* @param {KeyvStoreAdapter | KeyvOptions | Map<any, any>} store to be provided or just the options
|
|
185
190
|
* @param {Omit<KeyvOptions, 'store'>} [options] if you provide the store you can then provide the Keyv Options
|
|
186
191
|
*/
|
|
187
|
-
constructor(store?: KeyvStoreAdapter | KeyvOptions | Map<any, any>, options?: Omit<KeyvOptions,
|
|
192
|
+
constructor(store?: KeyvStoreAdapter | KeyvOptions | Map<any, any>, options?: Omit<KeyvOptions, "store">);
|
|
188
193
|
/**
|
|
189
194
|
* Keyv Constructor
|
|
190
195
|
* @param {KeyvOptions} options to be provided
|
|
@@ -304,6 +309,18 @@ declare class Keyv<GenericValue = any> extends EventManager {
|
|
|
304
309
|
getMany<Value = GenericValue>(keys: string[], options?: {
|
|
305
310
|
raw: true;
|
|
306
311
|
}): Promise<Array<StoredDataRaw<Value>>>;
|
|
312
|
+
/**
|
|
313
|
+
* Get the raw value of a key. This is the replacement for setting raw to true in the get() method.
|
|
314
|
+
* @param {string} key the key to get
|
|
315
|
+
* @returns {Promise<StoredDataRaw<Value> | undefined>} will return a StoredDataRaw<Value> or undefined if the key does not exist or is expired.
|
|
316
|
+
*/
|
|
317
|
+
getRaw<Value = GenericValue>(key: string): Promise<StoredDataRaw<Value> | undefined>;
|
|
318
|
+
/**
|
|
319
|
+
* Get the raw values of many keys. This is the replacement for setting raw to true in the getMany() method.
|
|
320
|
+
* @param {string[]} keys the keys to get
|
|
321
|
+
* @returns {Promise<Array<StoredDataRaw<Value>>>} will return an array of StoredDataRaw<Value> or undefined if the key does not exist or is expired.
|
|
322
|
+
*/
|
|
323
|
+
getManyRaw<Value = GenericValue>(keys: string[]): Promise<Array<StoredDataRaw<Value>>>;
|
|
307
324
|
/**
|
|
308
325
|
* Set an item to the store
|
|
309
326
|
* @param {string | Array<KeyvEntry>} key the key to use. If you pass in an array of KeyvEntry it will set many items
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import {
|
|
2
|
+
import { defaultDeserialize, defaultSerialize } from "@keyv/serialize";
|
|
3
3
|
|
|
4
4
|
// src/event-manager.ts
|
|
5
5
|
var EventManager = class {
|
|
@@ -23,7 +23,9 @@ var EventManager = class {
|
|
|
23
23
|
const listeners = this._eventListeners.get(event);
|
|
24
24
|
if (listeners) {
|
|
25
25
|
if (listeners.length >= this._maxListeners) {
|
|
26
|
-
console.warn(
|
|
26
|
+
console.warn(
|
|
27
|
+
`MaxListenersExceededWarning: Possible event memory leak detected. ${listeners.length + 1} ${event} listeners added. Use setMaxListeners() to increase limit.`
|
|
28
|
+
);
|
|
27
29
|
}
|
|
28
30
|
listeners.push(listener);
|
|
29
31
|
}
|
|
@@ -51,6 +53,7 @@ var EventManager = class {
|
|
|
51
53
|
this.on(event, onceListener);
|
|
52
54
|
}
|
|
53
55
|
// Emit an event
|
|
56
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
54
57
|
emit(event, ...arguments_) {
|
|
55
58
|
const listeners = this._eventListeners.get(event);
|
|
56
59
|
if (listeners && listeners.length > 0) {
|
|
@@ -105,6 +108,7 @@ var HooksManager = class extends event_manager_default {
|
|
|
105
108
|
}
|
|
106
109
|
}
|
|
107
110
|
// Triggers all handlers for a specific event with provided data
|
|
111
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
108
112
|
trigger(event, data) {
|
|
109
113
|
const eventHandlers = this._hookHandlers.get(event);
|
|
110
114
|
if (eventHandlers) {
|
|
@@ -112,7 +116,12 @@ var HooksManager = class extends event_manager_default {
|
|
|
112
116
|
try {
|
|
113
117
|
handler(data);
|
|
114
118
|
} catch (error) {
|
|
115
|
-
this.emit(
|
|
119
|
+
this.emit(
|
|
120
|
+
"error",
|
|
121
|
+
new Error(
|
|
122
|
+
`Error in hook handler for event "${event}": ${error.message}`
|
|
123
|
+
)
|
|
124
|
+
);
|
|
116
125
|
}
|
|
117
126
|
}
|
|
118
127
|
}
|
|
@@ -159,6 +168,15 @@ var StatsManager = class extends event_manager_default {
|
|
|
159
168
|
this.deletes++;
|
|
160
169
|
}
|
|
161
170
|
}
|
|
171
|
+
hitsOrMisses(array) {
|
|
172
|
+
for (const item of array) {
|
|
173
|
+
if (item === void 0) {
|
|
174
|
+
this.miss();
|
|
175
|
+
} else {
|
|
176
|
+
this.hit();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
162
180
|
reset() {
|
|
163
181
|
this.hits = 0;
|
|
164
182
|
this.misses = 0;
|
|
@@ -177,6 +195,10 @@ var KeyvHooks = /* @__PURE__ */ ((KeyvHooks2) => {
|
|
|
177
195
|
KeyvHooks2["POST_GET"] = "postGet";
|
|
178
196
|
KeyvHooks2["PRE_GET_MANY"] = "preGetMany";
|
|
179
197
|
KeyvHooks2["POST_GET_MANY"] = "postGetMany";
|
|
198
|
+
KeyvHooks2["PRE_GET_RAW"] = "preGetRaw";
|
|
199
|
+
KeyvHooks2["POST_GET_RAW"] = "postGetRaw";
|
|
200
|
+
KeyvHooks2["PRE_GET_MANY_RAW"] = "preGetManyRaw";
|
|
201
|
+
KeyvHooks2["POST_GET_MANY_RAW"] = "postGetManyRaw";
|
|
180
202
|
KeyvHooks2["PRE_DELETE"] = "preDelete";
|
|
181
203
|
KeyvHooks2["POST_DELETE"] = "postDelete";
|
|
182
204
|
return KeyvHooks2;
|
|
@@ -206,6 +228,7 @@ var Keyv = class extends event_manager_default {
|
|
|
206
228
|
/**
|
|
207
229
|
* Store
|
|
208
230
|
*/
|
|
231
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
209
232
|
_store = /* @__PURE__ */ new Map();
|
|
210
233
|
_serialize = defaultSerialize;
|
|
211
234
|
_deserialize = defaultDeserialize;
|
|
@@ -254,9 +277,14 @@ var Keyv = class extends event_manager_default {
|
|
|
254
277
|
}
|
|
255
278
|
this._store.namespace = this._namespace;
|
|
256
279
|
if (typeof this._store[Symbol.iterator] === "function" && this._store instanceof Map) {
|
|
257
|
-
this.iterator = this.generateIterator(
|
|
280
|
+
this.iterator = this.generateIterator(
|
|
281
|
+
this._store
|
|
282
|
+
);
|
|
258
283
|
} else if ("iterator" in this._store && this._store.opts && this._checkIterableAdapter()) {
|
|
259
|
-
this.iterator = this.generateIterator(
|
|
284
|
+
this.iterator = this.generateIterator(
|
|
285
|
+
// biome-ignore lint/style/noNonNullAssertion: need to fix
|
|
286
|
+
this._store.iterator.bind(this._store)
|
|
287
|
+
);
|
|
260
288
|
}
|
|
261
289
|
}
|
|
262
290
|
if (this.opts.stats) {
|
|
@@ -275,6 +303,7 @@ var Keyv = class extends event_manager_default {
|
|
|
275
303
|
/**
|
|
276
304
|
* Get the current store
|
|
277
305
|
*/
|
|
306
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
278
307
|
get store() {
|
|
279
308
|
return this._store;
|
|
280
309
|
}
|
|
@@ -282,6 +311,7 @@ var Keyv = class extends event_manager_default {
|
|
|
282
311
|
* Set the current store. This will also set the namespace, event error handler, and generate the iterator. If the store is not valid it will throw an error.
|
|
283
312
|
* @param {KeyvStoreAdapter | Map<any, any> | any} store the store to set
|
|
284
313
|
*/
|
|
314
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
285
315
|
set store(store) {
|
|
286
316
|
if (this._isValidStorageAdapter(store)) {
|
|
287
317
|
this._store = store;
|
|
@@ -293,9 +323,11 @@ var Keyv = class extends event_manager_default {
|
|
|
293
323
|
this._store.namespace = this._namespace;
|
|
294
324
|
}
|
|
295
325
|
if (typeof store[Symbol.iterator] === "function" && store instanceof Map) {
|
|
296
|
-
this.iterator = this.generateIterator(
|
|
326
|
+
this.iterator = this.generateIterator(
|
|
327
|
+
store
|
|
328
|
+
);
|
|
297
329
|
} else if ("iterator" in store && store.opts && this._checkIterableAdapter()) {
|
|
298
|
-
this.iterator = this.generateIterator(store.iterator
|
|
330
|
+
this.iterator = this.generateIterator(store.iterator?.bind(store));
|
|
299
331
|
}
|
|
300
332
|
} else {
|
|
301
333
|
throw new Error("Invalid storage adapter");
|
|
@@ -427,7 +459,9 @@ var Keyv = class extends event_manager_default {
|
|
|
427
459
|
return function_.bind(this);
|
|
428
460
|
}
|
|
429
461
|
_checkIterableAdapter() {
|
|
430
|
-
return iterableAdapters.includes(this._store.opts.dialect) || iterableAdapters.some(
|
|
462
|
+
return iterableAdapters.includes(this._store.opts.dialect) || iterableAdapters.some(
|
|
463
|
+
(element) => this._store.opts.url.includes(element)
|
|
464
|
+
);
|
|
431
465
|
}
|
|
432
466
|
_getKeyPrefix(key) {
|
|
433
467
|
if (!this._useKeyPrefix) {
|
|
@@ -453,6 +487,7 @@ var Keyv = class extends event_manager_default {
|
|
|
453
487
|
}
|
|
454
488
|
return key.split(":").splice(1).join(":");
|
|
455
489
|
}
|
|
490
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
456
491
|
_isValidStorageAdapter(store) {
|
|
457
492
|
return store instanceof Map || typeof store.get === "function" && typeof store.set === "function" && typeof store.delete === "function" && typeof store.clear === "function";
|
|
458
493
|
}
|
|
@@ -487,7 +522,10 @@ var Keyv = class extends event_manager_default {
|
|
|
487
522
|
this.stats.miss();
|
|
488
523
|
return void 0;
|
|
489
524
|
}
|
|
490
|
-
this.hooks.trigger("postGet" /* POST_GET */, {
|
|
525
|
+
this.hooks.trigger("postGet" /* POST_GET */, {
|
|
526
|
+
key: keyPrefixed,
|
|
527
|
+
value: deserializedData
|
|
528
|
+
});
|
|
491
529
|
this.stats.hit();
|
|
492
530
|
return options?.raw ? deserializedData : deserializedData.value;
|
|
493
531
|
}
|
|
@@ -510,7 +548,10 @@ var Keyv = class extends event_manager_default {
|
|
|
510
548
|
return options?.raw ? deserializedRow : deserializedRow.value;
|
|
511
549
|
});
|
|
512
550
|
const deserializedRows = await Promise.allSettled(promises);
|
|
513
|
-
const result2 = deserializedRows.map(
|
|
551
|
+
const result2 = deserializedRows.map(
|
|
552
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
553
|
+
(row) => row.value
|
|
554
|
+
);
|
|
514
555
|
this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result2);
|
|
515
556
|
if (result2.length > 0) {
|
|
516
557
|
this.stats.hit();
|
|
@@ -546,6 +587,95 @@ var Keyv = class extends event_manager_default {
|
|
|
546
587
|
}
|
|
547
588
|
return result;
|
|
548
589
|
}
|
|
590
|
+
/**
|
|
591
|
+
* Get the raw value of a key. This is the replacement for setting raw to true in the get() method.
|
|
592
|
+
* @param {string} key the key to get
|
|
593
|
+
* @returns {Promise<StoredDataRaw<Value> | undefined>} will return a StoredDataRaw<Value> or undefined if the key does not exist or is expired.
|
|
594
|
+
*/
|
|
595
|
+
async getRaw(key) {
|
|
596
|
+
const { store } = this.opts;
|
|
597
|
+
const keyPrefixed = this._getKeyPrefix(key);
|
|
598
|
+
this.hooks.trigger("preGetRaw" /* PRE_GET_RAW */, { key: keyPrefixed });
|
|
599
|
+
const rawData = await store.get(keyPrefixed);
|
|
600
|
+
if (rawData === void 0 || rawData === null) {
|
|
601
|
+
this.stats.miss();
|
|
602
|
+
return void 0;
|
|
603
|
+
}
|
|
604
|
+
const deserializedData = typeof rawData === "string" || this.opts.compression ? await this.deserializeData(rawData) : rawData;
|
|
605
|
+
if (deserializedData !== void 0 && deserializedData.expires !== void 0 && deserializedData.expires !== null && // biome-ignore lint/style/noNonNullAssertion: need to fix
|
|
606
|
+
deserializedData.expires < Date.now()) {
|
|
607
|
+
this.stats.miss();
|
|
608
|
+
await this.delete(key);
|
|
609
|
+
return void 0;
|
|
610
|
+
}
|
|
611
|
+
this.stats.hit();
|
|
612
|
+
this.hooks.trigger("postGetRaw" /* POST_GET_RAW */, {
|
|
613
|
+
key: keyPrefixed,
|
|
614
|
+
value: deserializedData
|
|
615
|
+
});
|
|
616
|
+
return deserializedData;
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Get the raw values of many keys. This is the replacement for setting raw to true in the getMany() method.
|
|
620
|
+
* @param {string[]} keys the keys to get
|
|
621
|
+
* @returns {Promise<Array<StoredDataRaw<Value>>>} will return an array of StoredDataRaw<Value> or undefined if the key does not exist or is expired.
|
|
622
|
+
*/
|
|
623
|
+
async getManyRaw(keys) {
|
|
624
|
+
const { store } = this.opts;
|
|
625
|
+
const keyPrefixed = this._getKeyPrefixArray(keys);
|
|
626
|
+
if (keys.length === 0) {
|
|
627
|
+
const result2 = Array.from({ length: keys.length }).fill(
|
|
628
|
+
void 0
|
|
629
|
+
);
|
|
630
|
+
this.stats.misses += keys.length;
|
|
631
|
+
this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, {
|
|
632
|
+
keys: keyPrefixed,
|
|
633
|
+
values: result2
|
|
634
|
+
});
|
|
635
|
+
return result2;
|
|
636
|
+
}
|
|
637
|
+
let result = [];
|
|
638
|
+
if (store.getMany === void 0) {
|
|
639
|
+
const promises = keyPrefixed.map(async (key) => {
|
|
640
|
+
const rawData = await store.get(key);
|
|
641
|
+
if (rawData !== void 0 && rawData !== null) {
|
|
642
|
+
return this.deserializeData(rawData);
|
|
643
|
+
}
|
|
644
|
+
return void 0;
|
|
645
|
+
});
|
|
646
|
+
const deserializedRows = await Promise.allSettled(promises);
|
|
647
|
+
result = deserializedRows.map(
|
|
648
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
649
|
+
(row) => row.value
|
|
650
|
+
);
|
|
651
|
+
} else {
|
|
652
|
+
const rawData = await store.getMany(keyPrefixed);
|
|
653
|
+
for (const row of rawData) {
|
|
654
|
+
if (row !== void 0 && row !== null) {
|
|
655
|
+
result.push(await this.deserializeData(row));
|
|
656
|
+
} else {
|
|
657
|
+
result.push(void 0);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
const expiredKeys = [];
|
|
662
|
+
const isDataExpired = (data) => typeof data.expires === "number" && Date.now() > data.expires;
|
|
663
|
+
for (const [index, row] of result.entries()) {
|
|
664
|
+
if (row !== void 0 && isDataExpired(row)) {
|
|
665
|
+
expiredKeys.push(keyPrefixed[index]);
|
|
666
|
+
result[index] = void 0;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
if (expiredKeys.length > 0) {
|
|
670
|
+
await this.deleteMany(expiredKeys);
|
|
671
|
+
}
|
|
672
|
+
this.stats.hitsOrMisses(result);
|
|
673
|
+
this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, {
|
|
674
|
+
keys: keyPrefixed,
|
|
675
|
+
values: result
|
|
676
|
+
});
|
|
677
|
+
return result;
|
|
678
|
+
}
|
|
549
679
|
/**
|
|
550
680
|
* Set an item to the store
|
|
551
681
|
* @param {string | Array<KeyvEntry>} key the key to use. If you pass in an array of KeyvEntry it will set many items
|
|
@@ -582,7 +712,11 @@ var Keyv = class extends event_manager_default {
|
|
|
582
712
|
throw error;
|
|
583
713
|
}
|
|
584
714
|
}
|
|
585
|
-
this.hooks.trigger("postSet" /* POST_SET */, {
|
|
715
|
+
this.hooks.trigger("postSet" /* POST_SET */, {
|
|
716
|
+
key: keyPrefixed,
|
|
717
|
+
value: serializedValue,
|
|
718
|
+
ttl
|
|
719
|
+
});
|
|
586
720
|
this.stats.set();
|
|
587
721
|
return result;
|
|
588
722
|
}
|
|
@@ -591,6 +725,7 @@ var Keyv = class extends event_manager_default {
|
|
|
591
725
|
* @param {Array<KeyvEntry>} entries the entries to set
|
|
592
726
|
* @returns {boolean[]} will return an array of booleans if it sets then it will return a true. On failure will return false.
|
|
593
727
|
*/
|
|
728
|
+
// biome-ignore lint/correctness/noUnusedVariables: type format
|
|
594
729
|
async setMany(entries) {
|
|
595
730
|
let results = [];
|
|
596
731
|
try {
|
|
@@ -602,20 +737,22 @@ var Keyv = class extends event_manager_default {
|
|
|
602
737
|
const promiseResults = await Promise.all(promises);
|
|
603
738
|
results = promiseResults;
|
|
604
739
|
} else {
|
|
605
|
-
const serializedEntries = await Promise.all(
|
|
606
|
-
ttl
|
|
607
|
-
|
|
608
|
-
ttl
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
740
|
+
const serializedEntries = await Promise.all(
|
|
741
|
+
entries.map(async ({ key, value, ttl }) => {
|
|
742
|
+
ttl ??= this._ttl;
|
|
743
|
+
if (ttl === 0) {
|
|
744
|
+
ttl = void 0;
|
|
745
|
+
}
|
|
746
|
+
const expires = typeof ttl === "number" ? Date.now() + ttl : void 0;
|
|
747
|
+
if (typeof value === "symbol") {
|
|
748
|
+
this.emit("error", "symbol cannot be serialized");
|
|
749
|
+
throw new Error("symbol cannot be serialized");
|
|
750
|
+
}
|
|
751
|
+
const formattedValue = { value, expires };
|
|
752
|
+
const serializedValue = await this.serializeData(formattedValue);
|
|
753
|
+
return { key, value: serializedValue, ttl };
|
|
754
|
+
})
|
|
755
|
+
);
|
|
619
756
|
results = await this._store.setMany(serializedEntries);
|
|
620
757
|
}
|
|
621
758
|
} catch (error) {
|
|
@@ -652,7 +789,10 @@ var Keyv = class extends event_manager_default {
|
|
|
652
789
|
throw error;
|
|
653
790
|
}
|
|
654
791
|
}
|
|
655
|
-
this.hooks.trigger("postDelete" /* POST_DELETE */, {
|
|
792
|
+
this.hooks.trigger("postDelete" /* POST_DELETE */, {
|
|
793
|
+
key: keyPrefixed,
|
|
794
|
+
value: result
|
|
795
|
+
});
|
|
656
796
|
this.stats.delete();
|
|
657
797
|
return result;
|
|
658
798
|
}
|
|
@@ -672,7 +812,10 @@ var Keyv = class extends event_manager_default {
|
|
|
672
812
|
const promises = keyPrefixed.map(async (key) => store.delete(key));
|
|
673
813
|
const results = await Promise.all(promises);
|
|
674
814
|
const returnResult = results.every(Boolean);
|
|
675
|
-
this.hooks.trigger("postDelete" /* POST_DELETE */, {
|
|
815
|
+
this.hooks.trigger("postDelete" /* POST_DELETE */, {
|
|
816
|
+
key: keyPrefixed,
|
|
817
|
+
value: returnResult
|
|
818
|
+
});
|
|
676
819
|
return returnResult;
|
|
677
820
|
} catch (error) {
|
|
678
821
|
this.emit("error", error);
|
|
@@ -756,6 +899,7 @@ var Keyv = class extends event_manager_default {
|
|
|
756
899
|
return store.disconnect();
|
|
757
900
|
}
|
|
758
901
|
}
|
|
902
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
759
903
|
emit(event, ...arguments_) {
|
|
760
904
|
if (event === "error" && !this.opts.emitErrors) {
|
|
761
905
|
return;
|
|
@@ -767,7 +911,10 @@ var Keyv = class extends event_manager_default {
|
|
|
767
911
|
return data;
|
|
768
912
|
}
|
|
769
913
|
if (this._compression?.compress) {
|
|
770
|
-
return this._serialize({
|
|
914
|
+
return this._serialize({
|
|
915
|
+
value: await this._compression.compress(data.value),
|
|
916
|
+
expires: data.expires
|
|
917
|
+
});
|
|
771
918
|
}
|
|
772
919
|
return this._serialize(data);
|
|
773
920
|
}
|
|
@@ -777,7 +924,10 @@ var Keyv = class extends event_manager_default {
|
|
|
777
924
|
}
|
|
778
925
|
if (this._compression?.decompress && typeof data === "string") {
|
|
779
926
|
const result = await this._deserialize(data);
|
|
780
|
-
return {
|
|
927
|
+
return {
|
|
928
|
+
value: await this._compression.decompress(result?.value),
|
|
929
|
+
expires: result?.expires
|
|
930
|
+
};
|
|
781
931
|
}
|
|
782
932
|
if (typeof data === "string") {
|
|
783
933
|
return this._deserialize(data);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "keyv",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.5.1",
|
|
4
4
|
"description": "Simple key-value storage with support for multiple backends",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -12,16 +12,6 @@
|
|
|
12
12
|
"import": "./dist/index.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
-
"xo": {
|
|
16
|
-
"rules": {
|
|
17
|
-
"@typescript-eslint/ban-ts-comment": "off",
|
|
18
|
-
"@typescript-eslint/no-unsafe-call": "off",
|
|
19
|
-
"@typescript-eslint/no-unsafe-return": "off",
|
|
20
|
-
"@typescript-eslint/no-unsafe-assignment": "off",
|
|
21
|
-
"@typescript-eslint/no-unsafe-argument": "off",
|
|
22
|
-
"@typescript-eslint/no-confusing-void-expression": "off"
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
15
|
"repository": {
|
|
26
16
|
"type": "git",
|
|
27
17
|
"url": "git+https://github.com/jaredwray/keyv.git"
|
|
@@ -54,23 +44,23 @@
|
|
|
54
44
|
},
|
|
55
45
|
"homepage": "https://github.com/jaredwray/keyv",
|
|
56
46
|
"dependencies": {
|
|
57
|
-
"@keyv/serialize": "^1.1.
|
|
47
|
+
"@keyv/serialize": "^1.1.1"
|
|
58
48
|
},
|
|
59
49
|
"devDependencies": {
|
|
60
|
-
"@
|
|
50
|
+
"@biomejs/biome": "^2.2.3",
|
|
51
|
+
"@faker-js/faker": "^10.0.0",
|
|
61
52
|
"@vitest/coverage-v8": "^3.2.4",
|
|
62
53
|
"rimraf": "^6.0.1",
|
|
63
54
|
"timekeeper": "^2.3.1",
|
|
64
|
-
"tsd": "^0.
|
|
55
|
+
"tsd": "^0.33.0",
|
|
65
56
|
"vitest": "^3.2.4",
|
|
66
|
-
"
|
|
67
|
-
"@keyv/memcache": "^2.0.2",
|
|
68
|
-
"@keyv/compress-gzip": "^2.0.3",
|
|
57
|
+
"@keyv/mongo": "^3.0.3",
|
|
69
58
|
"@keyv/compress-lz4": "^1.0.1",
|
|
59
|
+
"@keyv/memcache": "^2.0.2",
|
|
60
|
+
"@keyv/sqlite": "^4.0.5",
|
|
61
|
+
"@keyv/test-suite": "^2.1.1",
|
|
70
62
|
"@keyv/compress-brotli": "^2.0.5",
|
|
71
|
-
"@keyv/
|
|
72
|
-
"@keyv/test-suite": "^2.0.9",
|
|
73
|
-
"@keyv/sqlite": "^4.0.5"
|
|
63
|
+
"@keyv/compress-gzip": "^2.0.3"
|
|
74
64
|
},
|
|
75
65
|
"tsd": {
|
|
76
66
|
"directory": "test"
|
|
@@ -81,8 +71,8 @@
|
|
|
81
71
|
],
|
|
82
72
|
"scripts": {
|
|
83
73
|
"build": "rimraf ./dist && tsup src/index.ts --format cjs,esm --dts --clean",
|
|
84
|
-
"test": "
|
|
85
|
-
"test:ci": "
|
|
74
|
+
"test": "biome check --write && vitest run --coverage",
|
|
75
|
+
"test:ci": "biome check && vitest --run --sequence.setupFiles=list --coverage",
|
|
86
76
|
"clean": "rimraf ./node_modules ./coverage ./test/testdb.sqlite ./dist"
|
|
87
77
|
}
|
|
88
78
|
}
|