keyv 5.2.3 → 5.3.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 CHANGED
@@ -289,14 +289,30 @@ The following are third-party storage adapters compatible with Keyv:
289
289
 
290
290
  # Compression
291
291
 
292
- Keyv supports `gzip` and `brotli` compression. To enable compression, pass the `compress` option to the constructor.
292
+ Keyv supports `gzip`, `brotli` and `lz4` compression. To enable compression, pass the `compress` option to the constructor.
293
293
 
294
294
  ```js
295
295
  import Keyv from 'keyv';
296
296
  import KeyvGzip from '@keyv/compress-gzip';
297
297
 
298
298
  const keyvGzip = new KeyvGzip();
299
- const keyv = new Keyv({ compression: KeyvGzip });
299
+ const keyv = new Keyv({ compression: keyvGzip });
300
+ ```
301
+
302
+ ```js
303
+ import Keyv from 'keyv';
304
+ import KeyvBrotli from '@keyv/compress-brotli';
305
+
306
+ const keyvBrotli = new KeyvBrotli();
307
+ const keyv = new Keyv({ compression: keyvBrotli });
308
+ ```
309
+
310
+ ```js
311
+ import Keyv from 'keyv';
312
+ import KeyvLz4 from '@keyv/compress-lz4';
313
+
314
+ const keyvLz4 = new KeyvLz4();
315
+ const keyv = new Keyv({ compression: keyvLz4 });
300
316
  ```
301
317
 
302
318
  You can also pass a custom compression function to the `compression` option. Following the pattern of the official compression adapters.
@@ -407,10 +423,18 @@ By default keys are persistent. You can set an expiry TTL in milliseconds.
407
423
 
408
424
  Returns a promise which resolves to `true`.
409
425
 
426
+ ## .setMany(entries)
427
+
428
+ Set multiple values using KeyvEntrys `{ key: string, value: any, ttl?: number }`.
429
+
410
430
  ## .get(key, [options])
411
431
 
412
432
  Returns a promise which resolves to the retrieved value.
413
433
 
434
+ ## .getMany(keys, [options])
435
+
436
+ Returns a promise which resolves to an array of retrieved values.
437
+
414
438
  ### options.raw
415
439
 
416
440
  Type: `Boolean`<br />
@@ -426,6 +450,10 @@ Deletes an entry.
426
450
 
427
451
  Returns a promise which resolves to `true` if the key existed, `false` if not.
428
452
 
453
+ ## .deleteMany(keys)
454
+ Deletes multiple entries.
455
+ Returns a promise which resolves to an array of booleans indicating if the key existed or not.
456
+
429
457
  ## .clear()
430
458
 
431
459
  Delete all entries in the current namespace.
package/dist/index.cjs CHANGED
@@ -18,13 +18,13 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
 
20
20
  // src/index.ts
21
- var src_exports = {};
22
- __export(src_exports, {
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
23
  Keyv: () => Keyv,
24
24
  KeyvHooks: () => KeyvHooks,
25
- default: () => src_default
25
+ default: () => index_default
26
26
  });
27
- module.exports = __toCommonJS(src_exports);
27
+ module.exports = __toCommonJS(index_exports);
28
28
  var import_serialize = require("@keyv/serialize");
29
29
 
30
30
  // src/event-manager.ts
@@ -488,52 +488,10 @@ var Keyv = class extends event_manager_default {
488
488
  const keyPrefixed = isArray ? this._getKeyPrefixArray(key) : this._getKeyPrefix(key);
489
489
  const isDataExpired = (data) => typeof data.expires === "number" && Date.now() > data.expires;
490
490
  if (isArray) {
491
- this.hooks.trigger("preGetMany" /* PRE_GET_MANY */, { keys: keyPrefixed });
492
- if (store.getMany === void 0) {
493
- const promises = keyPrefixed.map(async (key2) => {
494
- const rawData3 = await store.get(key2);
495
- const deserializedRow = typeof rawData3 === "string" || this.opts.compression ? await this.deserializeData(rawData3) : rawData3;
496
- if (deserializedRow === void 0 || deserializedRow === null) {
497
- return void 0;
498
- }
499
- if (isDataExpired(deserializedRow)) {
500
- await this.delete(key2);
501
- return void 0;
502
- }
503
- return options?.raw ? deserializedRow : deserializedRow.value;
504
- });
505
- const deserializedRows = await Promise.allSettled(promises);
506
- const result2 = deserializedRows.map((row) => row.value);
507
- this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result2);
508
- if (result2.length > 0) {
509
- this.stats.hit();
510
- }
511
- return result2;
512
- }
513
- const rawData2 = await store.getMany(keyPrefixed);
514
- const result = [];
515
- for (const index in rawData2) {
516
- let row = rawData2[index];
517
- if (typeof row === "string") {
518
- row = await this.deserializeData(row);
519
- }
520
- if (row === void 0 || row === null) {
521
- result.push(void 0);
522
- continue;
523
- }
524
- if (isDataExpired(row)) {
525
- await this.delete(key[index]);
526
- result.push(void 0);
527
- continue;
528
- }
529
- const value = options?.raw ? row : row.value;
530
- result.push(value);
491
+ if (options?.raw === true) {
492
+ return this.getMany(key, { raw: true });
531
493
  }
532
- this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result);
533
- if (result.length > 0) {
534
- this.stats.hit();
535
- }
536
- return result;
494
+ return this.getMany(key, { raw: false });
537
495
  }
