encore.dev 1.54.2 → 1.56.0
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/config/secrets.ts +7 -1
- package/dist/config/secrets.js +4 -0
- package/dist/config/secrets.js.map +1 -1
- package/dist/internal/runtime/napi/napi.cjs +3 -1
- package/dist/internal/runtime/napi/napi.d.cts +114 -1
- package/dist/storage/cache/basic.d.ts +268 -0
- package/dist/storage/cache/basic.js +383 -0
- package/dist/storage/cache/basic.js.map +1 -0
- package/dist/storage/cache/cluster.d.ts +48 -0
- package/dist/storage/cache/cluster.js +40 -0
- package/dist/storage/cache/cluster.js.map +1 -0
- package/dist/storage/cache/errors.d.ts +19 -0
- package/dist/storage/cache/errors.js +59 -0
- package/dist/storage/cache/errors.js.map +1 -0
- package/dist/storage/cache/expiry.d.ts +55 -0
- package/dist/storage/cache/expiry.js +74 -0
- package/dist/storage/cache/expiry.js.map +1 -0
- package/dist/storage/cache/keyspace.d.ts +77 -0
- package/dist/storage/cache/keyspace.js +100 -0
- package/dist/storage/cache/keyspace.js.map +1 -0
- package/dist/storage/cache/list.d.ts +249 -0
- package/dist/storage/cache/list.js +376 -0
- package/dist/storage/cache/list.js.map +1 -0
- package/dist/storage/cache/mod.d.ts +10 -0
- package/dist/storage/cache/mod.js +13 -0
- package/dist/storage/cache/mod.js.map +1 -0
- package/dist/storage/cache/set.d.ts +258 -0
- package/dist/storage/cache/set.js +411 -0
- package/dist/storage/cache/set.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/internal/runtime/napi/napi.cjs +3 -1
- package/internal/runtime/napi/napi.d.cts +114 -1
- package/package.json +6 -1
- package/storage/cache/basic.ts +511 -0
- package/storage/cache/cluster.ts +67 -0
- package/storage/cache/errors.ts +66 -0
- package/storage/cache/expiry.ts +98 -0
- package/storage/cache/keyspace.ts +142 -0
- package/storage/cache/list.ts +496 -0
- package/storage/cache/mod.ts +36 -0
- package/storage/cache/set.ts +491 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* expireIn sets the cache entry to expire after the specified duration.
|
|
3
|
+
* @param ms - Duration in milliseconds
|
|
4
|
+
*/
|
|
5
|
+
export function expireIn(ms) {
|
|
6
|
+
return { type: "duration", durationMs: ms };
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* expireInSeconds sets the cache entry to expire after the specified seconds.
|
|
10
|
+
* @param seconds - Duration in seconds
|
|
11
|
+
*/
|
|
12
|
+
export function expireInSeconds(seconds) {
|
|
13
|
+
return { type: "duration", durationMs: seconds * 1000 };
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* expireInMinutes sets the cache entry to expire after the specified minutes.
|
|
17
|
+
* @param minutes - Duration in minutes
|
|
18
|
+
*/
|
|
19
|
+
export function expireInMinutes(minutes) {
|
|
20
|
+
return { type: "duration", durationMs: minutes * 60 * 1000 };
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* expireInHours sets the cache entry to expire after the specified hours.
|
|
24
|
+
* @param hours - Duration in hours
|
|
25
|
+
*/
|
|
26
|
+
export function expireInHours(hours) {
|
|
27
|
+
return { type: "duration", durationMs: hours * 60 * 60 * 1000 };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* expireDailyAt sets the cache entry to expire at a specific time each day (UTC).
|
|
31
|
+
* @param hours - Hour (0-23)
|
|
32
|
+
* @param minutes - Minutes (0-59)
|
|
33
|
+
* @param seconds - Seconds (0-59)
|
|
34
|
+
*/
|
|
35
|
+
export function expireDailyAt(hours, minutes, seconds) {
|
|
36
|
+
return { type: "time", hours, minutes, seconds };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* neverExpire sets the cache entry to never expire.
|
|
40
|
+
* Note: Redis may still evict the key based on the eviction policy.
|
|
41
|
+
*/
|
|
42
|
+
export const neverExpire = "never";
|
|
43
|
+
/**
|
|
44
|
+
* keepTTL preserves the existing TTL when updating a cache entry.
|
|
45
|
+
* If the key doesn't exist, no TTL is set.
|
|
46
|
+
*/
|
|
47
|
+
export const keepTTL = "keep-ttl";
|
|
48
|
+
/**
|
|
49
|
+
* Resolves an Expiry to a duration in milliseconds, "never", or "keep-ttl".
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
|
+
export function resolveExpiry(expiry) {
|
|
53
|
+
switch (expiry) {
|
|
54
|
+
case "never":
|
|
55
|
+
return "never";
|
|
56
|
+
case "keep-ttl":
|
|
57
|
+
return "keep-ttl";
|
|
58
|
+
}
|
|
59
|
+
switch (expiry.type) {
|
|
60
|
+
case "duration":
|
|
61
|
+
return expiry.durationMs;
|
|
62
|
+
case "time": {
|
|
63
|
+
const now = new Date();
|
|
64
|
+
const target = new Date(now);
|
|
65
|
+
target.setUTCHours(expiry.hours, expiry.minutes, expiry.seconds, 0);
|
|
66
|
+
// If target time has passed today, set for tomorrow
|
|
67
|
+
if (target.getTime() <= now.getTime()) {
|
|
68
|
+
target.setUTCDate(target.getUTCDate() + 1);
|
|
69
|
+
}
|
|
70
|
+
return target.getTime() - now.getTime();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=expiry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expiry.js","sourceRoot":"","sources":["../../../storage/cache/expiry.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAU;IACjC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,GAAG,IAAI,EAAE,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;AAC/D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;AAClE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAC3B,KAAa,EACb,OAAe,EACf,OAAe;IAEf,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AACnD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAW,OAAO,CAAC;AAE3C;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAAW,UAAU,CAAC;AAE1C;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO;YACV,OAAO,OAAO,CAAC;QACjB,KAAK,UAAU;YACb,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,UAAU;YACb,OAAO,MAAM,CAAC,UAAU,CAAC;QAE3B,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;YAC7B,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAEpE,oDAAoD;YACpD,IAAI,MAAM,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;gBACtC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;YAC7C,CAAC;YAED,OAAO,MAAM,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;QAC1C,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { CacheCluster } from "./cluster.js";
|
|
2
|
+
import { Expiry } from "./expiry.js";
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for a cache keyspace.
|
|
5
|
+
*/
|
|
6
|
+
export interface KeyspaceConfig<K> {
|
|
7
|
+
/**
|
|
8
|
+
* The pattern for generating cache keys.
|
|
9
|
+
* Use `:fieldName` to include a field from the key type.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // For a simple key type (string, number)
|
|
13
|
+
* keyPattern: "user/:id"
|
|
14
|
+
*
|
|
15
|
+
* // For a struct key type
|
|
16
|
+
* keyPattern: "user/:userId/region/:region"
|
|
17
|
+
*/
|
|
18
|
+
keyPattern: string;
|
|
19
|
+
/**
|
|
20
|
+
* Default expiry for cache entries in this keyspace.
|
|
21
|
+
* If not set, entries do not expire.
|
|
22
|
+
*/
|
|
23
|
+
defaultExpiry?: Expiry;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Options for write operations.
|
|
27
|
+
*/
|
|
28
|
+
export interface WriteOptions {
|
|
29
|
+
/**
|
|
30
|
+
* Expiry for this specific write operation.
|
|
31
|
+
* Overrides the keyspace's defaultExpiry.
|
|
32
|
+
*/
|
|
33
|
+
expiry?: Expiry;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Base class for all keyspace types (basic, list, set).
|
|
37
|
+
* Provides key mapping, TTL resolution, with(), and delete().
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
export declare abstract class Keyspace<K> {
|
|
41
|
+
protected readonly cluster: CacheCluster;
|
|
42
|
+
protected readonly config: KeyspaceConfig<K>;
|
|
43
|
+
protected readonly keyMapper: (key: K) => string;
|
|
44
|
+
private _effectiveExpiry?;
|
|
45
|
+
constructor(cluster: CacheCluster, config: KeyspaceConfig<K>);
|
|
46
|
+
/**
|
|
47
|
+
* Creates a key mapper by parsing the key pattern.
|
|
48
|
+
*/
|
|
49
|
+
private createKeyMapper;
|
|
50
|
+
/**
|
|
51
|
+
* Maps a key to its Redis key string.
|
|
52
|
+
*/
|
|
53
|
+
protected mapKey(key: K): string;
|
|
54
|
+
/**
|
|
55
|
+
* Resolves the TTL for a write operation.
|
|
56
|
+
* Returns i64 sentinel for NAPI: undefined=no config, -1=KeepTTL, -2=Persist/NeverExpire, >=0=ms
|
|
57
|
+
*/
|
|
58
|
+
protected resolveTtl(options?: WriteOptions): number | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Returns a shallow clone of this keyspace with the specified write options applied.
|
|
61
|
+
* This allows setting expiry for a chain of operations.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* await myKeyspace.with({ expiry: expireIn(5000) }).set(key, value);
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
with(options: WriteOptions): this;
|
|
69
|
+
/**
|
|
70
|
+
* Deletes the specified keys.
|
|
71
|
+
* If a key does not exist it is ignored.
|
|
72
|
+
*
|
|
73
|
+
* @returns The number of keys that were deleted.
|
|
74
|
+
* @see https://redis.io/commands/del/
|
|
75
|
+
*/
|
|
76
|
+
delete(...keys: K[]): Promise<number>;
|
|
77
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { getCurrentRequest } from "../../internal/reqtrack/mod.js";
|
|
2
|
+
import { resolveExpiry } from "./expiry.js";
|
|
3
|
+
/**
|
|
4
|
+
* Base class for all keyspace types (basic, list, set).
|
|
5
|
+
* Provides key mapping, TTL resolution, with(), and delete().
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export class Keyspace {
|
|
9
|
+
cluster;
|
|
10
|
+
config;
|
|
11
|
+
keyMapper;
|
|
12
|
+
_effectiveExpiry;
|
|
13
|
+
constructor(cluster, config) {
|
|
14
|
+
this.cluster = cluster;
|
|
15
|
+
this.config = config;
|
|
16
|
+
this.keyMapper = this.createKeyMapper(config.keyPattern);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a key mapper by parsing the key pattern.
|
|
20
|
+
*/
|
|
21
|
+
createKeyMapper(pattern) {
|
|
22
|
+
const segments = pattern.split("/").map((seg) => {
|
|
23
|
+
if (seg.startsWith(":")) {
|
|
24
|
+
return { isLiteral: false, value: seg.slice(1), field: seg.slice(1) };
|
|
25
|
+
}
|
|
26
|
+
return { isLiteral: true, value: seg };
|
|
27
|
+
});
|
|
28
|
+
return (key) => {
|
|
29
|
+
return segments
|
|
30
|
+
.map((seg) => {
|
|
31
|
+
if (seg.isLiteral)
|
|
32
|
+
return seg.value;
|
|
33
|
+
let val;
|
|
34
|
+
if (typeof key === "object" && key !== null && seg.field) {
|
|
35
|
+
val = key[seg.field];
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
val = key;
|
|
39
|
+
}
|
|
40
|
+
// Escape forward slashes in string values
|
|
41
|
+
const str = String(val);
|
|
42
|
+
return str.replace(/\//g, "\\/");
|
|
43
|
+
})
|
|
44
|
+
.join("/");
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Maps a key to its Redis key string.
|
|
49
|
+
*/
|
|
50
|
+
mapKey(key) {
|
|
51
|
+
const mapped = this.keyMapper(key);
|
|
52
|
+
if (mapped.startsWith("__encore")) {
|
|
53
|
+
throw new Error('use of reserved key prefix "__encore"');
|
|
54
|
+
}
|
|
55
|
+
return mapped;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Resolves the TTL for a write operation.
|
|
59
|
+
* Returns i64 sentinel for NAPI: undefined=no config, -1=KeepTTL, -2=Persist/NeverExpire, >=0=ms
|
|
60
|
+
*/
|
|
61
|
+
resolveTtl(options) {
|
|
62
|
+
const expiry = options?.expiry ?? this._effectiveExpiry ?? this.config.defaultExpiry;
|
|
63
|
+
if (!expiry)
|
|
64
|
+
return undefined;
|
|
65
|
+
const resolved = resolveExpiry(expiry);
|
|
66
|
+
if (resolved === "keep-ttl")
|
|
67
|
+
return -1; // KeepTTL
|
|
68
|
+
if (resolved === "never")
|
|
69
|
+
return -2; // NeverExpire → Persist
|
|
70
|
+
return resolved; // milliseconds
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Returns a shallow clone of this keyspace with the specified write options applied.
|
|
74
|
+
* This allows setting expiry for a chain of operations.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* await myKeyspace.with({ expiry: expireIn(5000) }).set(key, value);
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
with(options) {
|
|
82
|
+
const clone = Object.create(Object.getPrototypeOf(this));
|
|
83
|
+
Object.assign(clone, this);
|
|
84
|
+
clone._effectiveExpiry = options.expiry ?? this._effectiveExpiry;
|
|
85
|
+
return clone;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Deletes the specified keys.
|
|
89
|
+
* If a key does not exist it is ignored.
|
|
90
|
+
*
|
|
91
|
+
* @returns The number of keys that were deleted.
|
|
92
|
+
* @see https://redis.io/commands/del/
|
|
93
|
+
*/
|
|
94
|
+
async delete(...keys) {
|
|
95
|
+
const source = getCurrentRequest();
|
|
96
|
+
const mappedKeys = keys.map((k) => this.mapKey(k));
|
|
97
|
+
return await this.cluster.impl.delete(mappedKeys, source);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=keyspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyspace.js","sourceRoot":"","sources":["../../../storage/cache/keyspace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { CacheCluster } from "./cluster.js";
|
|
3
|
+
import { Keyspace, KeyspaceConfig, WriteOptions } from "./keyspace.js";
|
|
4
|
+
/**
|
|
5
|
+
* Position in a list (left/head or right/tail).
|
|
6
|
+
*/
|
|
7
|
+
export type ListPosition = "left" | "right";
|
|
8
|
+
/**
|
|
9
|
+
* Base class for list keyspaces with all list operations.
|
|
10
|
+
* Subclasses provide typed serialization/deserialization.
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
declare abstract class ListKeyspace<K, V> extends Keyspace<K> {
|
|
14
|
+
constructor(cluster: CacheCluster, config: KeyspaceConfig<K>);
|
|
15
|
+
protected abstract serializeItem(value: V): Buffer;
|
|
16
|
+
protected abstract deserializeItem(data: Buffer): V;
|
|
17
|
+
/**
|
|
18
|
+
* Pushes one or more values at the head of the list stored at key.
|
|
19
|
+
* If the key does not already exist, it is first created as an empty list.
|
|
20
|
+
*
|
|
21
|
+
* If multiple values are given, they are inserted one after another,
|
|
22
|
+
* starting with the leftmost value. For instance,
|
|
23
|
+
* `pushLeft(key, "a", "b", "c")` will result in a list containing
|
|
24
|
+
* "c" as its first element, "b" as its second, and "a" as its third.
|
|
25
|
+
*
|
|
26
|
+
* @returns The length of the list after the operation.
|
|
27
|
+
* @see https://redis.io/commands/lpush/
|
|
28
|
+
*/
|
|
29
|
+
pushLeft(key: K, ...values: V[]): Promise<number>;
|
|
30
|
+
/**
|
|
31
|
+
* Pushes one or more values at the tail of the list stored at key.
|
|
32
|
+
* If the key does not already exist, it is first created as an empty list.
|
|
33
|
+
*
|
|
34
|
+
* If multiple values are given, they are inserted one after another,
|
|
35
|
+
* starting with the leftmost value. For instance,
|
|
36
|
+
* `pushRight(key, "a", "b", "c")` will result in a list containing
|
|
37
|
+
* "a" as its first element, "b" as its second, and "c" as its third.
|
|
38
|
+
*
|
|
39
|
+
* @returns The length of the list after the operation.
|
|
40
|
+
* @see https://redis.io/commands/rpush/
|
|
41
|
+
*/
|
|
42
|
+
pushRight(key: K, ...values: V[]): Promise<number>;
|
|
43
|
+
/**
|
|
44
|
+
* Pops a single element off the head of the list stored at key.
|
|
45
|
+
*
|
|
46
|
+
* @returns The popped value, or `undefined` if the key does not exist.
|
|
47
|
+
* @see https://redis.io/commands/lpop/
|
|
48
|
+
*/
|
|
49
|
+
popLeft(key: K, options?: WriteOptions): Promise<V | undefined>;
|
|
50
|
+
/**
|
|
51
|
+
* Pops a single element off the tail of the list stored at key.
|
|
52
|
+
*
|
|
53
|
+
* @returns The popped value, or `undefined` if the key does not exist.
|
|
54
|
+
* @see https://redis.io/commands/rpop/
|
|
55
|
+
*/
|
|
56
|
+
popRight(key: K, options?: WriteOptions): Promise<V | undefined>;
|
|
57
|
+
/**
|
|
58
|
+
* Returns the length of the list stored at key.
|
|
59
|
+
*
|
|
60
|
+
* Non-existing keys are considered as empty lists.
|
|
61
|
+
*
|
|
62
|
+
* @returns The list length.
|
|
63
|
+
* @see https://redis.io/commands/llen/
|
|
64
|
+
*/
|
|
65
|
+
len(key: K): Promise<number>;
|
|
66
|
+
/**
|
|
67
|
+
* Trims the list stored at key to only contain the elements between the indices
|
|
68
|
+
* `start` and `stop` (inclusive). Both are zero-based indices.
|
|
69
|
+
*
|
|
70
|
+
* Negative indices can be used to indicate offsets from the end of the list,
|
|
71
|
+
* where -1 is the last element of the list, -2 the penultimate element, and so on.
|
|
72
|
+
*
|
|
73
|
+
* Out of range indices are valid and are treated as if they specify the start or end of the list,
|
|
74
|
+
* respectively. If `start` > `stop` the end result is an empty list.
|
|
75
|
+
*
|
|
76
|
+
* @param key - The cache key.
|
|
77
|
+
* @param start - Start index (inclusive).
|
|
78
|
+
* @param stop - Stop index (inclusive).
|
|
79
|
+
* @see https://redis.io/commands/ltrim/
|
|
80
|
+
*/
|
|
81
|
+
trim(key: K, start: number, stop: number, options?: WriteOptions): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Updates the list element at the given index.
|
|
84
|
+
*
|
|
85
|
+
* Negative indices can be used to indicate offsets from the end of the list,
|
|
86
|
+
* where -1 is the last element of the list, -2 the penultimate element, and so on.
|
|
87
|
+
*
|
|
88
|
+
* @param key - The cache key.
|
|
89
|
+
* @param index - Zero-based index of the element to update.
|
|
90
|
+
* @param value - The new value.
|
|
91
|
+
* @throws {Error} If the index is out of range.
|
|
92
|
+
* @see https://redis.io/commands/lset/
|
|
93
|
+
*/
|
|
94
|
+
set(key: K, index: number, value: V, options?: WriteOptions): Promise<void>;
|
|
95
|
+
/**
|
|
96
|
+
* Returns the value of the list element at the given index.
|
|
97
|
+
*
|
|
98
|
+
* Negative indices can be used to indicate offsets from the end of the list,
|
|
99
|
+
* where -1 is the last element of the list, -2 the penultimate element, and so on.
|
|
100
|
+
*
|
|
101
|
+
* @param key - The cache key.
|
|
102
|
+
* @param index - Zero-based index of the element to retrieve.
|
|
103
|
+
* @returns The value at the index, or `undefined` if out of range or the key does not exist.
|
|
104
|
+
* @see https://redis.io/commands/lindex/
|
|
105
|
+
*/
|
|
106
|
+
get(key: K, index: number): Promise<V | undefined>;
|
|
107
|
+
/**
|
|
108
|
+
* Returns all the elements in the list stored at key.
|
|
109
|
+
*
|
|
110
|
+
* If the key does not exist it returns an empty array.
|
|
111
|
+
*
|
|
112
|
+
* @returns All elements in the list.
|
|
113
|
+
* @see https://redis.io/commands/lrange/
|
|
114
|
+
*/
|
|
115
|
+
items(key: K): Promise<V[]>;
|
|
116
|
+
/**
|
|
117
|
+
* Returns the elements in the list stored at key between `start` and `stop` (inclusive).
|
|
118
|
+
* Both are zero-based indices.
|
|
119
|
+
*
|
|
120
|
+
* Negative indices can be used to indicate offsets from the end of the list,
|
|
121
|
+
* where -1 is the last element of the list, -2 the penultimate element, and so on.
|
|
122
|
+
*
|
|
123
|
+
* If the key does not exist it returns an empty array.
|
|
124
|
+
*
|
|
125
|
+
* @param key - The cache key.
|
|
126
|
+
* @param start - Start index (inclusive).
|
|
127
|
+
* @param stop - Stop index (inclusive).
|
|
128
|
+
* @returns The elements in the specified range.
|
|
129
|
+
* @see https://redis.io/commands/lrange/
|
|
130
|
+
*/
|
|
131
|
+
getRange(key: K, start: number, stop: number): Promise<V[]>;
|
|
132
|
+
/**
|
|
133
|
+
* Inserts `value` into the list stored at key, at the position just before `pivot`.
|
|
134
|
+
*
|
|
135
|
+
* If the list does not contain `pivot`, the value is not inserted and -1 is returned.
|
|
136
|
+
*
|
|
137
|
+
* @param key - The cache key.
|
|
138
|
+
* @param pivot - The existing element to insert before.
|
|
139
|
+
* @param value - The value to insert.
|
|
140
|
+
* @returns The new list length, or -1 if `pivot` was not found.
|
|
141
|
+
* @see https://redis.io/commands/linsert/
|
|
142
|
+
*/
|
|
143
|
+
insertBefore(key: K, pivot: V, value: V, options?: WriteOptions): Promise<number>;
|
|
144
|
+
/**
|
|
145
|
+
* Inserts `value` into the list stored at key, at the position just after `pivot`.
|
|
146
|
+
*
|
|
147
|
+
* If the list does not contain `pivot`, the value is not inserted and -1 is returned.
|
|
148
|
+
*
|
|
149
|
+
* @param key - The cache key.
|
|
150
|
+
* @param pivot - The existing element to insert after.
|
|
151
|
+
* @param value - The value to insert.
|
|
152
|
+
* @returns The new list length, or -1 if `pivot` was not found.
|
|
153
|
+
* @see https://redis.io/commands/linsert/
|
|
154
|
+
*/
|
|
155
|
+
insertAfter(key: K, pivot: V, value: V, options?: WriteOptions): Promise<number>;
|
|
156
|
+
/**
|
|
157
|
+
* Removes all occurrences of `value` in the list stored at key.
|
|
158
|
+
*
|
|
159
|
+
* If the list does not contain `value`, or the list does not exist, returns 0.
|
|
160
|
+
*
|
|
161
|
+
* @param key - The cache key.
|
|
162
|
+
* @param value - The value to remove.
|
|
163
|
+
* @returns The number of elements removed.
|
|
164
|
+
* @see https://redis.io/commands/lrem/
|
|
165
|
+
*/
|
|
166
|
+
removeAll(key: K, value: V, options?: WriteOptions): Promise<number>;
|
|
167
|
+
/**
|
|
168
|
+
* Removes the first `count` occurrences of `value` in the list stored at key,
|
|
169
|
+
* scanning from head to tail.
|
|
170
|
+
*
|
|
171
|
+
* If the list does not contain `value`, or the list does not exist, returns 0.
|
|
172
|
+
*
|
|
173
|
+
* @param key - The cache key.
|
|
174
|
+
* @param count - Maximum number of occurrences to remove.
|
|
175
|
+
* @param value - The value to remove.
|
|
176
|
+
* @returns The number of elements removed.
|
|
177
|
+
* @see https://redis.io/commands/lrem/
|
|
178
|
+
*/
|
|
179
|
+
removeFirst(key: K, count: number, value: V, options?: WriteOptions): Promise<number>;
|
|
180
|
+
/**
|
|
181
|
+
* Removes the last `count` occurrences of `value` in the list stored at key,
|
|
182
|
+
* scanning from tail to head.
|
|
183
|
+
*
|
|
184
|
+
* If the list does not contain `value`, or the list does not exist, returns 0.
|
|
185
|
+
*
|
|
186
|
+
* @param key - The cache key.
|
|
187
|
+
* @param count - Maximum number of occurrences to remove.
|
|
188
|
+
* @param value - The value to remove.
|
|
189
|
+
* @returns The number of elements removed.
|
|
190
|
+
* @see https://redis.io/commands/lrem/
|
|
191
|
+
*/
|
|
192
|
+
removeLast(key: K, count: number, value: V, options?: WriteOptions): Promise<number>;
|
|
193
|
+
/**
|
|
194
|
+
* Atomically moves an element from the list stored at `src` to the list stored at `dst`.
|
|
195
|
+
*
|
|
196
|
+
* The value moved can be either the head (`srcPos === "left"`) or tail (`srcPos === "right"`)
|
|
197
|
+
* of the list at `src`. Similarly, the value can be placed either at the head (`dstPos === "left"`)
|
|
198
|
+
* or tail (`dstPos === "right"`) of the list at `dst`.
|
|
199
|
+
*
|
|
200
|
+
* If `src` and `dst` are the same list, the value is atomically rotated from one end to the other
|
|
201
|
+
* when `srcPos !== dstPos`, or if `srcPos === dstPos` nothing happens.
|
|
202
|
+
*
|
|
203
|
+
* @param src - Source list key.
|
|
204
|
+
* @param dst - Destination list key.
|
|
205
|
+
* @param srcPos - Position to pop from in the source list.
|
|
206
|
+
* @param dstPos - Position to push to in the destination list.
|
|
207
|
+
* @returns The moved element, or `undefined` if the source list does not exist.
|
|
208
|
+
* @see https://redis.io/commands/lmove/
|
|
209
|
+
*/
|
|
210
|
+
move(src: K, dst: K, srcPos: ListPosition, dstPos: ListPosition, options?: WriteOptions): Promise<V | undefined>;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* StringListKeyspace stores lists of string values.
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* ```ts
|
|
217
|
+
* const recentViews = new StringListKeyspace<string>(cluster, {
|
|
218
|
+
* keyPattern: "recent-views/:userId",
|
|
219
|
+
* defaultExpiry: ExpireIn(86400000), // 24 hours
|
|
220
|
+
* });
|
|
221
|
+
*
|
|
222
|
+
* await recentViews.pushLeft("user1", "product-123", "product-456");
|
|
223
|
+
* const views = await recentViews.items("user1");
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
export declare class StringListKeyspace<K> extends ListKeyspace<K, string> {
|
|
227
|
+
constructor(cluster: CacheCluster, config: KeyspaceConfig<K>);
|
|
228
|
+
protected serializeItem(value: string): Buffer;
|
|
229
|
+
protected deserializeItem(data: Buffer): string;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* NumberListKeyspace stores lists of numeric values.
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```ts
|
|
236
|
+
* const scores = new NumberListKeyspace<string>(cluster, {
|
|
237
|
+
* keyPattern: "scores/:gameId",
|
|
238
|
+
* });
|
|
239
|
+
*
|
|
240
|
+
* await scores.pushRight("game1", 100, 200, 300);
|
|
241
|
+
* const allScores = await scores.items("game1");
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
export declare class NumberListKeyspace<K> extends ListKeyspace<K, number> {
|
|
245
|
+
constructor(cluster: CacheCluster, config: KeyspaceConfig<K>);
|
|
246
|
+
protected serializeItem(value: number): Buffer;
|
|
247
|
+
protected deserializeItem(data: Buffer): number;
|
|
248
|
+
}
|
|
249
|
+
export {};
|