keyv 6.0.0-beta.1 → 6.0.0-beta.4

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.cjs CHANGED
@@ -177,6 +177,26 @@ function detectKeyvStorage(obj) {
177
177
  };
178
178
  }
179
179
  /**
180
+ * Build the capability descriptor for a v6 storage adapter: the structurally detected
181
+ * methods plus `expires: true`, declaring that the adapter accepts an absolute `expires`
182
+ * timestamp on `set`/`setMany`. First-party adapters expose this from their `capabilities`
183
+ * getter so Keyv uses them directly instead of bridging.
184
+ * @param adapter - The storage adapter to describe (typically `this`).
185
+ * @returns A {@link KeyvStorageCapability} with `expires` set to `true`.
186
+ * @example
187
+ * ```typescript
188
+ * public get capabilities(): KeyvStorageCapability {
189
+ * return keyvStorageCapability(this);
190
+ * }
191
+ * ```
192
+ */
193
+ function keyvStorageCapability(adapter) {
194
+ return {
195
+ ...detectKeyvStorage(adapter),
196
+ expires: true
197
+ };
198
+ }
199
+ /**
180
200
  * Detect whether an object implements the Keyv compression adapter interface
181
201
  * @param obj - The object to check
182
202
  * @returns A {@link KeyvCompressionCapability} where `compatible` is `true` when both `compress` and `decompress` methods are present
@@ -406,26 +426,26 @@ async function deleteExpiredKeys(keys, data, keyv) {
406
426
  * Maps new hook names to their deprecated equivalents so both fire during migration.
407
427
  */
408
428
  const deprecatedHookAliases = new Map([
409
- [KeyvHooks.BEFORE_SET, KeyvHooks.PRE_SET],
410
- [KeyvHooks.AFTER_SET, KeyvHooks.POST_SET],
411
- [KeyvHooks.BEFORE_GET, KeyvHooks.PRE_GET],
412
- [KeyvHooks.AFTER_GET, KeyvHooks.POST_GET],
413
- [KeyvHooks.BEFORE_GET_MANY, KeyvHooks.PRE_GET_MANY],
414
- [KeyvHooks.AFTER_GET_MANY, KeyvHooks.POST_GET_MANY],
415
- [KeyvHooks.BEFORE_GET_RAW, KeyvHooks.PRE_GET_RAW],
416
- [KeyvHooks.AFTER_GET_RAW, KeyvHooks.POST_GET_RAW],
417
- [KeyvHooks.BEFORE_GET_MANY_RAW, KeyvHooks.PRE_GET_MANY_RAW],
418
- [KeyvHooks.AFTER_GET_MANY_RAW, KeyvHooks.POST_GET_MANY_RAW],
419
- [KeyvHooks.BEFORE_SET_RAW, KeyvHooks.PRE_SET_RAW],
420
- [KeyvHooks.AFTER_SET_RAW, KeyvHooks.POST_SET_RAW],
421
- [KeyvHooks.BEFORE_SET_MANY, KeyvHooks.PRE_SET_MANY],
422
- [KeyvHooks.AFTER_SET_MANY, KeyvHooks.POST_SET_MANY],
423
- [KeyvHooks.BEFORE_SET_MANY_RAW, KeyvHooks.PRE_SET_MANY_RAW],
424
- [KeyvHooks.AFTER_SET_MANY_RAW, KeyvHooks.POST_SET_MANY_RAW],
425
- [KeyvHooks.BEFORE_DELETE, KeyvHooks.PRE_DELETE],
426
- [KeyvHooks.AFTER_DELETE, KeyvHooks.POST_DELETE],
427
- [KeyvHooks.BEFORE_DELETE_MANY, KeyvHooks.PRE_DELETE_MANY],
428
- [KeyvHooks.AFTER_DELETE_MANY, KeyvHooks.POST_DELETE_MANY]
429
+ ["before:set", "preSet"],
430
+ ["after:set", "postSet"],
431
+ ["before:get", "preGet"],
432
+ ["after:get", "postGet"],
433
+ ["before:getMany", "preGetMany"],
434
+ ["after:getMany", "postGetMany"],
435
+ ["before:getRaw", "preGetRaw"],
436
+ ["after:getRaw", "postGetRaw"],
437
+ ["before:getManyRaw", "preGetManyRaw"],
438
+ ["after:getManyRaw", "postGetManyRaw"],
439
+ ["before:setRaw", "preSetRaw"],
440
+ ["after:setRaw", "postSetRaw"],
441
+ ["before:setMany", "preSetMany"],
442
+ ["after:setMany", "postSetMany"],
443
+ ["before:setManyRaw", "preSetManyRaw"],
444
+ ["after:setManyRaw", "postSetManyRaw"],
445
+ ["before:delete", "preDelete"],
446
+ ["after:delete", "postDelete"],
447
+ ["before:deleteMany", "preDeleteMany"],
448
+ ["after:deleteMany", "postDeleteMany"]
429
449
  ]);
430
450
  /**
431
451
  * Build the deprecated-hooks map used by Hookified to warn when old PRE_/POST_ hook names are registered.
@@ -479,6 +499,12 @@ var KeyvBridgeAdapter = class extends hookified.Hookified {
479
499
  _keySeparator = ":";
480
500
  _capabilities;
481
501
  /**
502
+ * Whether the wrapped store manages its own namespace (exposes a `namespace` property).
503
+ * When true the bridge propagates its namespace to the store and does not prefix keys,
504
+ * so the store's native, namespace-scoped operations (notably `clear()`) are used directly.
505
+ */
506
+ _storeHandlesNamespace;
507
+ /**
482
508
  * Creates a new KeyvBridgeAdapter instance.
483
509
  * @param store - The underlying promise-based store to bridge
484
510
  * @param options - Configuration options for the adapter
@@ -486,10 +512,12 @@ var KeyvBridgeAdapter = class extends hookified.Hookified {
486
512
  constructor(store, options) {
487
513
  super({ throwOnHookError: false });
488
514
  this._store = store;
515
+ this._capabilities = detectKeyvStorage(store);
516
+ this._storeHandlesNamespace = this._capabilities.store === "keyvStorage" && "namespace" in store;
489
517
  if (options?.keySeparator) this._keySeparator = options.keySeparator;
490
518
  if (options?.namespace) this._namespace = options.namespace;
491
- this._capabilities = detectKeyvStorage(store);
492
- if (typeof store.on === "function") store.on(KeyvEvents.ERROR, (error) => this.emit(KeyvEvents.ERROR, error));
519
+ if (this._storeHandlesNamespace) this._store.namespace = this._namespace;
520
+ if (typeof store.on === "function") store.on("error", (error) => this.emit("error", error));
493
521
  }
494
522
  /**
495
523
  * Gets the underlying store instance.
@@ -504,10 +532,15 @@ var KeyvBridgeAdapter = class extends hookified.Hookified {
504
532
  this._store = store;
505
533
  }
506
534
  /**
507
- * Gets the detected capabilities of the underlying store.
535
+ * Gets the capabilities of the underlying store, with `expires: true` to declare that
536
+ * the bridge accepts an absolute `expires` timestamp (which it converts to a ttl for the
537
+ * wrapped legacy store).
508
538
  */
