@common-stack/store-redis 8.2.5-alpha.33
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 +34 -0
- package/README.md +69 -0
- package/lib/__tests__/redis-key-builder.test.d.ts +1 -0
- package/lib/__tests__/redis-key-sanitizer.test.d.ts +1 -0
- package/lib/index.d.ts +14 -0
- package/lib/index.js +3 -0
- package/lib/interfaces/cache-manager.d.ts +28 -0
- package/lib/interfaces/index.d.ts +6 -0
- package/lib/interfaces/redis-key-options.d.ts +35 -0
- package/lib/interfaces/redis-key-options.js +17 -0
- package/lib/interfaces/storage-backend.d.ts +17 -0
- package/lib/services/index.d.ts +8 -0
- package/lib/templates/constants/SERVER_TYPES.ts.template +7 -0
- package/lib/templates/repositories/IRedisCacheManager.ts.template +212 -0
- package/lib/templates/repositories/IRedisKeyBuilder.ts.template +169 -0
- package/lib/templates/repositories/IRedisService.ts.template +236 -0
- package/lib/templates/repositories/IRedisStorageBackend.ts.template +229 -0
- package/lib/templates/repositories/redisCommonTypes.ts.template +189 -0
- package/lib/utils/index.d.ts +5 -0
- package/lib/utils/redis-key-builder.d.ts +32 -0
- package/lib/utils/redis-key-builder.js +68 -0
- package/lib/utils/redis-key-sanitizer.d.ts +30 -0
- package/lib/utils/redis-key-sanitizer.js +54 -0
- package/package.json +58 -0
|
@@ -0,0 +1,68 @@
|
|
|
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 };
|
|
@@ -0,0 +1,30 @@
|
|
|
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;
|
|
@@ -0,0 +1,54 @@
|
|
|
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 };
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@common-stack/store-redis",
|
|
3
|
+
"version": "8.2.5-alpha.33",
|
|
4
|
+
"description": "Redis store utilities and services for common-stack",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"author": "CDMBase LLC",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "lib/index.js",
|
|
9
|
+
"module": "lib/index.js",
|
|
10
|
+
"types": "lib/index.d.ts",
|
|
11
|
+
"files": [
|
|
12
|
+
"lib"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "npm run build:clean && npm run build:lib",
|
|
16
|
+
"build:clean": "rimraf lib",
|
|
17
|
+
"build:lib": "rollup -c rollup.config.mjs",
|
|
18
|
+
"build:lib:watch": "npm run build:lib -- --watch",
|
|
19
|
+
"jest": "./node_modules/.bin/jest",
|
|
20
|
+
"prepublish": "npm run build",
|
|
21
|
+
"test": "cross-env ENV_FILE=../../config/test/test.env jest",
|
|
22
|
+
"test:debug": "npm test -- --runInBand",
|
|
23
|
+
"test:watch": "npm test -- --watch",
|
|
24
|
+
"watch": "npm run build:lib:watch"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@common-stack/core": "8.2.5-alpha.15"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"common": "8.2.5-alpha.15",
|
|
31
|
+
"ioredis": "^5.3.2"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"inversify": "*",
|
|
35
|
+
"ioredis": ">=5.0.0"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"cdecode": {
|
|
41
|
+
"common": {
|
|
42
|
+
"constants": [
|
|
43
|
+
"./${libDir}/templates/constants/SERVER_TYPES.ts.template"
|
|
44
|
+
],
|
|
45
|
+
"repositories": [
|
|
46
|
+
"./${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
|
+
"./${libDir}/templates/repositories/redisCommonTypes.ts.template"
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"typescript": {
|
|
55
|
+
"definition": "lib/index.d.ts"
|
|
56
|
+
},
|
|
57
|
+
"gitHead": "5745649eba49ac589b9ace8c55378b6cbe130096"
|
|
58
|
+
}
|