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