509
539
  get capabilities() {
510
- return this._capabilities;
540
+ return {
541
+ ...this._capabilities,
542
+ expires: true
543
+ };
511
544
  }
512
545
  /**
513
546
  * Gets the current key separator used between namespace and key.
@@ -528,10 +561,12 @@ var KeyvBridgeAdapter = class extends hookified.Hookified {
528
561
  return this._namespace;
529
562
  }
530
563
  /**
531
- * Sets the namespace.
564
+ * Sets the namespace. When the wrapped store manages its own namespace, the value is
565
+ * propagated to it so its native scoped operations stay in sync.
532
566
  */
533
567
  set namespace(namespace) {
534
568
  this._namespace = namespace;
569
+ if (this._storeHandlesNamespace) this._store.namespace = namespace;
535
570
  }
536
571
  /**
537
572
  * Creates a prefixed key by combining the namespace and key with the separator.
@@ -540,6 +575,7 @@ var KeyvBridgeAdapter = class extends hookified.Hookified {
540
575
  * @returns The prefixed key if namespace is provided, otherwise the original key
541
576
  */
542
577
  getKeyPrefix(key, namespace) {
578
+ if (this._storeHandlesNamespace) return key;
543
579
  if (namespace) return `${namespace}${this._keySeparator}${key}`;
544
580
  return key;
545
581
  }
@@ -605,35 +641,49 @@ var KeyvBridgeAdapter = class extends hookified.Hookified {
605
641
  return values;
606
642
  }
607
643
  /**
608
- * Stores a value in the store with an optional TTL.
644
+ * Stores a value in the store with an optional absolute expiry.
645
+ * The wrapped store's `set(key, value, ttl?)` expects a relative duration, so the absolute
646
+ * `expires` is converted to a remaining ttl (`undefined` when already expired or absent).
647
+ * The value is passed through unchanged — the bridge does not wrap it in an envelope — so
648
+ * expiry is enforced by the wrapped legacy store's own ttl handling. (The read-side
649
+ * {@link isDataExpired} check only fires when a caller stores a raw `{ value, expires }`
650
+ * object directly; when Keyv core drives the bridge the value arrives already encoded.)
609
651
  * @param key - The key to store the value under
610
652
  * @param value - The value to store
611
- * @param ttl - Optional time-to-live in milliseconds
653
+ * @param expires - Optional absolute expiry as Unix ms since epoch
612
654
  * @returns Always returns true indicating success
613
655
  */
