keyv 6.0.0-alpha.2 → 6.0.0-beta.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/dist/index.js DELETED
@@ -1,972 +0,0 @@
1
- // src/index.ts
2
- import { defaultDeserialize, defaultSerialize } from "@keyv/serialize";
3
-
4
- // src/event-manager.ts
5
- var EventManager = class {
6
- _eventListeners;
7
- _maxListeners;
8
- constructor() {
9
- this._eventListeners = /* @__PURE__ */ new Map();
10
- this._maxListeners = 100;
11
- }
12
- maxListeners() {
13
- return this._maxListeners;
14
- }
15
- // Add an event listener
16
- addListener(event, listener) {
17
- this.on(event, listener);
18
- }
19
- on(event, listener) {
20
- if (!this._eventListeners.has(event)) {
21
- this._eventListeners.set(event, []);
22
- }
23
- const listeners = this._eventListeners.get(event);
24
- if (listeners) {
25
- if (listeners.length >= this._maxListeners) {
26
- console.warn(
27
- `MaxListenersExceededWarning: Possible event memory leak detected. ${listeners.length + 1} ${event} listeners added. Use setMaxListeners() to increase limit.`
28
- );
29
- }
30
- listeners.push(listener);
31
- }
32
- return this;
33
- }
34
- // Remove an event listener
35
- removeListener(event, listener) {
36
- this.off(event, listener);
37
- }
38
- off(event, listener) {
39
- const listeners = this._eventListeners.get(event) ?? [];
40
- const index = listeners.indexOf(listener);
41
- if (index !== -1) {
42
- listeners.splice(index, 1);
43
- }
44
- if (listeners.length === 0) {
45
- this._eventListeners.delete(event);
46
- }
47
- }
48
- once(event, listener) {
49
- const onceListener = (...arguments_) => {
50
- listener(...arguments_);
51
- this.off(event, onceListener);
52
- };
53
- this.on(event, onceListener);
54
- }
55
- // Emit an event
56
- // biome-ignore lint/suspicious/noExplicitAny: type format
57
- emit(event, ...arguments_) {
58
- const listeners = this._eventListeners.get(event);
59
- if (listeners && listeners.length > 0) {
60
- for (const listener of listeners) {
61
- listener(...arguments_);
62
- }
63
- }
64
- }
65
- // Get all listeners for a specific event
66
- listeners(event) {
67
- return this._eventListeners.get(event) ?? [];
68
- }
69
- // Remove all listeners for a specific event
70
- removeAllListeners(event) {
71
- if (event) {
72
- this._eventListeners.delete(event);
73
- } else {
74
- this._eventListeners.clear();
75
- }
76
- }
77
- // Set the maximum number of listeners for a single event
78
- setMaxListeners(n) {
79
- this._maxListeners = n;
80
- }
81
- };
82
- var event_manager_default = EventManager;
83
-
84
- // src/hooks-manager.ts
85
- var HooksManager = class extends event_manager_default {
86
- _hookHandlers;
87
- constructor() {
88
- super();
89
- this._hookHandlers = /* @__PURE__ */ new Map();
90
- }
91
- // Adds a handler function for a specific event
92
- addHandler(event, handler) {
93
- const eventHandlers = this._hookHandlers.get(event);
94
- if (eventHandlers) {
95
- eventHandlers.push(handler);
96
- } else {
97
- this._hookHandlers.set(event, [handler]);
98
- }
99
- }
100
- // Removes a specific handler function for a specific event
101
- removeHandler(event, handler) {
102
- const eventHandlers = this._hookHandlers.get(event);
103
- if (eventHandlers) {
104
- const index = eventHandlers.indexOf(handler);
105
- if (index !== -1) {
106
- eventHandlers.splice(index, 1);
107
- }
108
- }
109
- }
110
- // Triggers all handlers for a specific event with provided data
111
- // biome-ignore lint/suspicious/noExplicitAny: type format
112
- trigger(event, data) {
113
- const eventHandlers = this._hookHandlers.get(event);
114
- if (eventHandlers) {
115
- for (const handler of eventHandlers) {
116
- try {
117
- handler(data);
118
- } catch (error) {
119
- this.emit(
120
- "error",
121
- new Error(
122
- `Error in hook handler for event "${event}": ${error.message}`
123
- )
124
- );
125
- }
126
- }
127
- }
128
- }
129
- // Provides read-only access to the current handlers
130
- get handlers() {
131
- return new Map(this._hookHandlers);
132
- }
133
- };
134
- var hooks_manager_default = HooksManager;
135
-
136
- // src/stats-manager.ts
137
- var StatsManager = class extends event_manager_default {
138
- enabled = true;
139
- hits = 0;
140
- misses = 0;
141
- sets = 0;
142
- deletes = 0;
143
- errors = 0;
144
- constructor(enabled) {
145
- super();
146
- if (enabled !== void 0) {
147
- this.enabled = enabled;
148
- }
149
- this.reset();
150
- }
151
- hit() {
152
- if (this.enabled) {
153
- this.hits++;
154
- }
155
- }
156
- miss() {
157
- if (this.enabled) {
158
- this.misses++;
159
- }
160
- }
161
- set() {
162
- if (this.enabled) {
163
- this.sets++;
164
- }
165
- }
166
- delete() {
167
- if (this.enabled) {
168
- this.deletes++;
169
- }
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
- }
180
- reset() {
181
- this.hits = 0;
182
- this.misses = 0;
183
- this.sets = 0;
184
- this.deletes = 0;
185
- this.errors = 0;
186
- }
187
- };
188
- var stats_manager_default = StatsManager;
189
-
190
- // src/index.ts
191
- var KeyvHooks = /* @__PURE__ */ ((KeyvHooks2) => {
192
- KeyvHooks2["PRE_SET"] = "preSet";
193
- KeyvHooks2["POST_SET"] = "postSet";
194
- KeyvHooks2["PRE_GET"] = "preGet";
195
- KeyvHooks2["POST_GET"] = "postGet";
196
- KeyvHooks2["PRE_GET_MANY"] = "preGetMany";
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";
202
- KeyvHooks2["PRE_DELETE"] = "preDelete";
203
- KeyvHooks2["POST_DELETE"] = "postDelete";
204
- return KeyvHooks2;
205
- })(KeyvHooks || {});
206
- var iterableAdapters = [
207
- "sqlite",
208
- "postgres",
209
- "mysql",
210
- "mongo",
211
- "redis",
212
- "valkey",
213
- "etcd"
214
- ];
215
- var Keyv = class extends event_manager_default {
216
- iterator;
217
- hooks = new hooks_manager_default();
218
- stats = new stats_manager_default(false);
219
- /**
220
- * Time to live in milliseconds
221
- */
222
- _ttl;
223
- /**
224
- * Namespace
225
- */
226
- _namespace;
227
- /**
228
- * Store
229
- */
230
- // biome-ignore lint/suspicious/noExplicitAny: type format
231
- _store = /* @__PURE__ */ new Map();
232
- _serialize = defaultSerialize;
233
- _deserialize = defaultDeserialize;
234
- _compression;
235
- _useKeyPrefix = true;
236
- _throwOnErrors = false;
237
- _emitErrors = true;
238
- /**
239
- * Keyv Constructor
240
- * @param {KeyvStoreAdapter | KeyvOptions} store
241
- * @param {Omit<KeyvOptions, 'store'>} [options] if you provide the store you can then provide the Keyv Options
242
- */
243
- constructor(store, options) {
244
- super();
245
- options ??= {};
246
- store ??= {};
247
- const mergedOptions = {
248
- namespace: "keyv",
249
- serialize: defaultSerialize,
250
- deserialize: defaultDeserialize,
251
- emitErrors: true,
252
- ...options
253
- };
254
- if (store && store.get) {
255
- mergedOptions.store = store;
256
- } else {
257
- Object.assign(mergedOptions, store);
258
- }
259
- this._store = mergedOptions.store ?? /* @__PURE__ */ new Map();
260
- this._compression = mergedOptions.compression;
261
- this._serialize = mergedOptions.serialize;
262
- this._deserialize = mergedOptions.deserialize;
263
- if (mergedOptions.namespace) {
264
- this._namespace = mergedOptions.namespace;
265
- }
266
- if (this._store) {
267
- if (!this._isValidStorageAdapter(this._store)) {
268
- throw new Error("Invalid storage adapter");
269
- }
270
- if (typeof this._store.on === "function") {
271
- this._store.on("error", (error) => this.emit("error", error));
272
- }
273
- this._store.namespace = this._namespace;
274
- if (
275
- // biome-ignore lint/suspicious/noExplicitAny: need to check Map iterator
276
- typeof this._store[Symbol.iterator] === "function" && this._store instanceof Map
277
- ) {
278
- this.iterator = this.generateIterator(
279
- this._store
280
- );
281
- } else if ("iterator" in this._store && this._store.opts && this._checkIterableAdapter()) {
282
- this.iterator = this.generateIterator(
283
- // biome-ignore lint/style/noNonNullAssertion: need to fix
284
- this._store.iterator.bind(this._store)
285
- );
286
- }
287
- }
288
- if (mergedOptions.stats) {
289
- this.stats.enabled = mergedOptions.stats;
290
- }
291
- if (mergedOptions.ttl) {
292
- this._ttl = mergedOptions.ttl;
293
- }
294
- if (mergedOptions.useKeyPrefix !== void 0) {
295
- this._useKeyPrefix = mergedOptions.useKeyPrefix;
296
- }
297
- if (mergedOptions.emitErrors !== void 0) {
298
- this._emitErrors = mergedOptions.emitErrors;
299
- }
300
- if (mergedOptions.throwOnErrors !== void 0) {
301
- this._throwOnErrors = mergedOptions.throwOnErrors;
302
- }
303
- }
304
- /**
305
- * Get the current store
306
- */
307
- // biome-ignore lint/suspicious/noExplicitAny: type format
308
- get store() {
309
- return this._store;
310
- }
311
- /**
312
- * 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.
313
- * @param {KeyvStoreAdapter | Map<any, any> | any} store the store to set
314
- */
315
- // biome-ignore lint/suspicious/noExplicitAny: type format
316
- set store(store) {
317
- if (this._isValidStorageAdapter(store)) {
318
- this._store = store;
319
- if (typeof store.on === "function") {
320
- store.on("error", (error) => this.emit("error", error));
321
- }
322
- if (this._namespace) {
323
- this._store.namespace = this._namespace;
324
- }
325
- if (typeof store[Symbol.iterator] === "function" && store instanceof Map) {
326
- this.iterator = this.generateIterator(
327
- store
328
- );
329
- } else if ("iterator" in store && store.opts && this._checkIterableAdapter()) {
330
- this.iterator = this.generateIterator(store.iterator?.bind(store));
331
- }
332
- } else {
333
- throw new Error("Invalid storage adapter");
334
- }
335
- }
336
- /**
337
- * Get the current compression function
338
- * @returns {CompressionAdapter} The current compression function
339
- */
340
- get compression() {
341
- return this._compression;
342
- }
343
- /**
344
- * Set the current compression function
345
- * @param {CompressionAdapter} compress The compression function to set
346
- */
347
- set compression(compress) {
348
- this._compression = compress;
349
- }
350
- /**
351
- * Get the current namespace.
352
- * @returns {string | undefined} The current namespace.
353
- */
354
- get namespace() {
355
- return this._namespace;
356
- }
357
- /**
358
- * Set the current namespace.
359
- * @param {string | undefined} namespace The namespace to set.
360
- */
361
- set namespace(namespace) {
362
- this._namespace = namespace;
363
- this._store.namespace = namespace;
364
- }
365
- /**
366
- * Get the current TTL.
367
- * @returns {number} The current TTL in milliseconds.
368
- */
369
- get ttl() {
370
- return this._ttl;
371
- }
372
- /**
373
- * Set the current TTL.
374
- * @param {number} ttl The TTL to set in milliseconds.
375
- */
376
- set ttl(ttl) {
377
- this._ttl = ttl;
378
- }
379
- /**
380
- * Get the current serialize function.
381
- * @returns {Serialize} The current serialize function.
382
- */
383
- get serialize() {
384
- return this._serialize;
385
- }
386
- /**
387
- * Set the current serialize function.
388
- * @param {Serialize} serialize The serialize function to set.
389
- */
390
- set serialize(serialize) {
391
- this._serialize = serialize;
392
- }
393
- /**
394
- * Get the current deserialize function.
395
- * @returns {Deserialize} The current deserialize function.
396
- */
397
- get deserialize() {
398
- return this._deserialize;
399
- }
400
- /**
401
- * Set the current deserialize function.
402
- * @param {Deserialize} deserialize The deserialize function to set.
403
- */
404
- set deserialize(deserialize) {
405
- this._deserialize = deserialize;
406
- }
407
- /**
408
- * Get the current useKeyPrefix value. This will enable or disable key prefixing.
409
- * @returns {boolean} The current useKeyPrefix value.
410
- * @default true
411
- */
412
- get useKeyPrefix() {
413
- return this._useKeyPrefix;
414
- }
415
- /**
416
- * Set the current useKeyPrefix value. This will enable or disable key prefixing.
417
- * @param {boolean} value The useKeyPrefix value to set.
418
- */
419
- set useKeyPrefix(value) {
420
- this._useKeyPrefix = value;
421
- }
422
- /**
423
- * Get the current throwErrors value. This will enable or disable throwing errors on methods in addition to emitting them.
424
- * @return {boolean} The current throwOnErrors value.
425
- */
426
- get throwOnErrors() {
427
- return this._throwOnErrors;
428
- }
429
- /**
430
- * Set the current throwOnErrors value. This will enable or disable throwing errors on methods in addition to emitting them.
431
- * @param {boolean} value The throwOnErrors value to set.
432
- */
433
- set throwOnErrors(value) {
434
- this._throwOnErrors = value;
435
- }
436
- /**
437
- * Get the current emitErrors value. This will enable or disable emitting errors on methods.
438
- * @return {boolean} The current emitErrors value.
439
- * @default true
440
- */
441
- get emitErrors() {
442
- return this._emitErrors;
443
- }
444
- /**
445
- * Set the current emitErrors value. This will enable or disable emitting errors on methods.
446
- * @param {boolean} value The emitErrors value to set.
447
- */
448
- set emitErrors(value) {
449
- this._emitErrors = value;
450
- }
451
- generateIterator(iterator) {
452
- const function_ = async function* () {
453
- for await (const [key, raw] of typeof iterator === "function" ? iterator(this._store.namespace) : iterator) {
454
- const data = await this.deserializeData(raw);
455
- if (this._useKeyPrefix && this._store.namespace && !key.includes(this._store.namespace)) {
456
- continue;
457
- }
458
- if (typeof data.expires === "number" && Date.now() > data.expires) {
459
- await this.delete(key);
460
- continue;
461
- }
462
- yield [this._getKeyUnprefix(key), data.value];
463
- }
464
- };
465
- return function_.bind(this);
466
- }
467
- _checkIterableAdapter() {
468
- return iterableAdapters.includes(this._store.opts.dialect) || iterableAdapters.some(
469
- (element) => this._store.opts.url.includes(element)
470
- );
471
- }
472
- _getKeyPrefix(key) {
473
- if (!this._useKeyPrefix) {
474
- return key;
475
- }
476
- if (!this._namespace) {
477
- return key;
478
- }
479
- if (key.startsWith(`${this._namespace}:`)) {
480
- return key;
481
- }
482
- return `${this._namespace}:${key}`;
483
- }
484
- _getKeyPrefixArray(keys) {
485
- if (!this._useKeyPrefix) {
486
- return keys;
487
- }
488
- if (!this._namespace) {
489
- return keys;
490
- }
491
- return keys.map((key) => `${this._namespace}:${key}`);
492
- }
493
- _getKeyUnprefix(key) {
494
- if (!this._useKeyPrefix) {
495
- return key;
496
- }
497
- return key.split(":").splice(1).join(":");
498
- }
499
- // biome-ignore lint/suspicious/noExplicitAny: type format
500
- _isValidStorageAdapter(store) {
501
- return store instanceof Map || typeof store.get === "function" && typeof store.set === "function" && typeof store.delete === "function" && typeof store.clear === "function";
502
- }
503
- // eslint-disable-next-line @stylistic/max-len
504
- async get(key, options) {
505
- const store = this._store;
506
- const isArray = Array.isArray(key);
507
- const keyPrefixed = isArray ? this._getKeyPrefixArray(key) : this._getKeyPrefix(key);
508
- const isDataExpired = (data) => typeof data.expires === "number" && Date.now() > data.expires;
509
- if (isArray) {
510
- if (options?.raw === true) {
511
- return this.getMany(key, { raw: true });
512
- }
513
- return this.getMany(key, { raw: false });
514
- }
515
- this.hooks.trigger("preGet" /* PRE_GET */, { key: keyPrefixed });
516
- let rawData;
517
- try {
518
- rawData = await store.get(keyPrefixed);
519
- } catch (error) {
520
- if (this.throwOnErrors) {
521
- throw error;
522
- }
523
- }
524
- const deserializedData = typeof rawData === "string" || this._compression ? await this.deserializeData(rawData) : rawData;
525
- if (deserializedData === void 0 || deserializedData === null) {
526
- this.hooks.trigger("postGet" /* POST_GET */, {
527
- key: keyPrefixed,
528
- value: void 0
529
- });
530
- this.stats.miss();
531
- return void 0;
532
- }
533
- if (isDataExpired(deserializedData)) {
534
- await this.delete(key);
535
- this.hooks.trigger("postGet" /* POST_GET */, {
536
- key: keyPrefixed,
537
- value: void 0
538
- });
539
- this.stats.miss();
540
- return void 0;
541
- }
542
- this.hooks.trigger("postGet" /* POST_GET */, {
543
- key: keyPrefixed,
544
- value: deserializedData
545
- });
546
- this.stats.hit();
547
- return options?.raw ? deserializedData : deserializedData.value;
548
- }
549
- async getMany(keys, options) {
550
- const store = this._store;
551
- const keyPrefixed = this._getKeyPrefixArray(keys);
552
- const isDataExpired = (data) => typeof data.expires === "number" && Date.now() > data.expires;
553
- this.hooks.trigger("preGetMany" /* PRE_GET_MANY */, { keys: keyPrefixed });
554
- if (store.getMany === void 0) {
555
- const promises = keyPrefixed.map(async (key) => {
556
- const rawData2 = await store.get(key);
557
- const deserializedRow = typeof rawData2 === "string" || this._compression ? await this.deserializeData(rawData2) : rawData2;
558
- if (deserializedRow === void 0 || deserializedRow === null) {
559
- return void 0;
560
- }
561
- if (isDataExpired(deserializedRow)) {
562
- await this.delete(key);
563
- return void 0;
564
- }
565
- return options?.raw ? deserializedRow : deserializedRow.value;
566
- });
567
- const deserializedRows = await Promise.allSettled(promises);
568
- const result2 = deserializedRows.map(
569
- // biome-ignore lint/suspicious/noExplicitAny: type format
570
- (row) => row.value
571
- );
572
- this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result2);
573
- if (result2.length > 0) {
574
- this.stats.hit();
575
- }
576
- return result2;
577
- }
578
- const rawData = await store.getMany(keyPrefixed);
579
- const result = [];
580
- const expiredKeys = [];
581
- for (const index in rawData) {
582
- let row = rawData[index];
583
- if (typeof row === "string") {
584
- row = await this.deserializeData(row);
585
- }
586
- if (row === void 0 || row === null) {
587
- result.push(void 0);
588
- continue;
589
- }
590
- if (isDataExpired(row)) {
591
- expiredKeys.push(keys[index]);
592
- result.push(void 0);
593
- continue;
594
- }
595
- const value = options?.raw ? row : row.value;
596
- result.push(value);
597
- }
598
- if (expiredKeys.length > 0) {
599
- await this.deleteMany(expiredKeys);
600
- }
601
- this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result);
602
- if (result.length > 0) {
603
- this.stats.hit();
604
- }
605
- return result;
606
- }
607
- /**
608
- * Get the raw value of a key. This is the replacement for setting raw to true in the get() method.
609
- * @param {string} key the key to get
610
- * @returns {Promise<StoredDataRaw<Value> | undefined>} will return a StoredDataRaw<Value> or undefined if the key does not exist or is expired.
611
- */
612
- async getRaw(key) {
613
- const store = this._store;
614
- const keyPrefixed = this._getKeyPrefix(key);
615
- this.hooks.trigger("preGetRaw" /* PRE_GET_RAW */, { key: keyPrefixed });
616
- const rawData = await store.get(keyPrefixed);
617
- if (rawData === void 0 || rawData === null) {
618
- this.hooks.trigger("postGetRaw" /* POST_GET_RAW */, {
619
- key: keyPrefixed,
620
- value: void 0
621
- });
622
- this.stats.miss();
623
- return void 0;
624
- }
625
- const deserializedData = typeof rawData === "string" || this._compression ? await this.deserializeData(rawData) : rawData;
626
- if (deserializedData !== void 0 && deserializedData.expires !== void 0 && deserializedData.expires !== null && // biome-ignore lint/style/noNonNullAssertion: need to fix
627
- deserializedData.expires < Date.now()) {
628
- this.hooks.trigger("postGetRaw" /* POST_GET_RAW */, {
629
- key: keyPrefixed,
630
- value: void 0
631
- });
632
- this.stats.miss();
633
- await this.delete(key);
634
- return void 0;
635
- }
636
- this.stats.hit();
637
- this.hooks.trigger("postGetRaw" /* POST_GET_RAW */, {
638
- key: keyPrefixed,
639
- value: deserializedData
640
- });
641
- return deserializedData;
642
- }
643
- /**
644
- * Get the raw values of many keys. This is the replacement for setting raw to true in the getMany() method.
645
- * @param {string[]} keys the keys to get
646
- * @returns {Promise<Array<StoredDataRaw<Value>>>} will return an array of StoredDataRaw<Value> or undefined if the key does not exist or is expired.
647
- */
648
- async getManyRaw(keys) {
649
- const store = this._store;
650
- const keyPrefixed = this._getKeyPrefixArray(keys);
651
- if (keys.length === 0) {
652
- const result2 = Array.from({ length: keys.length }).fill(
653
- void 0
654
- );
655
- this.stats.misses += keys.length;
656
- this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, {
657
- keys: keyPrefixed,
658
- values: result2
659
- });
660
- return result2;
661
- }
662
- let result = [];
663
- if (store.getMany === void 0) {
664
- const promises = keyPrefixed.map(async (key) => {
665
- const rawData = await store.get(key);
666
- if (rawData !== void 0 && rawData !== null) {
667
- return this.deserializeData(rawData);
668
- }
669
- return void 0;
670
- });
671
- const deserializedRows = await Promise.allSettled(promises);
672
- result = deserializedRows.map(
673
- // biome-ignore lint/suspicious/noExplicitAny: type format
674
- (row) => row.value
675
- );
676
- } else {
677
- const rawData = await store.getMany(keyPrefixed);
678
- for (const row of rawData) {
679
- if (row !== void 0 && row !== null) {
680
- result.push(await this.deserializeData(row));
681
- } else {
682
- result.push(void 0);
683
- }
684
- }
685
- }
686
- const expiredKeys = [];
687
- const isDataExpired = (data) => typeof data.expires === "number" && Date.now() > data.expires;
688
- for (const [index, row] of result.entries()) {
689
- if (row !== void 0 && isDataExpired(row)) {
690
- expiredKeys.push(keyPrefixed[index]);
691
- result[index] = void 0;
692
- }
693
- }
694
- if (expiredKeys.length > 0) {
695
- await this.deleteMany(expiredKeys);
696
- }
697
- this.stats.hitsOrMisses(result);
698
- this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, {
699
- keys: keyPrefixed,
700
- values: result
701
- });
702
- return result;
703
- }
704
- /**
705
- * Set an item to the store
706
- * @param {string | Array<KeyvEntry>} key the key to use. If you pass in an array of KeyvEntry it will set many items
707
- * @param {Value} value the value of the key
708
- * @param {number} [ttl] time to live in milliseconds
709
- * @returns {boolean} if it sets then it will return a true. On failure will return false.
710
- */
711
- async set(key, value, ttl) {
712
- const data = { key, value, ttl };
713
- this.hooks.trigger("preSet" /* PRE_SET */, data);
714
- const keyPrefixed = this._getKeyPrefix(data.key);
715
- data.ttl ??= this._ttl;
716
- if (data.ttl === 0) {
717
- data.ttl = void 0;
718
- }
719
- const store = this._store;
720
- const expires = typeof data.ttl === "number" ? Date.now() + data.ttl : void 0;
721
- if (typeof data.value === "symbol") {
722
- this.emit("error", "symbol cannot be serialized");
723
- throw new Error("symbol cannot be serialized");
724
- }
725
- const formattedValue = { value: data.value, expires };
726
- const serializedValue = await this.serializeData(formattedValue);
727
- let result = true;
728
- try {
729
- const value2 = await store.set(keyPrefixed, serializedValue, data.ttl);
730
- if (typeof value2 === "boolean") {
731
- result = value2;
732
- }
733
- } catch (error) {
734
- result = false;
735
- this.emit("error", error);
736
- if (this._throwOnErrors) {
737
- throw error;
738
- }
739
- }
740
- this.hooks.trigger("postSet" /* POST_SET */, {
741
- key: keyPrefixed,
742
- value: serializedValue,
743
- ttl
744
- });
745
- this.stats.set();
746
- return result;
747
- }
748
- /**
749
- * Set many items to the store
750
- * @param {Array<KeyvEntry>} entries the entries to set
751
- * @returns {boolean[]} will return an array of booleans if it sets then it will return a true. On failure will return false.
752
- */
753
- // biome-ignore lint/correctness/noUnusedVariables: type format
754
- async setMany(entries) {
755
- let results = [];
756
- try {
757
- if (this._store.setMany === void 0) {
758
- const promises = [];
759
- for (const entry of entries) {
760
- promises.push(this.set(entry.key, entry.value, entry.ttl));
761
- }
762
- const promiseResults = await Promise.all(promises);
763
- results = promiseResults;
764
- } else {
765
- const serializedEntries = await Promise.all(
766
- entries.map(async ({ key, value, ttl }) => {
767
- ttl ??= this._ttl;
768
- if (ttl === 0) {
769
- ttl = void 0;
770
- }
771
- const expires = typeof ttl === "number" ? Date.now() + ttl : void 0;
772
- if (typeof value === "symbol") {
773
- this.emit("error", "symbol cannot be serialized");
774
- throw new Error("symbol cannot be serialized");
775
- }
776
- const formattedValue = { value, expires };
777
- const serializedValue = await this.serializeData(formattedValue);
778
- const keyPrefixed = this._getKeyPrefix(key);
779
- return { key: keyPrefixed, value: serializedValue, ttl };
780
- })
781
- );
782
- results = await this._store.setMany(
783
- serializedEntries
784
- );
785
- }
786
- } catch (error) {
787
- this.emit("error", error);
788
- if (this._throwOnErrors) {
789
- throw error;
790
- }
791
- results = entries.map(() => false);
792
- }
793
- return results;
794
- }
795
- /**
796
- * Delete an Entry
797
- * @param {string | string[]} key the key to be deleted. if an array it will delete many items
798
- * @returns {boolean} will return true if item or items are deleted. false if there is an error
799
- */
800
- async delete(key) {
801
- const store = this._store;
802
- if (Array.isArray(key)) {
803
- return this.deleteMany(key);
804
- }
805
- const keyPrefixed = this._getKeyPrefix(key);
806
- this.hooks.trigger("preDelete" /* PRE_DELETE */, { key: keyPrefixed });
807
- let result = true;
808
- try {
809
- const value = await store.delete(keyPrefixed);
810
- if (typeof value === "boolean") {
811
- result = value;
812
- }
813
- } catch (error) {
814
- result = false;
815
- this.emit("error", error);
816
- if (this._throwOnErrors) {
817
- throw error;
818
- }
819
- }
820
- this.hooks.trigger("postDelete" /* POST_DELETE */, {
821
- key: keyPrefixed,
822
- value: result
823
- });
824
- this.stats.delete();
825
- return result;
826
- }
827
- /**
828
- * Delete many items from the store
829
- * @param {string[]} keys the keys to be deleted
830
- * @returns {boolean} will return true if item or items are deleted. false if there is an error
831
- */
832
- async deleteMany(keys) {
833
- try {
834
- const store = this._store;
835
- const keyPrefixed = this._getKeyPrefixArray(keys);
836
- this.hooks.trigger("preDelete" /* PRE_DELETE */, { key: keyPrefixed });
837
- if (store.deleteMany !== void 0) {
838
- return await store.deleteMany(keyPrefixed);
839
- }
840
- const promises = keyPrefixed.map(async (key) => store.delete(key));
841
- const results = await Promise.all(promises);
842
- const returnResult = results.every(Boolean);
843
- this.hooks.trigger("postDelete" /* POST_DELETE */, {
844
- key: keyPrefixed,
845
- value: returnResult
846
- });
847
- return returnResult;
848
- } catch (error) {
849
- this.emit("error", error);
850
- if (this._throwOnErrors) {
851
- throw error;
852
- }
853
- return false;
854
- }
855
- }
856
- /**
857
- * Clear the store
858
- * @returns {void}
859
- */
860
- async clear() {
861
- this.emit("clear");
862
- const store = this._store;
863
- try {
864
- await store.clear();
865
- } catch (error) {
866
- this.emit("error", error);
867
- if (this._throwOnErrors) {
868
- throw error;
869
- }
870
- }
871
- }
872
- async has(key) {
873
- if (Array.isArray(key)) {
874
- return this.hasMany(key);
875
- }
876
- const keyPrefixed = this._getKeyPrefix(key);
877
- const store = this._store;
878
- if (store.has !== void 0 && !(store instanceof Map)) {
879
- return store.has(keyPrefixed);
880
- }
881
- let rawData;
882
- try {
883
- rawData = await store.get(keyPrefixed);
884
- } catch (error) {
885
- this.emit("error", error);
886
- if (this._throwOnErrors) {
887
- throw error;
888
- }
889
- return false;
890
- }
891
- if (rawData) {
892
- const data = await this.deserializeData(rawData);
893
- if (data) {
894
- if (data.expires === void 0 || data.expires === null) {
895
- return true;
896
- }
897
- return data.expires > Date.now();
898
- }
899
- }
900
- return false;
901
- }
902
- /**
903
- * Check if many keys exist
904
- * @param {string[]} keys the keys to check
905
- * @returns {boolean[]} will return an array of booleans if the keys exist
906
- */
907
- async hasMany(keys) {
908
- const keyPrefixed = this._getKeyPrefixArray(keys);
909
- const store = this._store;
910
- if (store.hasMany !== void 0) {
911
- return store.hasMany(keyPrefixed);
912
- }
913
- const results = [];
914
- for (const key of keys) {
915
- results.push(await this.has(key));
916
- }
917
- return results;
918
- }
919
- /**
920
- * Will disconnect the store. This is only available if the store has a disconnect method
921
- * @returns {Promise<void>}
922
- */
923
- async disconnect() {
924
- const store = this._store;
925
- this.emit("disconnect");
926
- if (typeof store.disconnect === "function") {
927
- return store.disconnect();
928
- }
929
- }
930
- // biome-ignore lint/suspicious/noExplicitAny: type format
931
- emit(event, ...arguments_) {
932
- if (event === "error" && !this._emitErrors) {
933
- return;
934
- }
935
- super.emit(event, ...arguments_);
936
- }
937
- async serializeData(data) {
938
- if (!this._serialize) {
939
- return data;
940
- }
941
- if (this._compression?.compress) {
942
- return this._serialize({
943
- value: await this._compression.compress(data.value),
944
- expires: data.expires
945
- });
946
- }
947
- return this._serialize(data);
948
- }
949
- async deserializeData(data) {
950
- if (!this._deserialize) {
951
- return data;
952
- }
953
- if (this._compression?.decompress && typeof data === "string") {
954
- const result = await this._deserialize(data);
955
- return {
956
- value: await this._compression.decompress(result?.value),
957
- expires: result?.expires
958
- };
959
- }
960
- if (typeof data === "string") {
961
- return this._deserialize(data);
962
- }
963
- return void 0;
964
- }
965
- };
966
- var index_default = Keyv;
967
- export {
968
- Keyv,
969
- KeyvHooks,
970
- index_default as default
971
- };
972
- /* v8 ignore next -- @preserve */