538
496
  this.hooks.trigger("preGet" /* PRE_GET */, { key: keyPrefixed });
539
497
  const rawData = await store.get(keyPrefixed);
@@ -551,9 +509,60 @@ var Keyv = class extends event_manager_default {
551
509
  this.stats.hit();
552
510
  return options?.raw ? deserializedData : deserializedData.value;
553
511
  }
512
+ async getMany(keys, options) {
513
+ const { store } = this.opts;
514
+ const keyPrefixed = this._getKeyPrefixArray(keys);
515
+ const isDataExpired = (data) => typeof data.expires === "number" && Date.now() > data.expires;
516
+ this.hooks.trigger("preGetMany" /* PRE_GET_MANY */, { keys: keyPrefixed });
517
+ if (store.getMany === void 0) {
518
+ const promises = keyPrefixed.map(async (key) => {
519
+ const rawData2 = await store.get(key);
520
+ const deserializedRow = typeof rawData2 === "string" || this.opts.compression ? await this.deserializeData(rawData2) : rawData2;
521
+ if (deserializedRow === void 0 || deserializedRow === null) {
522
+ return void 0;
523
+ }
524
+ if (isDataExpired(deserializedRow)) {
525
+ await this.delete(key);
526
+ return void 0;
527
+ }
528
+ return options?.raw ? deserializedRow : deserializedRow.value;
529
+ });
530
+ const deserializedRows = await Promise.allSettled(promises);
531
+ const result2 = deserializedRows.map((row) => row.value);
532
+ this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result2);
533
+ if (result2.length > 0) {
534
+ this.stats.hit();
535
+ }
536
+ return result2;
537
+ }
538
+ const rawData = await store.getMany(keyPrefixed);
539
+ const result = [];
540
+ for (const index in rawData) {
541
+ let row = rawData[index];
542
+ if (typeof row === "string") {
543
+ row = await this.deserializeData(row);
544
+ }
545
+ if (row === void 0 || row === null) {
546
+ result.push(void 0);
547
+ continue;
548
+ }
549
+ if (isDataExpired(row)) {
550
+ await this.delete(keys[index]);
551
+ result.push(void 0);
552
+ continue;
553
+ }
554
+ const value = options?.raw ? row : row.value;
555
+ result.push(value);
556
+ }
557
+ this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result);
558
+ if (result.length > 0) {
559
+ this.stats.hit();
560
+ }
561
+ return result;
562
+ }
554
563
  /**
555
564
  * Set an item to the store
556
- * @param {string} key the key to use
565
+ * @param {string | Array<KeyvEntry>} key the key to use. If you pass in an array of KeyvEntry it will set many items
557
566
  * @param {Value} value the value of the key
558
567
  * @param {number} [ttl] time to live in milliseconds
559
568
  * @returns {boolean} if it sets then it will return a true. On failure will return false.
@@ -561,7 +570,7 @@ var Keyv = class extends event_manager_default {
561
570
  async set(key, value, ttl) {
562
571
  this.hooks.trigger("preSet" /* PRE_SET */, { key, value, ttl });
563
572
  const keyPrefixed = this._getKeyPrefix(key);
564
- if (typeof ttl === "undefined") {
573
+ if (ttl === void 0) {
565
574
  ttl = this._ttl;
566
575
  }
567
576
  if (ttl === 0) {
@@ -588,6 +597,30 @@ var Keyv = class extends event_manager_default {
588
597
  this.stats.set();
589
598
  return result;
590
599
  }
600
+ /**
601
+ * Set many items to the store
602
+ * @param {Array<KeyvEntry>} entries the entries to set
603
+ * @returns {boolean[]} will return an array of booleans if it sets then it will return a true. On failure will return false.
604
+ */
605
+ async setMany(entries) {
606
+ let results = [];
607
+ try {
608
+ if (this._store.setMany !== void 0) {
609
+ results = await this._store.setMany(entries);
610
+ return results;
611
+ }
612
+ const promises = [];
613
+ for (const entry of entries) {
614
+ promises.push(this.set(entry.key, entry.value, entry.ttl));
615
+ }
616
+ const promiseResults = await Promise.allSettled(promises);
617
+ results = promiseResults.map((result) => result.value);
618
+ } catch (error) {
619
+ this.emit("error", error);
620
+ results = entries.map(() => false);
621
+ }
622
+ return results;
623
+ }
591
624
  /**
592
625
  * Delete an Entry
593
626
  * @param {string | string[]} key the key to be deleted. if an array it will delete many items
@@ -596,16 +629,7 @@ var Keyv = class extends event_manager_default {
596
629
  async delete(key) {
597
630
  const { store } = this.opts;
598
631
  if (Array.isArray(key)) {
599
- const keyPrefixed2 = this._getKeyPrefixArray(key);
600
- this.hooks.trigger("preDelete" /* PRE_DELETE */, { key: keyPrefixed2 });
601
- if (store.deleteMany !== void 0) {
602
- return store.deleteMany(keyPrefixed2);
603
- }
604
- const promises = keyPrefixed2.map(async (key2) => store.delete(key2));
605
- const results = await Promise.allSettled(promises);
606
- const returnResult = results.every((x) => x.value === true);
607
- this.hooks.trigger("postDelete" /* POST_DELETE */, { key: keyPrefixed2, value: returnResult });
608
- return returnResult;
632
+ return this.deleteMany(key);
609
633
  }
610
634
  const keyPrefixed = this._getKeyPrefix(key);