614
- async set(key, value, ttl) {
656
+ async set(key, value, expires) {
615
657
  const keyPrefix = this.getKeyPrefix(key, this._namespace);
616
- const result = await this._store.set(keyPrefix, value, ttl);
658
+ if (typeof expires === "number" && expires <= Date.now()) {
659
+ await this._store.delete(keyPrefix);
660
+ return true;
661
+ }
662
+ const result = await this._store.set(keyPrefix, value, ttlFromExpires(expires));
617
663
  if (typeof result === "boolean") return result;
618
664
  return true;
619
665
  }
620
666
  /**
621
667
  * Stores multiple entries in the store at once.
622
668
  * Delegates to the store's native setMany if available, otherwise loops over set.
623
- * @param entries - Array of entries containing key, value, and optional TTL
669
+ * @param entries - Array of entries containing key, value, and optional absolute `expires`
624
670
  */
625
671
  async setMany(entries) {
626
672
  if (this._capabilities.methods.setMany.exists) {
627
- const prefixedEntries = entries.map((entry) => ({
628
- ...entry,
629
- key: this.getKeyPrefix(entry.key, this._namespace)
630
- }));
631
- await this._store.setMany?.(prefixedEntries);
673
+ const now = Date.now();
674
+ const isExpired = (entry) => typeof entry.expires === "number" && entry.expires <= now;
675
+ const live = entries.filter((entry) => !isExpired(entry));
676
+ if (live.length > 0) await this._store.setMany?.(live.map((entry) => ({
677
+ key: this.getKeyPrefix(entry.key, this._namespace),
678
+ value: entry.value,
679
+ ttl: ttlFromExpires(entry.expires)
680
+ })));
681
+ for (const entry of entries) if (isExpired(entry)) await this._store.delete(this.getKeyPrefix(entry.key, this._namespace));
632
682
  return entries.map(() => true);
633
683
  }
634
684
  const results = [];
635
685
  for (const entry of entries) {
636
- await this.set(entry.key, entry.value, entry.ttl);
686
+ await this.set(entry.key, entry.value, entry.expires);
637
687
  results.push(true);
638
688
  }
639
689
  return results;
@@ -696,7 +746,7 @@ var KeyvBridgeAdapter = class extends hookified.Hookified {
696
746
  const result = await this._store.delete(keyPrefix);
697
747
  results.push(result);
698
748
  } catch (error) {
699
- this.emit(KeyvEvents.ERROR, error);
749
+ this.emit("error", error);
700
750
  results.push(false);
701
751
  }
702
752
  return results;
@@ -707,6 +757,10 @@ var KeyvBridgeAdapter = class extends hookified.Hookified {
707
757
  * entire store is cleared.
708
758
  */
709
759
  async clear() {
760
+ if (this._namespace && this._storeHandlesNamespace) {
761
+ await this._store.clear();
762
+ return;
763
+ }
710
764
  if (!this._namespace || !this._capabilities.methods.iterator.exists) {
711
765
  await this._store.clear();
712
766
  return;
@@ -728,7 +782,7 @@ var KeyvBridgeAdapter = class extends hookified.Hookified {
728
782
  async *iterator() {
729
783
  if (!this._capabilities.methods.iterator.exists) return;
730
784
  const namespace = this._namespace;
731
- const prefix = namespace ? `${namespace}${this._keySeparator}` : void 0;
785
+ const prefix = namespace && !this._storeHandlesNamespace ? `${namespace}${this._keySeparator}` : void 0;
732
786
  /* v8 ignore next -- @preserve */
733
787
  for await (const entry of this._store.iterator?.(this._namespace) ?? []) {
734
788
  const [key, data] = Array.isArray(entry) ? entry : [entry];
@@ -1168,6 +1222,29 @@ var KeyvStats = class {
1168
1222
  //#endregion
1169
1223
  //#region src/keyv.ts
1170
1224
  var Keyv = class Keyv extends hookified.Hookified {
1225
+ /**
1226
+ * Keyv Constructor
1227
+ * @param {KeyvStorageAdapter | KeyvOptions} store
1228
+ * @param {Omit<KeyvOptions, 'store'>} [options] if you provide the store you can then provide the Keyv Options
1229
+ */
1230
+ constructor(store, options) {
1231
+ const mergedOptions = Keyv.resolveOptions(store, options);
1232
+ super({
1233
+ throwOnHookError: false,
1234
+ throwOnEmptyListeners: true,
1235
+ throwOnEmitError: mergedOptions.throwOnErrors ?? false
1236
+ });
1237
+ this.deprecatedHooks = buildDeprecatedHooks();
1238
+ this._compression = mergedOptions.compression;
1239
+ this._encryption = mergedOptions.encryption;
1240
+ this.initSerialization(mergedOptions);
1241
+ this.initSanitize(mergedOptions);
1242
+ this.initNamespace(mergedOptions.namespace);
1243
+ this.initStats(mergedOptions);
1244
+ if (mergedOptions.store) this.setStore(mergedOptions.store);
1245
+ this.setTtl(mergedOptions.ttl);
1246
+ this._checkExpired = mergedOptions.checkExpired ?? false;
1247
+ }
1171
1248
  /**
1172
1249
  * Stats manager for tracking cache operation metrics (hits, misses, sets, deletes, errors).
1173
1250
  * @default this is disabled.
@@ -1207,29 +1284,6 @@ var Keyv = class Keyv extends hookified.Hookified {
1207
1284
  */
1208
1285
  _checkExpired = false;
1209
1286
  /**
1210
- * Keyv Constructor
1211
- * @param {KeyvStorageAdapter | KeyvOptions} store
1212
- * @param {Omit<KeyvOptions, 'store'>} [options] if you provide the store you can then provide the Keyv Options
1213
- */
1214
- constructor(store, options) {
1215
- const mergedOptions = Keyv.resolveOptions(store, options);
1216
- super({
1217
- throwOnHookError: false,
1218
- throwOnEmptyListeners: true,
1219
- throwOnEmitError: mergedOptions.throwOnErrors ?? false
1220
- });
1221
- this.deprecatedHooks = buildDeprecatedHooks();
1222
- this._compression = mergedOptions.compression;
1223
- this._encryption = mergedOptions.encryption;
1224
- this.initSerialization(mergedOptions);
1225
- this.initSanitize(mergedOptions);
1226
- this.initNamespace(mergedOptions.namespace);
1227
- this.initStats(mergedOptions);
1228
- if (mergedOptions.store) this.setStore(mergedOptions.store);
1229
- this.setTtl(mergedOptions.ttl);
1230
- this._checkExpired = mergedOptions.checkExpired ?? false;
1231
- }
1232
- /**
1233
1287
  * Get the current storage adapter.
1234
1288
  * @returns {KeyvStorageAdapter} The current storage adapter.
1235
1289
  */
@@ -1357,13 +1411,6 @@ var Keyv = class Keyv extends hookified.Hookified {
1357
1411
  return this._stats;
1358
1412
  }
1359
1413
  /**
1360
- * When true, Keyv checks expiry at its layer on get/getMany/has/hasMany.
1361
- * When false (default), trusts the storage adapter.
1362
- */
1363
- get checkExpired() {
1364
- return this._checkExpired;
1365
- }
1366
- /**
1367
1414
  * Set the stats. When setting a new instance it will unsubscribe the old listeners
1368
1415
  * and subscribe the new instance.
1369
1416
  * @param {KeyvStats} stats The stats instance to set.
@@ -1374,22 +1421,35 @@ var Keyv = class Keyv extends hookified.Hookified {
1374
1421
  this._stats.subscribe(this);
1375
1422
  }
1376
1423
  /**
1377
- * Resolves a store to a fully-compliant KeyvStorageAdapter using a 3-tier detection chain:
1378
- * 1. If the store already implements the full KeyvStorageAdapter interface, use it directly.
1379
- * 2. If the store is map-like (synchronous get/set/delete/has), wrap it in KeyvMemoryAdapter.
1380
- * 3. If the store has async get/set/delete/clear, wrap it in KeyvBridgeAdapter.
1381
- * 4. Otherwise, emit an error and fall back to a default in-memory KeyvMemoryAdapter.
1424
+ * Get whether Keyv checks expiry at its own layer on get/getMany/has/hasMany.
1425
+ * When false (default), it trusts the storage adapter to handle expiry.
1426
+ * @returns {boolean} `true` if Keyv checks expiry at its layer.
1427
+ */
1428
+ get checkExpired() {
1429
+ return this._checkExpired;
1430
+ }
1431
+ /**
1432
+ * Resolves a store to a fully-compliant KeyvStorageAdapter:
1433
+ * 1. If the store declares the v6 `capabilities.expires` contract, use it directly (this takes
1434
+ * precedence over structural detection, so a full adapter whose async methods aren't written
1435
+ * with the `async` keyword is not mis-bridged).
1436
+ * 2. If the store implements the full async storage interface (but doesn't declare `expires`),
1437
+ * treat it as a legacy relative-`ttl` adapter and wrap it in KeyvBridgeAdapter.
1438
+ * 3. If the store is map-like (synchronous get/set/delete/has), wrap it in KeyvMemoryAdapter.
1439
+ * 4. If the store has async get/set/delete/clear, wrap it in KeyvBridgeAdapter.
1440
+ * 5. Otherwise, emit an error and fall back to a default in-memory KeyvMemoryAdapter.
1382
1441
  *
1383
1442
  * NOTE: this is used for internal but provided public for custom adapter testing
1384
1443
  * @param {unknown} store The store to resolve.
1385
1444
  * @returns {KeyvStorageAdapter} A fully-compliant storage adapter.
1386
1445
  */
1387
1446
  resolveStore(store) {
1447
+ if (store?.capabilities?.expires === true) return store;
1388
1448
  const cap = detectKeyvStorage(store);
1389
- if (cap.store === "keyvStorage") return store;
1449
+ if (cap.store === "keyvStorage") return new KeyvBridgeAdapter(store);
1390
1450
  if (cap.store === "mapLike") return new KeyvMemoryAdapter(store);
1391
1451
  if (cap.store === "asyncMap") return new KeyvBridgeAdapter(store);
1392
- this.emit(KeyvEvents.ERROR, /* @__PURE__ */ new Error("Could not use the provided storage adapter, falling back to KeyvMemoryAdapter with Map"));
1452
+ this.emit("error", /* @__PURE__ */ new Error("Could not use the provided storage adapter, falling back to KeyvMemoryAdapter with Map"));
1393
1453
  return new KeyvMemoryAdapter(/* @__PURE__ */ new Map());
1394
1454
  }
1395
1455
  /**
@@ -1399,7 +1459,7 @@ var Keyv = class Keyv extends hookified.Hookified {
1399
1459
  */
1400
1460
  setStore(store) {
1401
1461
  this._store = this.resolveStore(store);
1402
- if (typeof this._store.on === "function") this._store.on(KeyvEvents.ERROR, (error) => this.emit(KeyvEvents.ERROR, error));
1462
+ if (typeof this._store.on === "function") this._store.on("error", (error) => this.emit("error", error));
1403
1463
  this._store.namespace = this._namespace;
1404
1464
  }
1405
1465
  /**
@@ -1417,40 +1477,54 @@ var Keyv = class Keyv extends hookified.Hookified {
1417
1477
  if (Array.isArray(key)) return this.getMany(key);
1418
1478
  key = this._sanitize.enabled ? this._sanitize.cleanKey(key) : key;
1419
1479
  if (key === "") return;
1420
- await this.hookWithDeprecated(KeyvHooks.BEFORE_GET, { key });
1480
+ await this.hookWithDeprecated("before:get", { key });
1421
1481
  let rawData;
1422
1482
  try {
1423
1483
  rawData = await this._store.get(key);
1424
1484
  } catch (error) {
1425
- this.emit(KeyvEvents.ERROR, error);
1426
- this.emitTelemetry(KeyvEvents.STAT_ERROR, key);
1485
+ this.emit("error", error);
1486
+ this.emitTelemetry("stat:error", key);
1427
1487
  }
1428
1488
  let data;
1429
1489
  if (this._checkExpired) [data] = await this.decodeWithExpire(key, rawData);
1430
1490
  else data = rawData === void 0 || rawData === null ? void 0 : typeof rawData === "string" ? await this.decode(rawData) : rawData;
1431
1491
  if (data === void 0) {
1432
- await this.hookWithDeprecated(KeyvHooks.AFTER_GET, {
1492
+ await this.hookWithDeprecated("after:get", {
1433
1493
  key,
1434
1494
  value: void 0
1435
1495
  });
1436
- this.emitTelemetry(KeyvEvents.STAT_MISS, key);
1496
+ this.emitTelemetry("stat:miss", key);
1437
1497
  return;
1438
1498
  }
1439
- await this.hookWithDeprecated(KeyvHooks.AFTER_GET, {
1499
+ await this.hookWithDeprecated("after:get", {
1440
1500
  key,
1441
1501
  value: data
1442
1502
  });
1443
- this.emitTelemetry(KeyvEvents.STAT_HIT, key);
1503
+ this.emitTelemetry("stat:hit", key);
1444
1504
  return data.value;
1445
1505
  }
1446
1506
  /**
1447
- * Get many values of keys
1448
- * @param {string[]} keys passing in a single key or multiple as an array
1507
+ * Reads many keys from the store, preferring its native `getMany` and falling back to parallel
1508
+ * single `get`s when an adapter does not implement it. A directly-used v6 adapter is not
1509
+ * structurally required to provide `getMany` (the bridge and memory adapters always do), so
1510
+ * this keeps `getMany`/`getManyRaw` working regardless of the resolved adapter.
1511
+ * @param keys - the keys to read
1512
+ * @returns the raw store results in the same order as `keys`
1513
+ */
1514
+ async storeGetMany(keys) {
1515
+ if (typeof this._store.getMany === "function") return this._store.getMany(keys);
1516
+ return Promise.all(keys.map(async (key) => this._store.get(key)));
1517
+ }
1518
+ /**
1519
+ * Get many values for an array of keys.
1520
+ * @param {string[]} keys the keys to get
1521
+ * @returns {Promise<Array<Value | undefined>>} an array of values in the same order as the
1522
+ * keys, with `undefined` for keys that do not exist or are expired.
1449
1523
  */
1450
1524
  async getMany(keys) {
1451
1525
  keys = this._sanitize.enabled ? this._sanitize.cleanKeys(keys) : keys;
1452
- await this.hookWithDeprecated(KeyvHooks.BEFORE_GET_MANY, { keys });
1453
- const rawData = await this._store.getMany(keys);
1526
+ await this.hookWithDeprecated("before:getMany", { keys });
1527
+ const rawData = await this.storeGetMany(keys);
1454
1528
  let deserialized;
1455
1529
  if (this._checkExpired) deserialized = await this.decodeWithExpire(keys, rawData);
1456
1530
  else deserialized = await Promise.all(rawData.map(async (row) => {
@@ -1458,9 +1532,9 @@ var Keyv = class Keyv extends hookified.Hookified {
1458
1532
  return typeof row === "string" ? this.decode(row) : row;
1459
1533
  }));
1460
1534
  const result = deserialized.map((row) => row !== void 0 ? row.value : void 0);
1461
- await this.hookWithDeprecated(KeyvHooks.AFTER_GET_MANY, result);
1462
- for (let i = 0; i < result.length; i++) if (result[i] === void 0) this.emitTelemetry(KeyvEvents.STAT_MISS, keys[i]);
1463
- else this.emitTelemetry(KeyvEvents.STAT_HIT, keys[i]);
1535
+ await this.hookWithDeprecated("after:getMany", result);
1536
+ for (let i = 0; i < result.length; i++) if (result[i] === void 0) this.emitTelemetry("stat:miss", keys[i]);
1537
+ else this.emitTelemetry("stat:hit", keys[i]);
1464
1538
  return result;
1465
1539
  }
1466
1540
  /**
@@ -1472,21 +1546,21 @@ var Keyv = class Keyv extends hookified.Hookified {
1472
1546
  async getRaw(key) {
1473
1547
  key = this._sanitize.enabled ? this._sanitize.cleanKey(key) : key;
1474
1548
  if (key === "") return;
1475
- await this.hookWithDeprecated(KeyvHooks.BEFORE_GET_RAW, { key });
1549
+ await this.hookWithDeprecated("before:getRaw", { key });
1476
1550
  const rawData = await this._store.get(key);
1477
1551
  let data;
1478
1552
  if (this._checkExpired) [data] = await this.decodeWithExpire(key, rawData);
1479
1553
  else data = rawData === void 0 || rawData === null ? void 0 : typeof rawData === "string" ? await this.decode(rawData) : rawData;
1480
1554
  if (data === void 0) {
1481
- await this.hookWithDeprecated(KeyvHooks.AFTER_GET_RAW, {
1555
+ await this.hookWithDeprecated("after:getRaw", {
1482
1556
  key,
1483
1557
  value: void 0
1484
1558
  });
1485
- this.emitTelemetry(KeyvEvents.STAT_MISS, key);
1559
+ this.emitTelemetry("stat:miss", key);
1486
1560
  return;
1487
1561
  }
1488
- this.emitTelemetry(KeyvEvents.STAT_HIT, key);
1489
- await this.hookWithDeprecated(KeyvHooks.AFTER_GET_RAW, {
1562
+ this.emitTelemetry("stat:hit", key);
1563
+ await this.hookWithDeprecated("after:getRaw", {
1490
1564
  key,
1491
1565
  value: data
1492
1566
  });
@@ -1500,25 +1574,25 @@ var Keyv = class Keyv extends hookified.Hookified {
1500
1574
  async getManyRaw(keys) {
1501
1575
  /* v8 ignore next -- @preserve */
1502
1576
  keys = this._sanitize.enabled ? this._sanitize.cleanKeys(keys) : keys;
1503
- await this.hookWithDeprecated(KeyvHooks.BEFORE_GET_MANY_RAW, { keys });
1577
+ await this.hookWithDeprecated("before:getManyRaw", { keys });
1504
1578
  if (keys.length === 0) {
1505
1579
  const result = [];
1506
- await this.hookWithDeprecated(KeyvHooks.AFTER_GET_MANY_RAW, {
1580
+ await this.hookWithDeprecated("after:getManyRaw", {
1507
1581
  keys,
1508
1582
  values: result
1509
1583
  });
1510
1584
  return result;
1511
1585
  }
1512
- const rawData = await this._store.getMany(keys);
1586
+ const rawData = await this.storeGetMany(keys);
1513
1587
  let result;
1514
1588
  if (this._checkExpired) result = await this.decodeWithExpire(keys, rawData);
1515
1589
  else result = await Promise.all(rawData.map(async (row) => {
1516
1590
  if (row === void 0 || row === null) return;
1517
1591
  return typeof row === "string" ? this.decode(row) : row;
1518
1592
  }));
1519
- for (let i = 0; i < result.length; i++) if (result[i] === void 0) this.emitTelemetry(KeyvEvents.STAT_MISS, keys[i]);
1520
- else this.emitTelemetry(KeyvEvents.STAT_HIT, keys[i]);
1521
- await this.hookWithDeprecated(KeyvHooks.AFTER_GET_MANY_RAW, {
1593
+ for (let i = 0; i < result.length; i++) if (result[i] === void 0) this.emitTelemetry("stat:miss", keys[i]);
1594
+ else this.emitTelemetry("stat:hit", keys[i]);
1595
+ await this.hookWithDeprecated("after:getManyRaw", {
1522
1596
  keys,
1523
1597
  values: result
1524
1598
  });
@@ -1526,10 +1600,10 @@ var Keyv = class Keyv extends hookified.Hookified {
1526
1600
  }
1527
1601
  /**
1528
1602
  * Set an item to the store
1529
- * @param {string | Array<KeyvEntry<Value>>} key the key to use. If you pass in an array of KeyvEntry it will set many items
1603
+ * @param {string} key the key to use
1530
1604
  * @param {Value} value the value of the key
1531
- * @param {number} [ttl] time to live in milliseconds
1532
- * @returns {boolean} if it sets then it will return a true. On failure will return false.
1605
+ * @param {number} [ttl] time to live in milliseconds. Overrides the instance-level `ttl`.
1606
+ * @returns {Promise<boolean>} `true` if it was set successfully, `false` on failure.
1533
1607
  */
1534
1608
  async set(key, value, ttl) {
1535
1609
  key = this._sanitize.enabled ? this._sanitize.cleanKey(key) : key;
@@ -1539,12 +1613,12 @@ var Keyv = class Keyv extends hookified.Hookified {
1539
1613
  value,
1540
1614
  ttl
1541
1615
  };
1542
- await this.hookWithDeprecated(KeyvHooks.BEFORE_SET, data);
1616
+ await this.hookWithDeprecated("before:set", data);
1543
1617
  data.ttl = resolveTtl(data.ttl, this._ttl);
1544
1618
  const expires = calculateExpires(data.ttl);
1545
1619
  if (typeof data.value === "symbol") {
1546
- this.emit(KeyvEvents.ERROR, "symbol cannot be serialized");
1547
- this.emitTelemetry(KeyvEvents.STAT_ERROR, key);
1620
+ this.emit("error", "symbol cannot be serialized");
1621
+ this.emitTelemetry("stat:error", key);
1548
1622
  return false;
1549
1623
  }
1550
1624
  const formattedValue = {
@@ -1555,24 +1629,24 @@ var Keyv = class Keyv extends hookified.Hookified {
1555
1629
  let encodedValue = formattedValue;
1556
1630
  try {
1557
1631
  encodedValue = await this.encode(formattedValue);
1558
- result = await this._store.set(data.key, encodedValue, data.ttl);
1632
+ result = await this._store.set(data.key, encodedValue, expires);
1559
1633
  } catch (error) {
1560
1634
  result = false;
1561
- this.emit(KeyvEvents.ERROR, error);
1562
- this.emitTelemetry(KeyvEvents.STAT_ERROR, key);
1635
+ this.emit("error", error);
1636
+ this.emitTelemetry("stat:error", key);
1563
1637
  }
1564
- await this.hookWithDeprecated(KeyvHooks.AFTER_SET, {
1638
+ await this.hookWithDeprecated("after:set", {
1565
1639
  key,
1566
1640
  value: encodedValue,
1567
1641
  ttl
1568
1642
  });
1569
- if (result) this.emitTelemetry(KeyvEvents.STAT_SET, key);
1643
+ if (result) this.emitTelemetry("stat:set", key);
1570
1644
  return result;
1571
1645
  }
1572
1646
  /**
1573
1647
  * Set many items to the store
1574
1648
  * @param {Array<KeyvEntry<Value>>} entries the entries to set
1575
- * @returns {boolean[]} will return an array of booleans if it sets then it will return a true. On failure will return false.
1649
+ * @returns {Promise<boolean[]>} an array of booleans, one per entry: `true` if set successfully, `false` on failure.
1576
1650
  */
1577
1651
  async setMany(entries) {
1578
1652
  entries = entries.map((e) => ({
@@ -1580,7 +1654,7 @@ var Keyv = class Keyv extends hookified.Hookified {
1580
1654
  key: this._sanitize.enabled ? this._sanitize.cleanKey(e.key) : e.key
1581
1655
  }));
1582
1656
  const data = { entries };
1583
- await this.hookWithDeprecated(KeyvHooks.BEFORE_SET_MANY, data);
1657
+ await this.hookWithDeprecated("before:setMany", data);
1584
1658
  entries = data.entries;
1585
1659
  let results = [];
1586
1660
  try {
@@ -1590,8 +1664,8 @@ var Keyv = class Keyv extends hookified.Hookified {
1590
1664
  const expires = calculateExpires(ttl);
1591
1665
  /* v8 ignore next -- @preserve */
1592
1666
  if (typeof value === "symbol") {
1593
- this.emit(KeyvEvents.ERROR, "symbol cannot be serialized");
1594
- this.emitTelemetry(KeyvEvents.STAT_ERROR, key);
1667
+ this.emit("error", "symbol cannot be serialized");
1668
+ this.emitTelemetry("stat:error", key);
1595
1669
  throw new Error("symbol cannot be serialized");
1596
1670
  }
1597
1671
  const formattedValue = {
@@ -1601,19 +1675,19 @@ var Keyv = class Keyv extends hookified.Hookified {
1601
1675
  return {
1602
1676
  key,
1603
1677
  value: await this.encode(formattedValue),
1604
- ttl
1678
+ expires
1605
1679
  };
1606
1680
  }));
1607
1681
  const storeResult = await this._store.setMany(serializedEntries);
1608
1682
  /* v8 ignore next -- @preserve */
1609
1683
  results = Array.isArray(storeResult) ? storeResult : entries.map(() => true);
1610
- this.emitTelemetry(KeyvEvents.STAT_SET, entries.map((e) => e.key));
1684
+ this.emitTelemetry("stat:set", entries.map((e) => e.key));
1611
1685
  } catch (error) {
1612
- this.emit(KeyvEvents.ERROR, error);
1613
- this.emitTelemetry(KeyvEvents.STAT_ERROR, entries.map((e) => e.key));
1686
+ this.emit("error", error);
1687
+ this.emitTelemetry("stat:error", entries.map((e) => e.key));
1614
1688
  results = entries.map(() => false);
1615
1689
  }
1616
- await this.hookWithDeprecated(KeyvHooks.AFTER_SET_MANY, {
1690
+ await this.hookWithDeprecated("after:setMany", {
1617
1691
  entries,
1618
1692
  values: results
1619
1693
  });
@@ -1626,7 +1700,7 @@ var Keyv = class Keyv extends hookified.Hookified {
1626
1700
  * The store-level TTL is derived automatically from `value.expires`.
1627
1701
  * @param {string} key the key to set
1628
1702
  * @param {KeyvValue<Value>} value the raw value envelope to store
1629
- * @returns {boolean} if it sets then it will return a true. On failure will return false.
1703
+ * @returns {Promise<boolean>} `true` if it was set successfully, `false` on failure.
1630
1704
  */
1631
1705
  async setRaw(key, value) {
1632
1706
  key = this._sanitize.enabled ? this._sanitize.cleanKey(key) : key;
@@ -1635,24 +1709,25 @@ var Keyv = class Keyv extends hookified.Hookified {
1635
1709
  key,
1636
1710
  value
1637
1711
  };
1638
- await this.hookWithDeprecated(KeyvHooks.BEFORE_SET_RAW, data);
1639
- const ttl = ttlFromExpires(data.value.expires);
1712
+ await this.hookWithDeprecated("before:setRaw", data);
1713
+ const expires = data.value.expires;
1714
+ const ttl = ttlFromExpires(expires);
1640
1715
  let result = true;
1641
1716
  try {
1642
1717
  const encodedValue = await this.encode(data.value);
1643
- const storeResult = await this._store.set(data.key, encodedValue, ttl);
1718
+ const storeResult = await this._store.set(data.key, encodedValue, expires);
1644
1719
  if (typeof storeResult === "boolean") result = storeResult;
1645
1720
  } catch (error) {
1646
1721
  result = false;
1647
- this.emit(KeyvEvents.ERROR, error);
1648
- this.emitTelemetry(KeyvEvents.STAT_ERROR, key);
1722
+ this.emit("error", error);
1723
+ this.emitTelemetry("stat:error", key);
1649
1724
  }
1650
- await this.hookWithDeprecated(KeyvHooks.AFTER_SET_RAW, {
1725
+ await this.hookWithDeprecated("after:setRaw", {
1651
1726
  key,
1652
1727
  value: data.value,
1653
1728
  ttl
1654
1729
  });
1655
- if (result) this.emitTelemetry(KeyvEvents.STAT_SET, key);
1730
+ if (result) this.emitTelemetry("stat:set", key);
1656
1731
  return result;
1657
1732
  }
1658
1733
  /**
@@ -1660,33 +1735,33 @@ var Keyv = class Keyv extends hookified.Hookified {
1660
1735
  * Each entry's value should be a KeyvValue object with { value, expires? }. If you need TTL-based expiration,
1661
1736
  * set `expires` on each value directly. The store-level TTL is derived automatically from `value.expires`.
1662
1737
  * @param {KeyvEntry<KeyvValue<Value>>[]} entries the raw entries to set
1663
- * @returns {boolean[]} will return an array of booleans if it sets then it will return a true. On failure will return false.
1738
+ * @returns {Promise<boolean[]>} an array of booleans, one per entry: `true` if set successfully, `false` on failure.
1664
1739
  */
1665
1740
  async setManyRaw(entries) {
1666
1741
  entries = entries.map((e) => ({
1667
1742
  ...e,
1743
+ /* v8 ignore next -- @preserve */
1668
1744
  key: this._sanitize.enabled ? this._sanitize.cleanKey(e.key) : e.key
1669
1745
  }));
1670
1746
  let results = [];
1671
- await this.hookWithDeprecated(KeyvHooks.BEFORE_SET_MANY_RAW, { entries });
1747
+ await this.hookWithDeprecated("before:setManyRaw", { entries });
1672
1748
  try {
1673
1749
  const rawEntries = await Promise.all(entries.map(async ({ key, value }) => {
1674
- const ttl = ttlFromExpires(value.expires);
1675
1750
  return {
1676
1751
  key,
1677
1752
  value: await this.encode(value),
1678
- ttl
1753
+ expires: value.expires
1679
1754
  };
1680
1755
  }));
1681
1756
  const storeResult = await this._store.setMany(rawEntries);
1682
1757
  results = Array.isArray(storeResult) ? storeResult : entries.map(() => true);
1683
- this.emitTelemetry(KeyvEvents.STAT_SET, entries.map((e) => e.key));
1758
+ this.emitTelemetry("stat:set", entries.map((e) => e.key));
1684
1759
  } catch (error) {
1685
- this.emit(KeyvEvents.ERROR, error);
1686
- this.emitTelemetry(KeyvEvents.STAT_ERROR, entries.map((e) => e.key));
1760
+ this.emit("error", error);
1761
+ this.emitTelemetry("stat:error", entries.map((e) => e.key));
1687
1762
  results = entries.map(() => false);
1688
1763
  }
1689
- await this.hookWithDeprecated(KeyvHooks.AFTER_SET_MANY_RAW, {
1764
+ await this.hookWithDeprecated("after:setManyRaw", {
1690
1765
  entries,
1691
1766
  results
1692
1767
  });
@@ -1696,46 +1771,46 @@ var Keyv = class Keyv extends hookified.Hookified {
1696
1771
  if (Array.isArray(key)) return this.deleteMany(key);
1697
1772
  key = this._sanitize.enabled ? this._sanitize.cleanKey(key) : key;
1698
1773
  if (key === "") return false;
1699
- await this.hookWithDeprecated(KeyvHooks.BEFORE_DELETE, { key });
1774
+ await this.hookWithDeprecated("before:delete", { key });
1700
1775
  let result = true;
1701
1776
  try {
1702
1777
  result = await this._store.delete(key);
1703
1778
  } catch (error) {
1704
1779
  result = false;
1705
- this.emit(KeyvEvents.ERROR, error);
1706
- this.emitTelemetry(KeyvEvents.STAT_ERROR, key);
1780
+ this.emit("error", error);
1781
+ this.emitTelemetry("stat:error", key);
1707
1782
  }
1708
- await this.hookWithDeprecated(KeyvHooks.AFTER_DELETE, {
1783
+ await this.hookWithDeprecated("after:delete", {
1709
1784
  key,
1710
1785
  value: result
1711
1786
  });
1712
- this.emitTelemetry(KeyvEvents.STAT_DELETE, key);
1787
+ this.emitTelemetry("stat:delete", key);
1713
1788
  return result;
1714
1789
  }
1715
1790
  /**
1716
1791
  * Delete many items from the store
1717
1792
  * @param {string[]} keys the keys to be deleted
1718
- * @returns {boolean[]} array of booleans indicating success for each key
1793
+ * @returns {Promise<boolean[]>} an array of booleans indicating success for each key.
1719
1794
  */
1720
1795
  async deleteMany(keys) {
1721
1796
  /* v8 ignore next -- @preserve */
1722
1797
  keys = this._sanitize.enabled ? this._sanitize.cleanKeys(keys) : keys;
1723
- await this.hookWithDeprecated(KeyvHooks.BEFORE_DELETE_MANY, { keys });
1724
- await this.hookWithDeprecated(KeyvHooks.BEFORE_DELETE, { key: keys });
1798
+ await this.hookWithDeprecated("before:deleteMany", { keys });
1799
+ await this.hookWithDeprecated("before:delete", { key: keys });
1725
1800
  let results;
1726
1801
  try {
1727
1802
  results = await this._store.deleteMany(keys);
1728
- this.emitTelemetry(KeyvEvents.STAT_DELETE, keys);
1803
+ this.emitTelemetry("stat:delete", keys);
1729
1804
  } catch (error) {
1730
- this.emit(KeyvEvents.ERROR, error);
1731
- this.emitTelemetry(KeyvEvents.STAT_ERROR, keys);
1805
+ this.emit("error", error);
1806
+ this.emitTelemetry("stat:error", keys);
1732
1807
  results = keys.map(() => false);
1733
1808
  }
1734
- await this.hookWithDeprecated(KeyvHooks.AFTER_DELETE_MANY, {
1809
+ await this.hookWithDeprecated("after:deleteMany", {
1735
1810
  keys,
1736
1811
  values: results
1737
1812
  });
1738
- await this.hookWithDeprecated(KeyvHooks.AFTER_DELETE, {
1813
+ await this.hookWithDeprecated("after:delete", {
1739
1814
  key: keys,
1740
1815
  value: results
1741
1816
  });
@@ -1745,7 +1820,7 @@ var Keyv = class Keyv extends hookified.Hookified {
1745
1820
  if (Array.isArray(key)) return this.hasMany(key);
1746
1821
  key = this._sanitize.enabled ? this._sanitize.cleanKey(key) : key;
1747
1822
  if (key === "") return false;
1748
- await this.hookWithDeprecated(KeyvHooks.BEFORE_HAS, { key });
1823
+ await this.hookWithDeprecated("before:has", { key });
1749
1824
  let result = false;
1750
1825
  try {
1751
1826
  if (this._checkExpired) {
@@ -1756,10 +1831,10 @@ var Keyv = class Keyv extends hookified.Hookified {
1756
1831
  }
1757
1832
  } else result = await this._store.has(key);
1758
1833
  } catch (error) {
1759
- this.emit(KeyvEvents.ERROR, error);
1760
- this.emitTelemetry(KeyvEvents.STAT_ERROR, key);
1834
+ this.emit("error", error);
1835
+ this.emitTelemetry("stat:error", key);
1761
1836
  }
1762
- await this.hookWithDeprecated(KeyvHooks.AFTER_HAS, {
1837
+ await this.hookWithDeprecated("after:has", {
1763
1838
  key,
1764
1839
  value: result
1765
1840
  });
@@ -1768,11 +1843,11 @@ var Keyv = class Keyv extends hookified.Hookified {
1768
1843
  /**
1769
1844
  * Check if many keys exist
1770
1845
  * @param {string[]} keys the keys to check
1771
- * @returns {boolean[]} will return an array of booleans if the keys exist
1846
+ * @returns {Promise<boolean[]>} an array of booleans in the same order as the keys, `true` if the key exists.
1772
1847
  */
1773
1848
  async hasMany(keys) {
1774
1849
  keys = this._sanitize.enabled ? this._sanitize.cleanKeys(keys) : keys;
1775
- await this.hookWithDeprecated(KeyvHooks.BEFORE_HAS_MANY, { keys });
1850
+ await this.hookWithDeprecated("before:hasMany", { keys });
1776
1851
  let results = [];
1777
1852
  try {
1778
1853
  if (this._checkExpired) {
@@ -1780,30 +1855,31 @@ var Keyv = class Keyv extends hookified.Hookified {
1780
1855
  results = (await this.decodeWithExpire(keys, rawData)).map((row) => row !== void 0);
1781
1856
  } else results = await this._store.hasMany(keys);
1782
1857
  } catch (error) {
1783
- this.emit(KeyvEvents.ERROR, error);
1784
- this.emitTelemetry(KeyvEvents.STAT_ERROR, keys);
1858
+ this.emit("error", error);
1859
+ this.emitTelemetry("stat:error", keys);
1785
1860
  results = keys.map(() => false);
1786
1861
  }
1787
- await this.hookWithDeprecated(KeyvHooks.AFTER_HAS_MANY, {
1862
+ await this.hookWithDeprecated("after:hasMany", {
1788
1863
  keys,
1789
1864
  values: results
1790
1865
  });
1791
1866
  return results;
1792
1867
  }
1793
1868
  /**
1794
- * Clear the store
1795
- * @returns {void}
1869
+ * Clear the store. If a namespace is set only entries in that namespace are removed.
1870
+ * Emits a `clear` event.
1871
+ * @returns {Promise<void>} resolves once the entries have been cleared.
1796
1872
  */
1797
1873
  async clear() {
1798
1874
  this.emit("clear");
1799
- await this.hook(KeyvHooks.BEFORE_CLEAR, { namespace: this._namespace });
1875
+ await this.hook("before:clear", { namespace: this._namespace });
1800
1876
  try {
1801
1877
  await this._store.clear();
1802
1878
  } catch (error) {
1803
- this.emit(KeyvEvents.ERROR, error);
1804
- this.emitTelemetry(KeyvEvents.STAT_ERROR);
1879
+ this.emit("error", error);
1880
+ this.emitTelemetry("stat:error");
1805
1881
  }
1806
- await this.hook(KeyvHooks.AFTER_CLEAR, { namespace: this._namespace });
1882
+ await this.hook("after:clear", { namespace: this._namespace });
1807
1883
  }
1808
1884
  /**
1809
1885
  * Will disconnect the store. This is only available if the store has a disconnect method
@@ -1811,13 +1887,13 @@ var Keyv = class Keyv extends hookified.Hookified {
1811
1887
  */
1812
1888
  async disconnect() {
1813
1889
  this.emit("disconnect");
1814
- await this.hook(KeyvHooks.BEFORE_DISCONNECT, { namespace: this._namespace });
1890
+ await this.hook("before:disconnect", { namespace: this._namespace });
1815
1891
  try {
1816
1892
  if (this._store.disconnect) await this._store.disconnect();
1817
1893
  } catch (error) {
1818
- this.emit(KeyvEvents.ERROR, error);
1894
+ this.emit("error", error);
1819
1895
  }
1820
- await this.hook(KeyvHooks.AFTER_DISCONNECT, { namespace: this._namespace });
1896
+ await this.hook("after:disconnect", { namespace: this._namespace });
1821
1897
  }
1822
1898
  /**
1823
1899
  * Iterate over all key-value pairs in the store. Automatically deserializes values,
@@ -1865,7 +1941,7 @@ var Keyv = class Keyv extends hookified.Hookified {
1865
1941
  if (typeof result === "string") return await this._serialization.parse(result);
1866
1942
  return result;
1867
1943
  } catch (error) {
1868
- this.emit(KeyvEvents.ERROR, error);
1944
+ this.emit("error", error);
1869
1945
  return;
1870
1946
  }
1871
1947
  }
@@ -2008,10 +2084,14 @@ var KeyvMemoryAdapter = class extends hookified.Hookified {
2008
2084
  if (options?.namespace) this._namespace = options?.namespace;
2009
2085
  }
2010
2086
  /**
2011
- * Gets the detected capabilities of the underlying store.
2087
+ * Gets the capabilities of the underlying store, with `expires: true` to declare that
2088
+ * this adapter accepts an absolute `expires` timestamp (the v6 storage contract).
2012
2089
  */
2013
2090
  get capabilities() {
2014
- return this._capabilities;
2091
+ return {
2092
+ ...this._capabilities,
2093
+ expires: true
2094
+ };
2015
2095
  }
2016
2096
  /**
2017
2097
  * Gets the underlying store instance.
@@ -2088,24 +2168,24 @@ var KeyvMemoryAdapter = class extends hookified.Hookified {
2088
2168
  return entry.value;
2089
2169
  }
2090
2170
  /**
2091
- * Stores a value in the store with an optional TTL.
2171
+ * Stores a value in the store with an optional absolute expiry.
2092
2172
  * @param key - The key to store the value under
2093
2173
  * @param value - The value to store
2094
- * @param ttl - Optional time-to-live in milliseconds
2174
+ * @param expires - Optional absolute expiry as Unix ms since epoch
2095
2175
  * @returns Always returns true indicating success
2096
2176
  */
2097
- async set(key, value, ttl) {
2177
+ async set(key, value, expires) {
2098
2178
  const keyPrefix = this.getKeyPrefix(key, this._namespace);
2099
2179
  const entry = {
2100
2180
  value,
2101
- expires: ttl ? Date.now() + ttl : void 0
2181
+ expires: typeof expires === "number" ? expires : void 0
2102
2182
  };
2103
- this._store.set(keyPrefix, entry, ttl);
2183
+ this._store.set(keyPrefix, entry, ttlFromExpires(expires));
2104
2184
  return true;
2105
2185
  }
2106
2186
  /**
2107
2187
  * Stores multiple entries in the store at once.
2108
- * @param entries - Array of entries containing key, value, and optional TTL
2188
+ * @param entries - Array of entries containing key, value, and optional absolute `expires`
2109
2189
  */
2110
2190
  async setMany(entries) {
2111
2191
  const results = [];
@@ -2113,9 +2193,9 @@ var KeyvMemoryAdapter = class extends hookified.Hookified {
2113
2193
  const keyPrefix = this.getKeyPrefix(entry.key, this._namespace);
2114
2194
  const memEntry = {
2115
2195
  value: entry.value,
2116
- expires: entry.ttl ? Date.now() + entry.ttl : void 0
2196
+ expires: typeof entry.expires === "number" ? entry.expires : void 0
2117
2197
  };
2118
- this._store.set(keyPrefix, memEntry, entry.ttl);
2198
+ this._store.set(keyPrefix, memEntry, ttlFromExpires(entry.expires));
2119
2199
  results.push(true);
2120
2200
  }
2121
2201
  return results;
@@ -2205,7 +2285,7 @@ var KeyvMemoryAdapter = class extends hookified.Hookified {
2205
2285
  this._store.delete(keyPrefix);
2206
2286
  results.push(existed);
2207
2287
  } catch (error) {
2208
- this.emit(KeyvEvents.ERROR, error);
2288
+ this.emit("error", error);
2209
2289
  results.push(false);
2210
2290
  }
2211
2291
  return results;
@@ -2284,3 +2364,4 @@ exports.detectKeyvEncryption = detectKeyvEncryption;
2284
2364
  exports.detectKeyvSerialization = detectKeyvSerialization;
2285
2365
  exports.detectKeyvStorage = detectKeyvStorage;
2286
2366
  exports.jsonSerializer = jsonSerializer;
2367
+ exports.keyvStorageCapability = keyvStorageCapability;