@common-stack/store-redis 8.2.5-alpha.33 → 8.2.5-alpha.35

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.
Files changed (41) hide show
  1. package/lib/containers/container.d.ts +2 -0
  2. package/lib/containers/container.js +9 -0
  3. package/lib/containers/index.d.ts +1 -0
  4. package/lib/core/index.d.ts +3 -0
  5. package/lib/core/ioredis.d.ts +15 -0
  6. package/lib/core/ioredis.js +31 -0
  7. package/lib/core/keyBuilder/generate-query-cache-key.d.ts +57 -0
  8. package/lib/core/keyBuilder/generate-query-cache-key.js +88 -0
  9. package/lib/core/keyBuilder/index.d.ts +18 -0
  10. package/lib/core/keyBuilder/index.js +27 -0
  11. package/lib/core/keyBuilder/redis-key-builder.d.ts +152 -0
  12. package/lib/core/keyBuilder/redis-key-builder.js +185 -0
  13. package/lib/core/keyBuilder/sanitize-redis-key.d.ts +118 -0
  14. package/lib/core/keyBuilder/sanitize-redis-key.js +120 -0
  15. package/lib/core/upstash-redis.d.ts +14 -0
  16. package/lib/core/upstash-redis.js +27 -0
  17. package/lib/index.d.ts +2 -1
  18. package/lib/index.js +7 -3
  19. package/lib/interfaces/index.d.ts +1 -6
  20. package/lib/interfaces/redis.d.ts +11 -0
  21. package/lib/module.d.ts +2 -0
  22. package/lib/module.js +9 -0
  23. package/lib/services/RedisCacheManager.d.ts +77 -0
  24. package/lib/services/RedisCacheManager.js +185 -0
  25. package/lib/services/index.d.ts +1 -5
  26. package/lib/templates/constants/SERVER_TYPES.ts.template +0 -1
  27. package/lib/templates/repositories/IRedisKeyBuilder.ts.template +4 -4
  28. package/lib/templates/repositories/redisCommonTypes.ts.template +2 -163
  29. package/lib/templates/{repositories/IRedisCacheManager.ts.template → services/RedisCacheManager.ts.template} +7 -7
  30. package/package.json +8 -7
  31. package/lib/interfaces/cache-manager.d.ts +0 -28
  32. package/lib/interfaces/redis-key-options.d.ts +0 -35
  33. package/lib/interfaces/redis-key-options.js +0 -17
  34. package/lib/interfaces/storage-backend.d.ts +0 -17
  35. package/lib/templates/repositories/IRedisService.ts.template +0 -236
  36. package/lib/templates/repositories/IRedisStorageBackend.ts.template +0 -229
  37. package/lib/utils/index.d.ts +0 -5
  38. package/lib/utils/redis-key-builder.d.ts +0 -32
  39. package/lib/utils/redis-key-builder.js +0 -68
  40. package/lib/utils/redis-key-sanitizer.d.ts +0 -30
  41. package/lib/utils/redis-key-sanitizer.js +0 -54
@@ -5,109 +5,15 @@
5
5
  * These types provide a standardized approach to working with Redis operations, including
6
6
  * key management, caching, and storage patterns.
7
7
  *
8
- * Key components include:
9
- * - RedisKeyOptions: Configuration for building standardized Redis keys
10
- * - RedisNamespace: Enum for organizing keys into logical namespaces
11
- * - CacheContext: Context information for cache operations (tenant, user, org)
12
- * - CachePolicy: Configuration for cache TTL and scope
13
- * - RedisValue: Union type for values that can be stored in Redis
14
- * - RedisHashValue: Type for Redis hash field values
15
- * - RedisScanOptions: Options for scanning Redis keys
16
- *
17
- * These types ensure consistency across Redis operations, providing type safety and
18
- * clear contracts for data caching and storage throughout the application.
8
+ * Most types are generated from GraphQL schema via codegen.
9
+ * Additional runtime types (RedisValue, RedisHashValue) are defined here.
19
10
  *
20
11
  * @see IRedisCacheManager - Cache manager interface using these types
21
12
  * @see IRedisStorageBackend - Storage backend interface using these types
22
13
  * @see IRedisKeyBuilder - Key builder interface using these types
23
14
  */
24
15
 
