@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
@@ -1,229 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- /**
3
- * @file IRedisStorageBackend.ts
4
- * @description Defines the IRedisStorageBackend interface for simple key-value storage operations using Redis.
5
- * This interface provides a clean abstraction for basic Redis operations, suitable for request-scoped storage,
6
- * temporary data, session storage, and other simple caching scenarios.
7
- *
8
- * The storage backend is designed for:
9
- * - Request-scoped temporary data
10
- * - Session storage
11
- * - Simple key-value caching
12
- * - Temporary flags and state
13
- *
14
- * Unlike RedisCacheManager which is optimized for GraphQL query caching with hashing,
15
- * this storage backend provides straightforward get/set/delete operations for simple use cases.
16
- *
17
- * Key features:
18
- * - Simple key-value operations
19
- * - TTL support for automatic expiration
20
- * - Bulk operations for efficiency
21
- * - Clear operations for cleanup
22
- * - Type-safe with generics
23
- *
24
- * @see IRedisCacheManager - For complex caching with GraphQL queries
25
- * @see IRedisKeyBuilder - For standardized key generation
26
- */
27
-
28
- export interface IRedisStorageBackend {
29
- /**
30
- * Get a value by key
31
- * Returns null if key doesn't exist
32
- *
33
- * @param key - Redis key to retrieve
34
- * @returns Promise resolving to the value or null
35
- *
36
- * @example
37
- * // Get session data
38
- * const sessionData = await storage.get('session:user-123');
39
- * if (sessionData) {
40
- * const session = JSON.parse(sessionData);
41
- * }
42
- */
43
- get(key: string): Promise<string | null>;
44
-
45
- /**
46
- * Get multiple values by keys
47
- * Returns array with same order as keys, null for missing keys
48
- *
49
- * @param keys - Array of Redis keys to retrieve
50
- * @returns Promise resolving to array of values
51
- *
52
- * @example
53
- * // Get multiple user preferences
54
- * const keys = ['pref:user-1', 'pref:user-2', 'pref:user-3'];
55
- * const values = await storage.getMany(keys);
56
- */
57
- getMany(keys: string[]): Promise<(string | null)[]>;
58
-
59
- /**
60
- * Set a value for a key
61
- * Optionally specify TTL in seconds
62
- *
63
- * @param key - Redis key to set
64
- * @param value - Value to store (will be stringified if object)
65
- * @param ttl - Optional time-to-live in seconds
66
- * @returns Promise that resolves when set is complete
67
- *
68
- * @example
69
- * // Store session with 1 hour expiration
70
- * await storage.set('session:user-123', JSON.stringify(sessionData), 3600);
71
- *
72
- * @example
73
- * // Store temporary flag
74
- * await storage.set('flag:processing', 'true', 300); // 5 minutes
75
- */
76
- set(key: string, value: string, ttl?: number): Promise<void>;
77
-
78
- /**
79
- * Set multiple key-value pairs
80
- * Efficiently stores multiple entries in one operation
81
- *
82
- * @param entries - Array of key-value pairs to set
83
- * @param ttl - Optional TTL to apply to all entries
84
- * @returns Promise that resolves when all are set
85
- *
86
- * @example
87
- * // Set multiple user preferences
88
- * await storage.setMany([
89
- * { key: 'pref:theme', value: 'dark' },
90
- * { key: 'pref:lang', value: 'en' }
91
- * ], 86400); // 24 hours
92
- */
93
- setMany(entries: Array<{ key: string; value: string }>, ttl?: number): Promise<void>;
94
-
95
- /**
96
- * Delete a value by key
97
- * Returns true if key existed and was deleted
98
- *
99
- * @param key - Redis key to delete
100
- * @returns Promise resolving to deletion success
101
- *
102
- * @example
103
- * // Delete session on logout
104
- * const deleted = await storage.delete('session:user-123');
105
- */
106
- delete(key: string): Promise<boolean>;
107
-
108
- /**
109
- * Delete multiple keys
110
- * Returns number of keys that were deleted
111
- *
112
- * @param keys - Array of Redis keys to delete
113
- * @returns Promise resolving to count of deleted keys
114
- *
115
- * @example
116
- * // Delete multiple cache entries
117
- * const deletedCount = await storage.deleteMany([
118
- * 'cache:user-1',
119
- * 'cache:user-2'
120
- * ]);
121
- */
122
- deleteMany(keys: string[]): Promise<number>;
123
-
124
- /**
125
- * Check if a key exists
126
- *
127
- * @param key - Redis key to check
128
- * @returns Promise resolving to true if key exists
129
- *
130
- * @example
131
- * // Check if session exists
132
- * const hasSession = await storage.exists('session:user-123');
133
- */
134
- exists(key: string): Promise<boolean>;
135
-
136
- /**
137
- * Get remaining TTL for a key in seconds
138
- * Returns -1 if key has no expiration
139
- * Returns -2 if key doesn't exist
140
- *
141
- * @param key - Redis key to check
142
- * @returns Promise resolving to TTL in seconds
143
- *
144
- * @example
145
- * // Check session expiration
146
- * const ttl = await storage.getTTL('session:user-123');
147
- * if (ttl < 300) {
148
- * // Session expires in less than 5 minutes
149
- * }
150
- */
151
- getTTL(key: string): Promise<number>;
152
-
153
- /**
154
- * Set TTL for an existing key
155
- * Updates expiration time without changing the value
156
- *
157
- * @param key - Redis key to update
158
- * @param ttl - New TTL in seconds
159
- * @returns Promise resolving to true if TTL was set
160
- *
161
- * @example
162
- * // Extend session by 1 hour
163
- * await storage.setTTL('session:user-123', 3600);
164
- */
165
- setTTL(key: string, ttl: number): Promise<boolean>;
166
-
167
- /**
168
- * Clear all keys matching a pattern
169
- * Uses SCAN to find keys, then deletes them
170
- *
171
- * @param pattern - Redis pattern to match (supports wildcards)
172
- * @returns Promise resolving to count of deleted keys
173
- *
174
- * @example
175
- * // Clear all session keys for a tenant
176
- * const cleared = await storage.clearPattern('APP:tenant-123:session:*');
177
- *
178
- * @example
179
- * // Clear all temporary keys
180
- * await storage.clearPattern('APP:*:temp:*');
181
- */
182
- clearPattern(pattern: string): Promise<number>;
183
-
184
- /**
185
- * Clear all keys in this storage's namespace
186
- * Useful for cleanup operations
187
- *
188
- * @returns Promise that resolves when clear is complete
189
- *
190
- * @example
191
- * // Clear all storage on request end
192
- * res.on('finish', async () => {
193
- * await storage.clear();
194
- * });
195
- */
196
- clear(): Promise<void>;
197
-
198
- /**
199
- * Increment a numeric value
200
- * Creates key with value 0 if it doesn't exist
201
- *
202
- * @param key - Redis key to increment
203
- * @param amount - Amount to increment by (default: 1)
204
- * @returns Promise resolving to new value
205
- *
206
- * @example
207
- * // Increment counter
208
- * const newCount = await storage.increment('counter:requests');
209
- *
210
- * @example
211
- * // Add to score
212
- * const score = await storage.increment('score:user-123', 10);
213
- */
214
- increment(key: string, amount?: number): Promise<number>;
215
-
216
- /**
217
- * Decrement a numeric value
218
- * Creates key with value 0 if it doesn't exist
219
- *
220
- * @param key - Redis key to decrement
221
- * @param amount - Amount to decrement by (default: 1)
222
- * @returns Promise resolving to new value
223
- *
224
- * @example
225
- * // Decrement available slots
226
- * const remaining = await storage.decrement('slots:available');
227
- */
228
- decrement(key: string, amount?: number): Promise<number>;
229
- }
@@ -1,5 +0,0 @@
1
- /**
2
- * Redis utility functions
3
- */
4
- export * from './redis-key-builder';
5
- export * from './redis-key-sanitizer';
@@ -1,32 +0,0 @@
1
- import type { RedisKeyOptions } from '../interfaces/redis-key-options';
2
- /**
3
- * Build a standardized Redis key with proper formatting and sanitization
4
- *
5
- * Format: <APP_NAME>:<tenantId>:<namespace>:<segments...>
6
- *
7
- * @example
8
- * buildRedisKey({
9
- * tenantId: 'tenant-123',
10
- * namespace: RedisNamespace.CACHE,
11
- * segments: ['user', 'profile']
12
- * })
13
- * // Returns: "APP_NAME:tenant-123:cache:user:profile"
14
- */
15
- export declare function buildRedisKey(options: RedisKeyOptions): string;
16
- /**
17
- * Build a Redis key pattern for wildcard matching
18
- *
19
- * @example
20
- * buildRedisKeyPattern({
21
- * tenantId: 'tenant-123',
22
- * namespace: RedisNamespace.CACHE,
23
- * segments: ['user', '*']
24
- * })
25
- * // Returns: "APP_NAME:tenant-123:cache:user:*"
26
- */
27
- export declare function buildRedisKeyPattern(options: RedisKeyOptions): string;
28
- /**
29
- * Validate if a string is a valid Redis key
30
- * Redis keys can be up to 512MB but should be kept reasonable
31
- */
32
- export declare function isValidRedisKey(key: string): boolean;
@@ -1,68 +0,0 @@
1
- import { sanitizeKeyComponent } from './redis-key-sanitizer.js';
2
-
3
- /**
4
- * Get application name from environment or config
5
- * This will be replaced with actual config import during migration
6
- */
7
- const getAppName = () => {
8
- return process.env.APP_NAME || 'APP';
9
- };
10
- /**
11
- * Build a standardized Redis key with proper formatting and sanitization
12
- *
13
- * Format: <APP_NAME>:<tenantId>:<namespace>:<segments...>
14
- *
15
- * @example
16
- * buildRedisKey({
17
- * tenantId: 'tenant-123',
18
- * namespace: RedisNamespace.CACHE,
19
- * segments: ['user', 'profile']
20
- * })
21
- * // Returns: "APP_NAME:tenant-123:cache:user:profile"
22
- */
23
- function buildRedisKey(options) {
24
- const { tenantId = 'default', namespace, segments, userId } = options;
25
- // Sanitize all components
26
- const sanitizedTenantId = sanitizeKeyComponent(tenantId);
27
- const sanitizedNamespace = sanitizeKeyComponent(namespace);
28
- const sanitizedSegments = segments.map(sanitizeKeyComponent);
29
- // Build key parts
30
- const parts = [getAppName(), sanitizedTenantId, sanitizedNamespace, ...sanitizedSegments];
31
- // Add userId if provided
32
- if (userId) {
33
- parts.splice(2, 0, sanitizeKeyComponent(userId));
34
- }
35
- return parts.join(':');
36
- }
37
- /**
38
- * Build a Redis key pattern for wildcard matching
39
- *
40
- * @example
41
- * buildRedisKeyPattern({
42
- * tenantId: 'tenant-123',
43
- * namespace: RedisNamespace.CACHE,
44
- * segments: ['user', '*']
45
- * })
46
- * // Returns: "APP_NAME:tenant-123:cache:user:*"
47
- */
48
- function buildRedisKeyPattern(options) {
49
- // Same as buildRedisKey but allows '*' in segments
50
- return buildRedisKey(options);
51
- }
52
- /**
53
- * Validate if a string is a valid Redis key
54
- * Redis keys can be up to 512MB but should be kept reasonable
55
- */
56
- function isValidRedisKey(key) {
57
- // Basic validation rules
58
- if (!key || key.length === 0)
59
- return false;
60
- if (key.length > 1024)
61
- return false; // Reasonable limit
62
- // Check for invalid characters after sanitization
63
- // After sanitization, keys should only contain alphanumeric, colons, hyphens, underscores
64
- const validPattern = /^[a-zA-Z0-9:_-]+$/;
65
- return validPattern.test(key);
66
- }
67
-
68
- export { buildRedisKey, buildRedisKeyPattern, isValidRedisKey };
@@ -1,30 +0,0 @@
1
- /**
2
- * Sanitize a Redis key component to ensure it's valid and safe
3
- *
4
- * Redis keys can contain any binary sequence, but for best practices:
5
- * - Avoid whitespace (spaces, tabs, newlines) - replace with underscores
6
- * - Avoid control characters (0x00-0x1F, 0x7F) - remove them
7
- * - Avoid quotes and backslashes that could cause escaping issues - remove them
8
- * - Replace pipes (|) with hyphens since Auth0 userIds use pipes (auth0|123)
9
- *
10
- * @param component - The key component to sanitize
11
- * @returns Sanitized key component
12
- */
13
- export declare function sanitizeKeyComponent(component: string): string;
14
- /**
15
- * Sanitize an entire Redis key (all components)
16
- * Useful for keys that are already constructed
17
- *
18
- * @param key - The complete Redis key to sanitize
19
- * @returns Sanitized Redis key
20
- */
21
- export declare function sanitizeRedisKey(key: string): string;
22
- /**
23
- * Escape special Redis pattern characters for exact matching
24
- * Useful when you want to search for keys containing wildcards literally
25
- * Note: Hyphens are not escaped as they're commonly used in keys
26
- *
27
- * @param pattern - The pattern to escape
28
- * @returns Escaped pattern
29
- */
30
- export declare function escapeRedisPattern(pattern: string): string;
@@ -1,54 +0,0 @@
1
- /**
2
- * Sanitize a Redis key component to ensure it's valid and safe
3
- *
4
- * Redis keys can contain any binary sequence, but for best practices:
5
- * - Avoid whitespace (spaces, tabs, newlines) - replace with underscores
6
- * - Avoid control characters (0x00-0x1F, 0x7F) - remove them
7
- * - Avoid quotes and backslashes that could cause escaping issues - remove them
8
- * - Replace pipes (|) with hyphens since Auth0 userIds use pipes (auth0|123)
9
- *
10
- * @param component - The key component to sanitize
11
- * @returns Sanitized key component
12
- */
13
- function sanitizeKeyComponent(component) {
14
- if (!component)
15
- return '';
16
- return component
17
- .trim() // Trim first to remove leading/trailing whitespace
18
- .replace(/[\s\r\n\t]+/g, '_') // Replace whitespace with underscore
19
- .replace(/\|/g, '-') // Replace pipe with hyphen (Auth0 userIds: auth0|123 → auth0-123)
20
- .replace(/[\x00-\x1F\x7F]/g, '') // Remove control characters
21
- .replace(/["'\\]/g, ''); // Remove quotes and backslashes
22
- }
23
- /**
24
- * Sanitize an entire Redis key (all components)
25
- * Useful for keys that are already constructed
26
- *
27
- * @param key - The complete Redis key to sanitize
28
- * @returns Sanitized Redis key
29
- */
30
- function sanitizeRedisKey(key) {
31
- if (!key)
32
- return '';
33
- // Split by colon, sanitize each part, rejoin
34
- return key
35
- .split(':')
36
- .map(sanitizeKeyComponent)
37
- .filter((part) => part.length > 0)
38
- .join(':');
39
- }
40
- /**
41
- * Escape special Redis pattern characters for exact matching
42
- * Useful when you want to search for keys containing wildcards literally
43
- * Note: Hyphens are not escaped as they're commonly used in keys
44
- *
45
- * @param pattern - The pattern to escape
46
- * @returns Escaped pattern
47
- */
48
- function escapeRedisPattern(pattern) {
49
- // Escape Redis KEYS pattern special characters: * ? [ ] ^ \
50
- // Note: We don't escape hyphen (-) as it's not special outside character classes
51
- return pattern.replace(/[*?[\]^\\]/g, '\\$&');
52
- }
53
-
54
- export { escapeRedisPattern, sanitizeKeyComponent, sanitizeRedisKey };