keyv 6.0.0-beta.3 → 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/LICENSE +0 -10
- package/README.md +203 -136
- package/dist/index.cjs +162 -82
- package/dist/index.d.cts +158 -61
- package/dist/index.d.mts +158 -61
- package/dist/index.mjs +162 -83
- package/package.json +1 -1
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
|
|
@@ -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,9 +512,11 @@ 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.
|
|
519
|
+
if (this._storeHandlesNamespace) this._store.namespace = this._namespace;
|
|
492
520
|
if (typeof store.on === "function") store.on("error", (error) => this.emit("error", error));
|
|
493
521
|
}
|
|
494
522
|
/**
|
|
@@ -504,10 +532,15 @@ var KeyvBridgeAdapter = class extends hookified.Hookified {
|
|
|
504
532
|
this._store = store;
|
|
505
533
|
}
|
|
506
534
|
/**
|
|
507
|
-
* Gets the
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
656
|
+
async set(key, value, expires) {
|
|
615
657
|
const keyPrefix = this.getKeyPrefix(key, this._namespace);
|
|
616
|
-
|
|
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
|
|
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
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
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.
|
|
686
|
+
await this.set(entry.key, entry.value, entry.expires);
|
|
637
687
|
results.push(true);
|
|
638
688
|
}
|
|
639
689
|
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,19 +1421,32 @@ var Keyv = class Keyv extends hookified.Hookified {
|
|
|
1374
1421
|
this._stats.subscribe(this);
|
|
1375
1422
|
}
|
|
1376
1423
|
/**
|
|
1377
|
-
*
|
|
1378
|
-
*
|
|
1379
|
-
*
|
|
1380
|
-
|
|
1381
|
-
|
|
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
1452
|
this.emit("error", /* @__PURE__ */ new Error("Could not use the provided storage adapter, falling back to KeyvMemoryAdapter with Map"));
|
|
@@ -1444,13 +1504,27 @@ var Keyv = class Keyv extends hookified.Hookified {
|
|
|
1444
1504
|
return data.value;
|
|
1445
1505
|
}
|
|
1446
1506
|
/**
|
|
1447
|
-
*
|
|
1448
|
-
*
|
|
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
1526
|
await this.hookWithDeprecated("before:getMany", { keys });
|
|
1453
|
-
const rawData = await this.
|
|
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) => {
|
|
@@ -1509,7 +1583,7 @@ var Keyv = class Keyv extends hookified.Hookified {
|
|
|
1509
1583
|
});
|
|
1510
1584
|
return result;
|
|
1511
1585
|
}
|
|
1512
|
-
const rawData = await this.
|
|
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) => {
|
|
@@ -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
|
|
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
|
|
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;
|
|
@@ -1555,7 +1629,7 @@ 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,
|
|
1632
|
+
result = await this._store.set(data.key, encodedValue, expires);
|
|
1559
1633
|
} catch (error) {
|
|
1560
1634
|
result = false;
|
|
1561
1635
|
this.emit("error", error);
|
|
@@ -1572,7 +1646,7 @@ var Keyv = class Keyv extends hookified.Hookified {
|
|
|
1572
1646
|
/**
|
|
1573
1647
|
* Set many items to the store
|
|
1574
1648
|
* @param {Array<KeyvEntry<Value>>} entries the entries to set
|
|
1575
|
-
* @returns {boolean[]}
|
|
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) => ({
|
|
@@ -1601,7 +1675,7 @@ var Keyv = class Keyv extends hookified.Hookified {
|
|
|
1601
1675
|
return {
|
|
1602
1676
|
key,
|
|
1603
1677
|
value: await this.encode(formattedValue),
|
|
1604
|
-
|
|
1678
|
+
expires
|
|
1605
1679
|
};
|
|
1606
1680
|
}));
|
|
1607
1681
|
const storeResult = await this._store.setMany(serializedEntries);
|
|
@@ -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
|
|
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;
|
|
@@ -1636,11 +1710,12 @@ var Keyv = class Keyv extends hookified.Hookified {
|
|
|
1636
1710
|
value
|
|
1637
1711
|
};
|
|
1638
1712
|
await this.hookWithDeprecated("before:setRaw", data);
|
|
1639
|
-
const
|
|
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,
|
|
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;
|
|
@@ -1660,7 +1735,7 @@ 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[]}
|
|
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) => ({
|
|
@@ -1672,11 +1747,10 @@ var Keyv = class Keyv extends hookified.Hookified {
|
|
|
1672
1747
|
await this.hookWithDeprecated("before:setManyRaw", { entries });
|
|
1673
1748
|
try {
|
|
1674
1749
|
const rawEntries = await Promise.all(entries.map(async ({ key, value }) => {
|
|
1675
|
-
const ttl = ttlFromExpires(value.expires);
|
|
1676
1750
|
return {
|
|
1677
1751
|
key,
|
|
1678
1752
|
value: await this.encode(value),
|
|
1679
|
-
|
|
1753
|
+
expires: value.expires
|
|
1680
1754
|
};
|
|
1681
1755
|
}));
|
|
1682
1756
|
const storeResult = await this._store.setMany(rawEntries);
|
|
@@ -1716,7 +1790,7 @@ var Keyv = class Keyv extends hookified.Hookified {
|
|
|
1716
1790
|
/**
|
|
1717
1791
|
* Delete many items from the store
|
|
1718
1792
|
* @param {string[]} keys the keys to be deleted
|
|
1719
|
-
* @returns {boolean[]} array of booleans indicating success for each key
|
|
1793
|
+
* @returns {Promise<boolean[]>} an array of booleans indicating success for each key.
|
|
1720
1794
|
*/
|
|
1721
1795
|
async deleteMany(keys) {
|
|
1722
1796
|
/* v8 ignore next -- @preserve */
|
|
@@ -1769,7 +1843,7 @@ var Keyv = class Keyv extends hookified.Hookified {
|
|
|
1769
1843
|
/**
|
|
1770
1844
|
* Check if many keys exist
|
|
1771
1845
|
* @param {string[]} keys the keys to check
|
|
1772
|
-
* @returns {boolean[]}
|
|
1846
|
+
* @returns {Promise<boolean[]>} an array of booleans in the same order as the keys, `true` if the key exists.
|
|
1773
1847
|
*/
|
|
1774
1848
|
async hasMany(keys) {
|
|
1775
1849
|
keys = this._sanitize.enabled ? this._sanitize.cleanKeys(keys) : keys;
|
|
@@ -1792,8 +1866,9 @@ var Keyv = class Keyv extends hookified.Hookified {
|
|
|
1792
1866
|
return results;
|
|
1793
1867
|
}
|
|
1794
1868
|
/**
|
|
1795
|
-
* Clear the store
|
|
1796
|
-
*
|
|
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.
|
|
1797
1872
|
*/
|
|
1798
1873
|
async clear() {
|
|
1799
1874
|
this.emit("clear");
|
|
@@ -2009,10 +2084,14 @@ var KeyvMemoryAdapter = class extends hookified.Hookified {
|
|
|
2009
2084
|
if (options?.namespace) this._namespace = options?.namespace;
|
|
2010
2085
|
}
|
|
2011
2086
|
/**
|
|
2012
|
-
* Gets the
|
|
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).
|
|
2013
2089
|
*/
|
|
2014
2090
|
get capabilities() {
|
|
2015
|
-
return
|
|
2091
|
+
return {
|
|
2092
|
+
...this._capabilities,
|
|
2093
|
+
expires: true
|
|
2094
|
+
};
|
|
2016
2095
|
}
|
|
2017
2096
|
/**
|
|
2018
2097
|
* Gets the underlying store instance.
|
|
@@ -2089,24 +2168,24 @@ var KeyvMemoryAdapter = class extends hookified.Hookified {
|
|
|
2089
2168
|
return entry.value;
|
|
2090
2169
|
}
|
|
2091
2170
|
/**
|
|
2092
|
-
* Stores a value in the store with an optional
|
|
2171
|
+
* Stores a value in the store with an optional absolute expiry.
|
|
2093
2172
|
* @param key - The key to store the value under
|
|
2094
2173
|
* @param value - The value to store
|
|
2095
|
-
* @param
|
|
2174
|
+
* @param expires - Optional absolute expiry as Unix ms since epoch
|
|
2096
2175
|
* @returns Always returns true indicating success
|
|
2097
2176
|
*/
|
|
2098
|
-
async set(key, value,
|
|
2177
|
+
async set(key, value, expires) {
|
|
2099
2178
|
const keyPrefix = this.getKeyPrefix(key, this._namespace);
|
|
2100
2179
|
const entry = {
|
|
2101
2180
|
value,
|
|
2102
|
-
expires:
|
|
2181
|
+
expires: typeof expires === "number" ? expires : void 0
|
|
2103
2182
|
};
|
|
2104
|
-
this._store.set(keyPrefix, entry,
|
|
2183
|
+
this._store.set(keyPrefix, entry, ttlFromExpires(expires));
|
|
2105
2184
|
return true;
|
|
2106
2185
|
}
|
|
2107
2186
|
/**
|
|
2108
2187
|
* Stores multiple entries in the store at once.
|
|
2109
|
-
* @param entries - Array of entries containing key, value, and optional
|
|
2188
|
+
* @param entries - Array of entries containing key, value, and optional absolute `expires`
|
|
2110
2189
|
*/
|
|
2111
2190
|
async setMany(entries) {
|
|
2112
2191
|
const results = [];
|
|
@@ -2114,9 +2193,9 @@ var KeyvMemoryAdapter = class extends hookified.Hookified {
|
|
|
2114
2193
|
const keyPrefix = this.getKeyPrefix(entry.key, this._namespace);
|
|
2115
2194
|
const memEntry = {
|
|
2116
2195
|
value: entry.value,
|
|
2117
|
-
expires: entry.
|
|
2196
|
+
expires: typeof entry.expires === "number" ? entry.expires : void 0
|
|
2118
2197
|
};
|
|
2119
|
-
this._store.set(keyPrefix, memEntry, entry.
|
|
2198
|
+
this._store.set(keyPrefix, memEntry, ttlFromExpires(entry.expires));
|
|
2120
2199
|
results.push(true);
|
|
2121
2200
|
}
|
|
2122
2201
|
return results;
|
|
@@ -2285,3 +2364,4 @@ exports.detectKeyvEncryption = detectKeyvEncryption;
|
|
|
2285
2364
|
exports.detectKeyvSerialization = detectKeyvSerialization;
|
|
2286
2365
|
exports.detectKeyvStorage = detectKeyvStorage;
|
|
2287
2366
|
exports.jsonSerializer = jsonSerializer;
|
|
2367
|
+
exports.keyvStorageCapability = keyvStorageCapability;
|