25
- /**
26
- * Options for building Redis keys with standardized format
27
- *
28
- * @property tenantId - Tenant ID for multi-tenant isolation (defaults to 'default')
29
- * @property namespace - Namespace to categorize keys (e.g., 'cache', 'session', 'storage')
30
- * @property segments - Additional key segments to append
31
- * @property userId - Optional user ID for user-specific keys
32
- *
33
- * @example
34
- * const keyOptions: RedisKeyOptions = {
35
- * tenantId: 'tenant-123',
36
- * namespace: RedisNamespace.CACHE,
37
- * segments: ['user', 'profile']
38
- * };
39
- * // Produces key: APP_NAME:tenant-123:cache:user:profile
40
- */
41
- export interface RedisKeyOptions {
42
- tenantId?: string;
43
- namespace: string;
44
- segments: string[];
45
- userId?: string;
46
- }
47
-
48
- /**
49
- * Standard Redis namespaces for organizing keys
50
- * Using namespaces helps prevent key collisions and makes bulk operations easier
51
- *
52
- * @example
53
- * // Use namespaces to organize cache keys
54
- * const cacheKey = buildRedisKey({
55
- * tenantId: 'tenant-123',
56
- * namespace: RedisNamespace.CACHE,
57
- * segments: ['query', 'users']
58
- * });
59
- */
60
- export enum RedisNamespace {
61
- CACHE = 'cache',
62
- SESSION = 'session',
63
- TENANT = 'tenant',
64
- CONFIG = 'config',
65
- EXTENSION = 'extension',
66
- CONTRIBUTION = 'contribution',
67
- STORAGE = 'storage',
68
- PERMISSION = 'permission',
69
- TEMP = 'temp',
70
- QUEUE = 'queue',
71
- LOCK = 'lock',
72
- }
73
-
74
- /**
75
- * Context for cache operations
76
- * Provides tenant, user, and organization isolation for cached data
77
- *
78
- * @property tenantId - Tenant identifier for multi-tenant applications
79
- * @property userId - User identifier for user-specific caching
80
- * @property orgId - Organization identifier for org-level caching
81
- *
82
- * @example
83
- * const ctx: CacheContext = {
84
- * tenantId: 'tenant-123',
85
- * userId: 'user-456',
86
- * orgId: 'org-789'
87
- * };
88
- */
89
- export interface CacheContext {
90
- tenantId?: string;
91
- userId?: string;
92
- orgId?: string;
93
- }
94
16
 
95
- /**
96
- * Cache policy for controlling cache behavior
97
- *
98
- * @property maxAge - Maximum age in seconds (TTL)
99
- * @property scope - Cache scope (PUBLIC, PRIVATE, etc.)
100
- *
101
- * @example
102
- * const policy: CachePolicy = {
103
- * maxAge: 3600, // 1 hour
104
- * scope: 'PRIVATE'
105
- * };
106
- */
107
- export interface CachePolicy {
108
- maxAge: number;
109
- scope?: string;
110
- }
111
17
 
112
18
  /**
113
19
  * Union type for values that can be stored in Redis
@@ -120,70 +26,3 @@ export type RedisValue = string | number | Buffer | null;
120
26
  * Hashes in Redis store field-value pairs
121
27
  */
122
28
  export type RedisHashValue = Record<string, string>;