611
635
  this.hooks.trigger("preDelete" /* PRE_DELETE */, { key: keyPrefixed });
@@ -623,6 +647,29 @@ var Keyv = class extends event_manager_default {
623
647
  this.stats.delete();
624
648
  return result;
625
649
  }
650
+ /**
651
+ * Delete many items from the store
652
+ * @param {string[]} keys the keys to be deleted
653
+ * @returns {boolean} will return true if item or items are deleted. false if there is an error
654
+ */
655
+ async deleteMany(keys) {
656
+ try {
657
+ const { store } = this.opts;
658
+ const keyPrefixed = this._getKeyPrefixArray(keys);
659
+ this.hooks.trigger("preDelete" /* PRE_DELETE */, { key: keyPrefixed });
660
+ if (store.deleteMany !== void 0) {
661
+ return await store.deleteMany(keyPrefixed);
662
+ }
663
+ const promises = keyPrefixed.map(async (key) => store.delete(key));
664
+ const results = await Promise.allSettled(promises);
665
+ const returnResult = results.every((x) => x.value === true);
666
+ this.hooks.trigger("postDelete" /* POST_DELETE */, { key: keyPrefixed, value: returnResult });
667
+ return returnResult;
668
+ } catch (error) {
669
+ this.emit("error", error);
670
+ return false;
671
+ }
672
+ }
626
673
  /**
627
674
  * Clear the store
628
675
  * @returns {void}
@@ -636,12 +683,10 @@ var Keyv = class extends event_manager_default {
636
683
  this.emit("error", error);
637
684
  }
638
685
  }
639
- /**
640
- * Has a key
641
- * @param {string} key the key to check
642
- * @returns {boolean} will return true if the key exists
643
- */
644
686
  async has(key) {
687
+ if (Array.isArray(key)) {
688
+ return this.hasMany(key);
689
+ }
645
690
  const keyPrefixed = this._getKeyPrefix(key);
646
691
  const { store } = this.opts;
647
692
  if (store.has !== void 0 && !(store instanceof Map)) {
@@ -664,6 +709,23 @@ var Keyv = class extends event_manager_default {
664
709
  }
665
710
  return false;
666
711
  }
712
+ /**
713
+ * Check if many keys exist
714
+ * @param {string[]} keys the keys to check
715
+ * @returns {boolean[]} will return an array of booleans if the keys exist
716
+ */
717
+ async hasMany(keys) {
718
+ const keyPrefixed = this._getKeyPrefixArray(keys);
719
+ const { store } = this.opts;
720
+ if (store.hasMany !== void 0) {
721
+ return store.hasMany(keyPrefixed);
722
+ }
723
+ const results = [];
724
+ for (const key of keyPrefixed) {
725
+ results.push(await this.has(key));
726
+ }
727
+ return results;
728
+ }
667
729
  /**
668
730
  * Will disconnect the store. This is only available if the store has a disconnect method
669
731
  * @returns {Promise<void>}
@@ -704,7 +766,7 @@ var Keyv = class extends event_manager_default {
704
766
  return void 0;
705
767
  }
706
768
  };
707
- var src_default = Keyv;
769
+ var index_default = Keyv;
708
770
  // Annotate the CommonJS export names for ESM import in node:
709
771
  0 && (module.exports = {
710
772
  Keyv,
package/dist/index.d.cts CHANGED
@@ -44,12 +44,12 @@ type DeserializedData<Value> = {
44
44
  value?: Value;
45
45
  expires?: number | null;
46
46
  };
47
- interface CompressionAdapter {
47
+ type CompressionAdapter = {
48
48
  compress(value: any, options?: any): Promise<any>;
49
49
  decompress(value: any, options?: any): Promise<any>;
50
50
  serialize<Value>(data: DeserializedData<Value>): Promise<string> | string;
51
51
  deserialize<Value>(data: string): Promise<DeserializedData<Value> | undefined> | DeserializedData<Value> | undefined;
52
- }
52
+ };
53
53
  type Serialize = <Value>(data: DeserializedData<Value>) => Promise<string> | string;
54
54
  type Deserialize = <Value>(data: string) => Promise<DeserializedData<Value> | undefined> | DeserializedData<Value> | undefined;
55
55
  declare enum KeyvHooks {
@@ -62,25 +62,45 @@ declare enum KeyvHooks {
62
62
  PRE_DELETE = "preDelete",
63
63
  POST_DELETE = "postDelete"
64
64
  }
65
+ type KeyvEntry = {
66
+ /**
67
+ * Key to set.
68
+ */
69
+ key: string;
70
+ /**
71
+ * Value to set.
72
+ */
73
+ value: any;
74
+ /**
75
+ * Time to live in milliseconds.
76
+ */
77
+ ttl?: number;
78
+ };
65
79
  type StoredDataNoRaw<Value> = Value | undefined;
66
80
  type StoredDataRaw<Value> = DeserializedData<Value> | undefined;
67
81
  type StoredData<Value> = StoredDataNoRaw<Value> | StoredDataRaw<Value>;