123
-
124
- /**
125
- * Options for scanning Redis keys
126
- * Used for iterating through keys matching a pattern
127
- *
128
- * @property match - Pattern to match keys (supports wildcards)
129
- * @property count - Number of keys to return per iteration
130
- * @property type - Optional Redis data type to filter by
131
- *
132
- * @example
133
- * const scanOptions: RedisScanOptions = {
134
- * match: 'APP:tenant-*:cache:*',
135
- * count: 100,
136
- * type: 'string'
137
- * };
138
- */
139
- export interface RedisScanOptions {
140
- match?: string;
141
- count?: number;
142
- type?: 'string' | 'list' | 'set' | 'zset' | 'hash' | 'stream';
143
- }
144
-
145
- /**
146
- * Result from a Redis SCAN operation
147
- *
148
- * @property cursor - Next cursor position (0 means scan is complete)
149
- * @property keys - Array of keys matching the scan criteria
150
- */
151
- export interface RedisScanResult {
152
- cursor: string;
153
- keys: string[];
154
- }
155
-
156
- /**
157
- * Options for Redis bulk operations
158
- * Used when performing operations on multiple keys
159
- *
160
- * @property pipeline - Whether to use Redis pipeline for batch operations
161
- * @property transaction - Whether to wrap operations in a MULTI/EXEC transaction
162
- */
163
- export interface RedisBulkOptions {
164
- pipeline?: boolean;
165
- transaction?: boolean;
166
- }
167
-
168
- /**
169
- * Redis connection configuration
170
- *
171
- * @property host - Redis server host
172
- * @property port - Redis server port
173
- * @property password - Optional password for authentication
174
- * @property db - Database number to use
175
- * @property keyPrefix - Prefix to add to all keys
176
- * @property maxRetriesPerRequest - Maximum retry attempts
177
- * @property enableReadyCheck - Whether to check connection is ready
178
- * @property lazyConnect - Whether to delay connection until first command
179
- */
180
- export interface RedisConnectionConfig {
181
- host?: string;
182
- port?: number;
183
- password?: string;
184
- db?: number;
185
- keyPrefix?: string;
186
- maxRetriesPerRequest?: number;
187
- enableReadyCheck?: boolean;
188
- lazyConnect?: boolean;
189
- }
@@ -24,12 +24,12 @@
24
24
  * while maintaining cache correctness through intelligent invalidation strategies.
25
25
  *
26
26
  * @see IRedisStorageBackend - For simpler key-value storage
27
- * @see CachePolicy - For cache TTL and scope configuration
28
- * @see CacheContext - For tenant/user isolation
27
+ * @see ICachePolicy - For cache TTL and scope configuration
28
+ * @see ICacheContext - For tenant/user isolation
29
29
  */
30
30
 
31
31
  import type { DocumentNode } from 'graphql';
32
- import { CacheContext, CachePolicy } from './redisCommonTypes';
32
+ import { ICacheContext, ICachePolicy } from 'common/server';
33
33
 
34
34
  export interface IRedisCacheManager {
35
35
  /**
@@ -60,7 +60,7 @@ export interface IRedisCacheManager {
60
60
  get<T>(
61
61
  query: string | DocumentNode,
62
62
  variables: Record<string, any>,
63
- ctx: CacheContext
63
+ ctx: ICacheContext
64
64
  ): Promise<T | null>;
65
65
 
66
66
  /**
@@ -97,8 +97,8 @@ export interface IRedisCacheManager {
97
97
  query: string | DocumentNode,
98
98
  variables: Record<string, any>,
99
99
  data: T,
100
- ctx: CacheContext,
101
- cachePolicy?: CachePolicy
100
+ ctx: ICacheContext,
101
+ cachePolicy?: ICachePolicy
102
102
  ): Promise<void>;
103
103
 
104
104
  /**
@@ -143,7 +143,7 @@ export interface IRedisCacheManager {
143
143
  del(
144
144
  query: string | DocumentNode,
145
145
  variables?: Record<string, unknown>,
146
- ctx?: CacheContext,
146
+ ctx?: ICacheContext,
147
147
  shouldRemoveAll?: boolean
148
148
  ): Promise<void>;
149
149
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@common-stack/store-redis",
3
- "version": "8.2.5-alpha.33",
3
+ "version": "8.2.5-alpha.35",
4
4
  "description": "Redis store utilities and services for common-stack",
5
5
  "license": "UNLICENSED",
6
6
  "author": "CDMBase LLC",
@@ -24,13 +24,14 @@
24
24
  "watch": "npm run build:lib:watch"
25
25
  },
26
26
  "dependencies": {
27
- "@common-stack/core": "8.2.5-alpha.15"
27
+ "@common-stack/core": "8.2.5-alpha.35"
28
28
  },
29
29
  "devDependencies": {
30
- "common": "8.2.5-alpha.15",
30
+ "common": "8.2.5-alpha.35",
31
31
  "ioredis": "^5.3.2"
32
32
  },
33
33
  "peerDependencies": {
34
+ "graphql": ">=16.0.0",
34
35
  "inversify": "*",
35
36
  "ioredis": ">=5.0.0"
36
37
  },
@@ -44,15 +45,15 @@
44
45
  ],
45
46
  "repositories": [
46
47
  "./${libDir}/templates/repositories/IRedisKeyBuilder.ts.template",
47
- "./${libDir}/templates/repositories/IRedisStorageBackend.ts.template",
48
- "./${libDir}/templates/repositories/IRedisCacheManager.ts.template",
49
- "./${libDir}/templates/repositories/IRedisService.ts.template",
50
48
  "./${libDir}/templates/repositories/redisCommonTypes.ts.template"
49
+ ],
50
+ "services": [
51
+ "./${libDir}/templates/services/RedisCacheManager.ts.template"
51
52
  ]
52
53
  }
53
54
  },
54
55
  "typescript": {
55
56
  "definition": "lib/index.d.ts"
56
57
  },
57
- "gitHead": "5745649eba49ac589b9ace8c55378b6cbe130096"
58
+ "gitHead": "33d6be7fdf924ca76bc1b98cee3031d55a8115d7"
58
59
  }
@@ -1,28 +0,0 @@
1
- import type { DocumentNode } from 'graphql';
2
- import type { CacheContext } from './redis-key-options';
3
- /**
4
- * Cache policy for controlling cache behavior
5
- */
6
- export interface CachePolicy {
7
- /** Maximum age in seconds */
8
- maxAge: number;
9
- /** Cache scope (PUBLIC, PRIVATE, etc.) */
10
- scope?: string;
11
- }
12
- /**
13
- * Redis cache manager interface for GraphQL query caching
14
- */
15
- export interface IRedisCacheManager {
16
- /**
17
- * Get cached data for a query
18
- */
19
- get<T>(query: string | DocumentNode, variables: Record<string, any>, ctx: CacheContext): Promise<T | null>;
20
- /**
21
- * Set cached data for a query
22
- */
23
- set<T>(query: string | DocumentNode, variables: Record<string, any>, data: T, ctx: CacheContext, cachePolicy?: CachePolicy): Promise<void>;
24
- /**
25
- * Delete cached data for a query
26
- */
27
- del(query: string | DocumentNode, variables?: Record<string, unknown>, ctx?: CacheContext, shouldRemoveAll?: boolean): Promise<void>;
28
- }
@@ -1,35 +0,0 @@
1
- /**
2
- * Options for building Redis keys with standardized format
3
- */
4
- export interface RedisKeyOptions {
5
- /** Tenant ID for multi-tenant isolation */
6
- tenantId?: string;
7
- /** Namespace to categorize keys (e.g., 'cache', 'session', 'storage') */
8
- namespace: string;
9
- /** Additional key segments to append */
10
- segments: string[];
11
- /** Optional user ID for user-specific keys */
12
- userId?: string;
13
- }
14
- /**
15
- * Standard Redis namespaces for organizing keys
16
- */
17
- export declare enum RedisNamespace {
18
- CACHE = "cache",
19
- SESSION = "session",
20
- TENANT = "tenant",
21
- CONFIG = "config",
22
- EXTENSION = "extension",
23
- CONTRIBUTION = "contribution",
24
- STORAGE = "storage",
25
- PERMISSION = "permission",
26
- TEMP = "temp"
27
- }
28
- /**
29
- * Context for cache operations
30
- */
31
- export interface CacheContext {
32
- tenantId?: string;
33
- userId?: string;
34
- orgId?: string;
35
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * Standard Redis namespaces for organizing keys
3
- */
4
- var RedisNamespace;
5
- (function (RedisNamespace) {
6
- RedisNamespace["CACHE"] = "cache";
7
- RedisNamespace["SESSION"] = "session";
8
- RedisNamespace["TENANT"] = "tenant";
9
- RedisNamespace["CONFIG"] = "config";
10
- RedisNamespace["EXTENSION"] = "extension";
11
- RedisNamespace["CONTRIBUTION"] = "contribution";
12
- RedisNamespace["STORAGE"] = "storage";
13
- RedisNamespace["PERMISSION"] = "permission";
14
- RedisNamespace["TEMP"] = "temp";
15
- })(RedisNamespace || (RedisNamespace = {}));
16
-
17
- export { RedisNamespace };
@@ -1,17 +0,0 @@
1
- /**
2
- * Generic storage backend interface for simple key-value operations
3
- */
4
- export interface IStorageBackend {
5
- /**
6
- * Get a value by key
7
- */
8
- get(key: string): Promise<string | null>;
9
- /**
10
- * Set a value for a key
11
- */
12
- set(key: string, value: string): Promise<void>;
13
- /**
14
- * Clear all keys in this storage
15
- */
16
- clear(): Promise<void>;
17
- }
@@ -1,236 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- /**
3
- * @file IRedisService.ts
4
- * @description Defines the IRedisService interface for advanced Redis operations and patterns.
5
- * This interface provides high-level Redis operations beyond simple key-value storage,
6
- * including pub/sub, streams, sorted sets, and distributed locking.
7
- *
8
- * The Redis service is designed for:
9
- * - Pub/Sub messaging patterns
10
- * - Distributed locking (mutex)
11
- * - Rate limiting
12
- * - Leaderboards and rankings (sorted sets)
13
- * - Event streams
14
- * - Queue management
15
- *
16
- * Key features:
17
- * - Pub/Sub for real-time messaging
18
- * - Distributed locks for resource coordination
19
- * - Rate limiting for API throttling
20
- * - Sorted sets for rankings and leaderboards
21
- * - Redis Streams for event sourcing
22
- * - Pipeline operations for performance
23
- *
24
- * This service layer provides advanced Redis patterns that go beyond simple caching
25
- * and storage, enabling sophisticated distributed system architectures.
26
- *
27
- * @see IRedisCacheManager - For query caching
28
- * @see IRedisStorageBackend - For simple key-value storage
29
- */
30
-
31
- export interface IRedisService {
32
- /**
33
- * Publish a message to a Redis channel
34
- * Part of the Pub/Sub pattern for real-time messaging
35
- *
36
- * @param channel - Channel name to publish to
37
- * @param message - Message to publish (will be stringified if object)
38
- * @returns Promise resolving to number of subscribers that received the message
39
- *
40
- * @example
41
- * // Publish user update event
42
- * await redisService.publish('user:updates', JSON.stringify({
43
- * userId: '123',
44
- * action: 'updated'
45
- * }));
46
- */
47
- publish(channel: string, message: string): Promise<number>;
48
-
49
- /**
50
- * Subscribe to a Redis channel
51
- * Receives messages published to the channel
52
- *
53
- * @param channel - Channel name to subscribe to
54
- * @param callback - Function called when message received
55
- * @returns Promise that resolves when subscribed
56
- *
57
- * @example
58
- * // Subscribe to user updates
59
- * await redisService.subscribe('user:updates', (message) => {
60
- * const event = JSON.parse(message);
61
- * console.log(`User ${event.userId} was ${event.action}`);
62
- * });
63
- */
64
- subscribe(channel: string, callback: (message: string) => void): Promise<void>;
65
-
66
- /**
67
- * Unsubscribe from a Redis channel
68
- *
69
- * @param channel - Channel name to unsubscribe from
70
- * @returns Promise that resolves when unsubscribed
71
- *
72
- * @example
73
- * // Unsubscribe from updates
74
- * await redisService.unsubscribe('user:updates');
75
- */
76
- unsubscribe(channel: string): Promise<void>;
77
-
78
- /**
79
- * Acquire a distributed lock
80
- * Ensures only one process can execute critical section
81
- *
82
- * @param key - Lock key (unique identifier for the resource)
83
- * @param ttl - Lock TTL in milliseconds (auto-release if process dies)
84
- * @param retries - Number of retry attempts
85
- * @returns Promise resolving to lock token (needed for release) or null if failed
86
- *
87
- * @example
88
- * // Acquire lock for order processing
89
- * const lock = await redisService.acquireLock('order:123:processing', 5000);
90
- * if (lock) {
91
- * try {
92
- * await processOrder('123');
93
- * } finally {
94
- * await redisService.releaseLock('order:123:processing', lock);
95
- * }
96
- * }
97
- */
98
- acquireLock(key: string, ttl: number, retries?: number): Promise<string | null>;
99
-
100
- /**
101
- * Release a distributed lock
102
- * Only the process that acquired the lock can release it
103
- *
104
- * @param key - Lock key
105
- * @param token - Lock token returned from acquireLock
106
- * @returns Promise resolving to true if lock was released
107
- *
108
- * @example
109
- * // Release lock after critical section
110
- * await redisService.releaseLock('resource:123', lockToken);
111
- */
112
- releaseLock(key: string, token: string): Promise<boolean>;
113
-
114
- /**
115
- * Check rate limit for a key
116
- * Implements sliding window rate limiting
117
- *
118
- * @param key - Rate limit key (e.g., userId or IP address)
119
- * @param limit - Maximum requests allowed
120
- * @param window - Time window in seconds
121
- * @returns Promise resolving to object with allowed status and remaining count
122
- *
123
- * @example
124
- * // Check API rate limit
125
- * const rateLimitStatus = await redisService.checkRateLimit(
126
- * `api:user:${userId}`,
127
- * 100, // 100 requests
128
- * 3600 // per hour
129
- * );
130
- *
131
- * if (!rateLimitStatus.allowed) {
132
- * throw new Error('Rate limit exceeded');
133
- * }
134
- */
135
- checkRateLimit(
136
- key: string,
137
- limit: number,
138
- window: number
139
- ): Promise<{
140
- allowed: boolean;
141
- remaining: number;
142
- resetAt: number;
143
- }>;
144
-
145
- /**
146
- * Add member to sorted set with score
147
- * Useful for leaderboards, rankings, and time-ordered data
148
- *
149
- * @param key - Sorted set key
150
- * @param score - Score for ordering (lower scores first)
151
- * @param member - Member to add
152
- * @returns Promise resolving to number of elements added
153
- *
154
- * @example
155
- * // Add user score to leaderboard
156
- * await redisService.sortedSetAdd('leaderboard:game1', 1000, 'user-123');
157
- */
158
- sortedSetAdd(key: string, score: number, member: string): Promise<number>;
159
-
160
- /**
161
- * Get top members from sorted set
162
- *
163
- * @param key - Sorted set key
164
- * @param start - Start index (0-based)
165
- * @param stop - Stop index (-1 for all)
166
- * @param withScores - Whether to include scores in result
167
- * @returns Promise resolving to array of members (and scores if requested)
168
- *
169
- * @example
170
- * // Get top 10 players
171
- * const topPlayers = await redisService.sortedSetRange(
172
- * 'leaderboard:game1',
173
- * 0,
174
- * 9,
175
- * true
176
- * );
177
- * // Result: [{member: 'user-1', score: 1500}, {member: 'user-2', score: 1400}, ...]
178
- */
179
- sortedSetRange(
180
- key: string,
181
- start: number,
182
- stop: number,
183
- withScores?: boolean
184
- ): Promise<Array<{ member: string; score?: number }>>;
185
-
186
- /**
187
- * Get member rank in sorted set
188
- *
189
- * @param key - Sorted set key
190
- * @param member - Member to get rank for
191
- * @returns Promise resolving to rank (0-based) or null if not found
192
- *
193
- * @example
194
- * // Get user's leaderboard position
195
- * const rank = await redisService.sortedSetRank('leaderboard:game1', 'user-123');
196
- * console.log(`You are ranked #${rank + 1}`);
197
- */
198
- sortedSetRank(key: string, member: string): Promise<number | null>;
199
-
200
- /**
201
- * Add entry to Redis Stream
202
- * Useful for event sourcing and message queues
203
- *
204
- * @param key - Stream key
205
- * @param fields - Fields to add to stream entry
206
- * @returns Promise resolving to entry ID
207
- *
208
- * @example
209
- * // Add event to stream
210
- * const entryId = await redisService.streamAdd('events:user-actions', {
211
- * userId: '123',
212
- * action: 'login',
213
- * timestamp: Date.now().toString()
214
- * });
215
- */
216
- streamAdd(key: string, fields: Record<string, string>): Promise<string>;
217
-
218
- /**
219
- * Read entries from Redis Stream
220
- *
221
- * @param key - Stream key
222
- * @param options - Read options (count, id to start from)
223
- * @returns Promise resolving to array of stream entries
224
- *
225
- * @example
226
- * // Read last 100 events
227
- * const events = await redisService.streamRead('events:user-actions', {
228
- * count: 100,
229
- * id: '0' // Start from beginning
230
- * });
231
- */
232
- streamRead(
233
- key: string,
234
- options?: { count?: number; id?: string }
235
- ): Promise<Array<{ id: string; fields: Record<string, string> }>>;
236
- }