68
- interface IEventEmitter {
69
- on(event: string, listener: (...arguments_: any[]) => void): this;
70
- }
71
- interface KeyvStoreAdapter extends IEventEmitter {
82
+ type IEventEmitter = {
83
+ on(event: string, listener: (...arguments_: any[]) => void): IEventEmitter;
84
+ };
85
+ type KeyvStoreAdapter = {
72
86
  opts: any;
73
87
  namespace?: string;
74
88
  get<Value>(key: string): Promise<StoredData<Value> | undefined>;
75
89
  set(key: string, value: any, ttl?: number): any;
90
+ setMany?(values: Array<{
91
+ key: string;
92
+ value: any;
93
+ ttl?: number;
94
+ }>): Promise<void>;
76
95
  delete(key: string): Promise<boolean>;
77
96
  clear(): Promise<void>;
78
97
  has?(key: string): Promise<boolean>;
98
+ hasMany?(keys: string[]): Promise<boolean[]>;
79
99
  getMany?<Value>(keys: string[]): Promise<Array<StoredData<Value | undefined>>>;
80
100
  disconnect?(): Promise<void>;
81
101
  deleteMany?(key: string[]): Promise<boolean>;
82
102
  iterator?<Value>(namespace?: string): AsyncGenerator<Array<string | Awaited<Value> | undefined>, void>;
83
- }
103
+ } & IEventEmitter;
84
104
  type KeyvOptions = {
85
105
  /** Emit errors */
86
106
  emitErrors?: boolean;
@@ -216,7 +236,7 @@ declare class Keyv<GenericValue = any> extends EventManager {
216
236
  /**
217
237
  * Get the Value of a Key
218
238
  * @param {string | string[]} key passing in a single key or multiple as an array
219
- * @param [options] can pass in to return the raw value by setting { raw: true }
239
+ * @param {{raw: boolean} | undefined} options can pass in to return the raw value by setting { raw: true }
220
240
  */
221
241
  get<Value = GenericValue>(key: string, options?: {
222
242
  raw: false;
@@ -230,20 +250,43 @@ declare class Keyv<GenericValue = any> extends EventManager {
230
250
  get<Value = GenericValue>(key: string[], options?: {
231
251
  raw: true;
232
252
  }): Promise<Array<StoredDataRaw<Value>>>;
253
+ /**
254
+ * Get many values of keys
255
+ * @param {string[]} keys passing in a single key or multiple as an array
256
+ * @param {{raw: boolean} | undefined} options can pass in to return the raw value by setting { raw: true }
257
+ */
258
+ getMany<Value = GenericValue>(keys: string[], options?: {
259
+ raw: false;
260
+ }): Promise<Array<StoredDataNoRaw<Value>>>;
261
+ getMany<Value = GenericValue>(keys: string[], options?: {
262
+ raw: true;
263
+ }): Promise<Array<StoredDataRaw<Value>>>;
233
264
  /**
234
265
  * Set an item to the store
235
- * @param {string} key the key to use
266
+ * @param {string | Array<KeyvEntry>} key the key to use. If you pass in an array of KeyvEntry it will set many items
236
267
  * @param {Value} value the value of the key
237
268
  * @param {number} [ttl] time to live in milliseconds
238
269
  * @returns {boolean} if it sets then it will return a true. On failure will return false.
239
270
  */
240
271
  set<Value = GenericValue>(key: string, value: Value, ttl?: number): Promise<boolean>;
272
+ /**
273
+ * Set many items to the store
274
+ * @param {Array<KeyvEntry>} entries the entries to set
275
+ * @returns {boolean[]} will return an array of booleans if it sets then it will return a true. On failure will return false.
276
+ */
277
+ setMany<Value = GenericValue>(entries: KeyvEntry[]): Promise<boolean[]>;
241
278
  /**
242
279
  * Delete an Entry
243
280
  * @param {string | string[]} key the key to be deleted. if an array it will delete many items
244
281
  * @returns {boolean} will return true if item or items are deleted. false if there is an error
245
282
  */
246
283
  delete(key: string | string[]): Promise<boolean>;
284
+ /**
285
+ * Delete many items from the store
286
+ * @param {string[]} keys the keys to be deleted
287
+ * @returns {boolean} will return true if item or items are deleted. false if there is an error
288
+ */
289
+ deleteMany(keys: string[]): Promise<boolean>;
247
290
  /**
248
291
  * Clear the store
249
292
  * @returns {void}
@@ -254,7 +297,14 @@ declare class Keyv<GenericValue = any> extends EventManager {
254
297
  * @param {string} key the key to check
255
298
  * @returns {boolean} will return true if the key exists
256
299
  */
300
+ has(key: string[]): Promise<boolean[]>;
257
301
  has(key: string): Promise<boolean>;
302
+ /**
303
+ * Check if many keys exist
304
+ * @param {string[]} keys the keys to check
305
+ * @returns {boolean[]} will return an array of booleans if the keys exist
306
+ */
307
+ hasMany(keys: string[]): Promise<boolean[]>;
258
308
  /**
259
309
  * Will disconnect the store. This is only available if the store has a disconnect method
260
310
  * @returns {Promise<void>}
@@ -265,4 +315,4 @@ declare class Keyv<GenericValue = any> extends EventManager {
265
315
  deserializeData<T>(data: string | DeserializedData<T>): Promise<DeserializedData<T> | undefined>;
266
316
  }
267
317
 
268
- export { type CompressionAdapter, type Deserialize, type DeserializedData, type IEventEmitter, Keyv, KeyvHooks, type KeyvOptions, type KeyvStoreAdapter, type Serialize, type StoredData, type StoredDataNoRaw, type StoredDataRaw, Keyv as default };
318
+ export { type CompressionAdapter, type Deserialize, type DeserializedData, type IEventEmitter, Keyv, type KeyvEntry, KeyvHooks, type KeyvOptions, type KeyvStoreAdapter, type Serialize, type StoredData, type StoredDataNoRaw, type StoredDataRaw, Keyv as default };
package/dist/index.d.ts CHANGED
@@ -44,12 +44,12 @@ type DeserializedData<Value> = {
44
44
  value?: Value;
45
45
  expires?: number | null;
46
46
  };
47
- interface CompressionAdapter {
47
+ type CompressionAdapter = {
48
48
  compress(value: any, options?: any): Promise<any>;
49
49
  decompress(value: any, options?: any): Promise<any>;
50
50
  serialize<Value>(data: DeserializedData<Value>): Promise<string> | string;
51
51
  deserialize<Value>(data: string): Promise<DeserializedData<Value> | undefined> | DeserializedData<Value> | undefined;
52
- }
52
+ };
53
53
  type Serialize = <Value>(data: DeserializedData<Value>) => Promise<string> | string;
54
54
  type Deserialize = <Value>(data: string) => Promise<DeserializedData<Value> | undefined> | DeserializedData<Value> | undefined;
55
55
  declare enum KeyvHooks {
@@ -62,25 +62,45 @@ declare enum KeyvHooks {
62
62
  PRE_DELETE = "preDelete",
63
63
  POST_DELETE = "postDelete"
64
64
  }
65
+ type KeyvEntry = {
66
+ /**
67
+ * Key to set.
68
+ */
69
+ key: string;
70
+ /**
71
+ * Value to set.
72
+ */
73
+ value: any;
74
+ /**
75
+ * Time to live in milliseconds.
76
+ */
77
+ ttl?: number;
78
+ };
65
79
  type StoredDataNoRaw<Value> = Value | undefined;
66
80
  type StoredDataRaw<Value> = DeserializedData<Value> | undefined;
67
81
  type StoredData<Value> = StoredDataNoRaw<Value> | StoredDataRaw<Value>;
68
- interface IEventEmitter {
69
- on(event: string, listener: (...arguments_: any[]) => void): this;
70
- }
71
- interface KeyvStoreAdapter extends IEventEmitter {
82
+ type IEventEmitter = {
83
+ on(event: string, listener: (...arguments_: any[]) => void): IEventEmitter;
84
+ };
85
+ type KeyvStoreAdapter = {
72
86
  opts: any;
73
87
  namespace?: string;
74
88
  get<Value>(key: string): Promise<StoredData<Value> | undefined>;
75
89
  set(key: string, value: any, ttl?: number): any;
90
+ setMany?(values: Array<{
91
+ key: string;
92
+ value: any;
93
+ ttl?: number;
94
+ }>): Promise<void>;
76
95
  delete(key: string): Promise<boolean>;
77
96
  clear(): Promise<void>;
78
97
  has?(key: string): Promise<boolean>;
98
+ hasMany?(keys: string[]): Promise<boolean[]>;
79
99
  getMany?<Value>(keys: string[]): Promise<Array<StoredData<Value | undefined>>>;
80
100
  disconnect?(): Promise<void>;
81
101
  deleteMany?(key: string[]): Promise<boolean>;
82
102
  iterator?<Value>(namespace?: string): AsyncGenerator<Array<string | Awaited<Value> | undefined>, void>;
83
- }
103
+ } & IEventEmitter;
84
104
  type KeyvOptions = {
85
105
  /** Emit errors */
86
106
  emitErrors?: boolean;
@@ -216,7 +236,7 @@ declare class Keyv<GenericValue = any> extends EventManager {
216
236
  /**
217
237
  * Get the Value of a Key
218
238
  * @param {string | string[]} key passing in a single key or multiple as an array
219
- * @param [options] can pass in to return the raw value by setting { raw: true }
239
+ * @param {{raw: boolean} | undefined} options can pass in to return the raw value by setting { raw: true }
220
240
  */
221
241
  get<Value = GenericValue>(key: string, options?: {
222
242
  raw: false;
@@ -230,20 +250,43 @@ declare class Keyv<GenericValue = any> extends EventManager {
230
250
  get<Value = GenericValue>(key: string[], options?: {
231
251
  raw: true;
232
252
  }): Promise<Array<StoredDataRaw<Value>>>;
253
+ /**
254
+ * Get many values of keys
255
+ * @param {string[]} keys passing in a single key or multiple as an array
256
+ * @param {{raw: boolean} | undefined} options can pass in to return the raw value by setting { raw: true }
257
+ */
258
+ getMany<Value = GenericValue>(keys: string[], options?: {
259
+ raw: false;
260
+ }): Promise<Array<StoredDataNoRaw<Value>>>;
261
+ getMany<Value = GenericValue>(keys: string[], options?: {
262
+ raw: true;
263
+ }): Promise<Array<StoredDataRaw<Value>>>;
233
264
  /**
234
265
  * Set an item to the store
235
- * @param {string} key the key to use
266
+ * @param {string | Array<KeyvEntry>} key the key to use. If you pass in an array of KeyvEntry it will set many items
236
267
  * @param {Value} value the value of the key
237
268
  * @param {number} [ttl] time to live in milliseconds
238
269
  * @returns {boolean} if it sets then it will return a true. On failure will return false.
239
270
  */
240
271
  set<Value = GenericValue>(key: string, value: Value, ttl?: number): Promise<boolean>;
272
+ /**
273
+ * Set many items to the store
274
+ * @param {Array<KeyvEntry>} entries the entries to set
275
+ * @returns {boolean[]} will return an array of booleans if it sets then it will return a true. On failure will return false.
276
+ */
277
+ setMany<Value = GenericValue>(entries: KeyvEntry[]): Promise<boolean[]>;
241
278
  /**
242
279
  * Delete an Entry
243
280
  * @param {string | string[]} key the key to be deleted. if an array it will delete many items
244
281
  * @returns {boolean} will return true if item or items are deleted. false if there is an error
245
282
  */
246
283
  delete(key: string | string[]): Promise<boolean>;
284
+ /**
285
+ * Delete many items from the store
286
+ * @param {string[]} keys the keys to be deleted
287
+ * @returns {boolean} will return true if item or items are deleted. false if there is an error
288
+ */
289
+ deleteMany(keys: string[]): Promise<boolean>;
247
290
  /**
248
291
  * Clear the store
249
292
  * @returns {void}
@@ -254,7 +297,14 @@ declare class Keyv<GenericValue = any> extends EventManager {
254
297
  * @param {string} key the key to check
255
298
  * @returns {boolean} will return true if the key exists
256
299
  */
300
+ has(key: string[]): Promise<boolean[]>;
257
301
  has(key: string): Promise<boolean>;
302
+ /**
303
+ * Check if many keys exist
304
+ * @param {string[]} keys the keys to check
305
+ * @returns {boolean[]} will return an array of booleans if the keys exist
306
+ */
307
+ hasMany(keys: string[]): Promise<boolean[]>;
258
308
  /**
259
309
  * Will disconnect the store. This is only available if the store has a disconnect method
260
310
  * @returns {Promise<void>}
@@ -265,4 +315,4 @@ declare class Keyv<GenericValue = any> extends EventManager {
265
315
  deserializeData<T>(data: string | DeserializedData<T>): Promise<DeserializedData<T> | undefined>;
266
316
  }
267
317
 
268
- export { type CompressionAdapter, type Deserialize, type DeserializedData, type IEventEmitter, Keyv, KeyvHooks, type KeyvOptions, type KeyvStoreAdapter, type Serialize, type StoredData, type StoredDataNoRaw, type StoredDataRaw, Keyv as default };
318
+ export { type CompressionAdapter, type Deserialize, type DeserializedData, type IEventEmitter, Keyv, type KeyvEntry, KeyvHooks, type KeyvOptions, type KeyvStoreAdapter, type Serialize, type StoredData, type StoredDataNoRaw, type StoredDataRaw, Keyv as default };
package/dist/index.js CHANGED
@@ -462,52 +462,10 @@ var Keyv = class extends event_manager_default {
462
462
  const keyPrefixed = isArray ? this._getKeyPrefixArray(key) : this._getKeyPrefix(key);
463
463
  const isDataExpired = (data) => typeof data.expires === "number" && Date.now() > data.expires;
464
464
  if (isArray) {
465
- this.hooks.trigger("preGetMany" /* PRE_GET_MANY */, { keys: keyPrefixed });
466
- if (store.getMany === void 0) {
467
- const promises = keyPrefixed.map(async (key2) => {
468
- const rawData3 = await store.get(key2);
469
- const deserializedRow = typeof rawData3 === "string" || this.opts.compression ? await this.deserializeData(rawData3) : rawData3;
470
- if (deserializedRow === void 0 || deserializedRow === null) {
471
- return void 0;
472
- }
473
- if (isDataExpired(deserializedRow)) {
474
- await this.delete(key2);
475
- return void 0;
476
- }
477
- return options?.raw ? deserializedRow : deserializedRow.value;
478
- });
479
- const deserializedRows = await Promise.allSettled(promises);
480
- const result2 = deserializedRows.map((row) => row.value);
481
- this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result2);
482
- if (result2.length > 0) {
483
- this.stats.hit();
484
- }
485
- return result2;
486
- }
487
- const rawData2 = await store.getMany(keyPrefixed);
488
- const result = [];
489
- for (const index in rawData2) {
490
- let row = rawData2[index];
491
- if (typeof row === "string") {
492
- row = await this.deserializeData(row);
493
- }
494
- if (row === void 0 || row === null) {
495
- result.push(void 0);
496
- continue;
497
- }
498
- if (isDataExpired(row)) {
499
- await this.delete(key[index]);
500
- result.push(void 0);
501
- continue;
502
- }
503
- const value = options?.raw ? row : row.value;
504
- result.push(value);
465
+ if (options?.raw === true) {
466
+ return this.getMany(key, { raw: true });
505
467
  }
506
- this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result);
507
- if (result.length > 0) {
508
- this.stats.hit();
509
- }
510
- return result;
468
+ return this.getMany(key, { raw: false });
511
469
  }
512
470
  this.hooks.trigger("preGet" /* PRE_GET */, { key: keyPrefixed });
513
471
  const rawData = await store.get(keyPrefixed);
@@ -525,9 +483,60 @@ var Keyv = class extends event_manager_default {
525
483
  this.stats.hit();
526
484
  return options?.raw ? deserializedData : deserializedData.value;
527
485
  }
486
+ async getMany(keys, options) {
487
+ const { store } = this.opts;
488
+ const keyPrefixed = this._getKeyPrefixArray(keys);
489
+ const isDataExpired = (data) => typeof data.expires === "number" && Date.now() > data.expires;
490
+ this.hooks.trigger("preGetMany" /* PRE_GET_MANY */, { keys: keyPrefixed });
491
+ if (store.getMany === void 0) {
492
+ const promises = keyPrefixed.map(async (key) => {
493
+ const rawData2 = await store.get(key);
494
+ const deserializedRow = typeof rawData2 === "string" || this.opts.compression ? await this.deserializeData(rawData2) : rawData2;
495
+ if (deserializedRow === void 0 || deserializedRow === null) {
496
+ return void 0;
497
+ }
498
+ if (isDataExpired(deserializedRow)) {
499
+ await this.delete(key);
500
+ return void 0;
501
+ }
502
+ return options?.raw ? deserializedRow : deserializedRow.value;
503
+ });
504
+ const deserializedRows = await Promise.allSettled(promises);
505
+ const result2 = deserializedRows.map((row) => row.value);
506
+ this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result2);
507
+ if (result2.length > 0) {
508
+ this.stats.hit();
509
+ }
510
+ return result2;
511
+ }
512
+ const rawData = await store.getMany(keyPrefixed);
513
+ const result = [];
514
+ for (const index in rawData) {
515
+ let row = rawData[index];
516
+ if (typeof row === "string") {
517
+ row = await this.deserializeData(row);
518
+ }
519
+ if (row === void 0 || row === null) {
520
+ result.push(void 0);
521
+ continue;
522
+ }
523
+ if (isDataExpired(row)) {
524
+ await this.delete(keys[index]);
525
+ result.push(void 0);
526
+ continue;
527
+ }
528
+ const value = options?.raw ? row : row.value;
529
+ result.push(value);
530
+ }
531
+ this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result);
532
+ if (result.length > 0) {
533
+ this.stats.hit();
534
+ }
535
+ return result;
536
+ }
528
537
  /**
529
538
  * Set an item to the store
530
- * @param {string} key the key to use
539
+ * @param {string | Array<KeyvEntry>} key the key to use. If you pass in an array of KeyvEntry it will set many items
531
540
  * @param {Value} value the value of the key
532
541
  * @param {number} [ttl] time to live in milliseconds
533
542
  * @returns {boolean} if it sets then it will return a true. On failure will return false.
@@ -535,7 +544,7 @@ var Keyv = class extends event_manager_default {
535
544
  async set(key, value, ttl) {
536
545
  this.hooks.trigger("preSet" /* PRE_SET */, { key, value, ttl });
537
546
  const keyPrefixed = this._getKeyPrefix(key);
538
- if (typeof ttl === "undefined") {
547
+ if (ttl === void 0) {
539
548
  ttl = this._ttl;
540
549
  }
541
550
  if (ttl === 0) {
@@ -562,6 +571,30 @@ var Keyv = class extends event_manager_default {
562
571
  this.stats.set();
563
572
  return result;
564
573
  }
574
+ /**
575
+ * Set many items to the store
576
+ * @param {Array<KeyvEntry>} entries the entries to set
577
+ * @returns {boolean[]} will return an array of booleans if it sets then it will return a true. On failure will return false.
578
+ */
579
+ async setMany(entries) {
580
+ let results = [];
581
+ try {
582
+ if (this._store.setMany !== void 0) {
583
+ results = await this._store.setMany(entries);
584
+ return results;
585
+ }
586
+ const promises = [];
587
+ for (const entry of entries) {
588
+ promises.push(this.set(entry.key, entry.value, entry.ttl));
589
+ }
590
+ const promiseResults = await Promise.allSettled(promises);
591
+ results = promiseResults.map((result) => result.value);
592
+ } catch (error) {
593
+ this.emit("error", error);
594
+ results = entries.map(() => false);
595
+ }
596
+ return results;
597
+ }
565
598
  /**
566
599
  * Delete an Entry
567
600
  * @param {string | string[]} key the key to be deleted. if an array it will delete many items
@@ -570,16 +603,7 @@ var Keyv = class extends event_manager_default {
570
603
  async delete(key) {
571
604
  const { store } = this.opts;
572
605
  if (Array.isArray(key)) {
573
- const keyPrefixed2 = this._getKeyPrefixArray(key);
574
- this.hooks.trigger("preDelete" /* PRE_DELETE */, { key: keyPrefixed2 });
575
- if (store.deleteMany !== void 0) {
576
- return store.deleteMany(keyPrefixed2);
577
- }
578
- const promises = keyPrefixed2.map(async (key2) => store.delete(key2));
579
- const results = await Promise.allSettled(promises);
580
- const returnResult = results.every((x) => x.value === true);
581
- this.hooks.trigger("postDelete" /* POST_DELETE */, { key: keyPrefixed2, value: returnResult });
582
- return returnResult;
606
+ return this.deleteMany(key);
583
607
  }
584
608
  const keyPrefixed = this._getKeyPrefix(key);
585
609
  this.hooks.trigger("preDelete" /* PRE_DELETE */, { key: keyPrefixed });
@@ -597,6 +621,29 @@ var Keyv = class extends event_manager_default {
597
621
  this.stats.delete();
598
622
  return result;
599
623
  }
624
+ /**
625
+ * Delete many items from the store
626
+ * @param {string[]} keys the keys to be deleted
627
+ * @returns {boolean} will return true if item or items are deleted. false if there is an error
628
+ */
629
+ async deleteMany(keys) {
630
+ try {
631
+ const { store } = this.opts;
632
+ const keyPrefixed = this._getKeyPrefixArray(keys);
633
+ this.hooks.trigger("preDelete" /* PRE_DELETE */, { key: keyPrefixed });
634
+ if (store.deleteMany !== void 0) {
635
+ return await store.deleteMany(keyPrefixed);
636
+ }
637
+ const promises = keyPrefixed.map(async (key) => store.delete(key));
638
+ const results = await Promise.allSettled(promises);
639
+ const returnResult = results.every((x) => x.value === true);
640
+ this.hooks.trigger("postDelete" /* POST_DELETE */, { key: keyPrefixed, value: returnResult });
641
+ return returnResult;
642
+ } catch (error) {
643
+ this.emit("error", error);
644
+ return false;
645
+ }
646
+ }
600
647
  /**
601
648
  * Clear the store
602
649
  * @returns {void}
@@ -610,12 +657,10 @@ var Keyv = class extends event_manager_default {
610
657
  this.emit("error", error);
611
658
  }
612
659
  }
613
- /**
614
- * Has a key
615
- * @param {string} key the key to check
616
- * @returns {boolean} will return true if the key exists
617
- */
618
660
  async has(key) {
661
+ if (Array.isArray(key)) {
662
+ return this.hasMany(key);
663
+ }
619
664
  const keyPrefixed = this._getKeyPrefix(key);
620
665
  const { store } = this.opts;
621
666
  if (store.has !== void 0 && !(store instanceof Map)) {
@@ -638,6 +683,23 @@ var Keyv = class extends event_manager_default {
638
683
  }
639
684
  return false;
640
685
  }
686
+ /**
687
+ * Check if many keys exist
688
+ * @param {string[]} keys the keys to check
689
+ * @returns {boolean[]} will return an array of booleans if the keys exist
690
+ */
691
+ async hasMany(keys) {
692
+ const keyPrefixed = this._getKeyPrefixArray(keys);
693
+ const { store } = this.opts;
694
+ if (store.hasMany !== void 0) {
695
+ return store.hasMany(keyPrefixed);
696
+ }
697
+ const results = [];
698
+ for (const key of keyPrefixed) {
699
+ results.push(await this.has(key));
700
+ }
701
+ return results;
702
+ }
641
703
  /**
642
704
  * Will disconnect the store. This is only available if the store has a disconnect method
643
705
  * @returns {Promise<void>}
@@ -678,9 +740,9 @@ var Keyv = class extends event_manager_default {
678
740
  return void 0;
679
741
  }
680
742
  };
681
- var src_default = Keyv;
743
+ var index_default = Keyv;
682
744
  export {
683
745
  Keyv,
684
746
  KeyvHooks,
685
- src_default as default
747
+ index_default as default
686
748
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keyv",
3
- "version": "5.2.3",
3
+ "version": "5.3.1",
4
4
  "description": "Simple key-value storage with support for multiple backends",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -14,27 +14,12 @@
14
14
  },
15
15
  "xo": {
16
16
  "rules": {
17
- "import/no-named-as-default": "off",
18
- "unicorn/prefer-module": "off",
19
- "unicorn/prefer-node-protocol": "off",
20
- "@typescript-eslint/consistent-type-definitions": "off",
21
- "unicorn/no-typeof-undefined": "off",
22
- "unicorn/prefer-event-target": "off",
23
- "import/no-extraneous-dependencies": "off",
24
- "import/extensions": "off",
25
17
  "@typescript-eslint/ban-ts-comment": "off",
26
18
  "@typescript-eslint/no-unsafe-call": "off",
27
- "@typescript-eslint/no-for-in-array": "off",
28
- "guard-for-in": "off",
29
- "no-await-in-loop": "off",
30
19
  "@typescript-eslint/no-unsafe-return": "off",
31
20
  "@typescript-eslint/no-unsafe-assignment": "off",
32
21
  "@typescript-eslint/no-unsafe-argument": "off",
33
- "@typescript-eslint/naming-convention": "off",
34
- "@typescript-eslint/consistent-type-assertions": "off",
35
- "@typescript-eslint/no-confusing-void-expression": "off",
36
- "@typescript-eslint/no-var-requires": "off",
37
- "@typescript-eslint/prefer-ts-expect-error": "off"
22
+ "@typescript-eslint/no-confusing-void-expression": "off"
38
23
  }
39
24
  },
40
25
  "repository": {
@@ -69,19 +54,23 @@
69
54
  },
70
55
  "homepage": "https://github.com/jaredwray/keyv",
71
56
  "dependencies": {
72
- "@keyv/serialize": "^1.0.2"
57
+ "@keyv/serialize": "^1.0.3"
73
58
  },
74
59
  "devDependencies": {
60
+ "@faker-js/faker": "^9.5.1",
61
+ "@vitest/coverage-v8": "^3.0.7",
75
62
  "rimraf": "^6.0.1",
76
63
  "timekeeper": "^2.3.1",
77
64
  "tsd": "^0.31.2",
65
+ "vitest": "^3.0.7",
78
66
  "xo": "^0.60.0",
79
- "@keyv/compress-brotli": "^2.0.2",
80
67
  "@keyv/compress-gzip": "^2.0.2",
81
- "@keyv/memcache": "^2.0.1",
68
+ "@keyv/compress-brotli": "^2.0.3",
82
69
  "@keyv/mongo": "^3.0.1",
83
- "@keyv/sqlite": "^4.0.1",
84
- "@keyv/test-suite": "^2.0.3"
70
+ "@keyv/compress-lz4": "^1.0.0",
71
+ "@keyv/test-suite": "^2.0.5",
72
+ "@keyv/memcache": "^2.0.1",
73
+ "@keyv/sqlite": "^4.0.1"
85
74
  },
86
75
  "tsd": {
87
76
  "directory": "test"