@ecashlib/shared-message 1.0.1 → 1.0.2
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.
|
@@ -3,61 +3,41 @@ import { IRedisCache } from "./cache-interfaces";
|
|
|
3
3
|
* Redis Cache Adapter for Message System
|
|
4
4
|
* Handles caching of messages with TTL support
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* // implement methods using your redis wrapper
|
|
11
|
-
* }
|
|
12
|
-
*
|
|
13
|
-
* const adapter = new YourRedisAdapter();
|
|
14
|
-
* const cache = new MessageCache(adapter, 3600);
|
|
6
|
+
* Cache format (matches ecash-cms):
|
|
7
|
+
* - Key: `message:${code}` (Redis hash)
|
|
8
|
+
* - Fields: language codes (vi, en, ko, etc.)
|
|
9
|
+
* - Values: message content
|
|
15
10
|
*/
|
|
16
11
|
export declare class MessageCache {
|
|
17
12
|
private readonly redis;
|
|
18
13
|
private readonly defaultTTL;
|
|
19
14
|
constructor(redis: IRedisCache, defaultTTL?: number);
|
|
20
15
|
/**
|
|
21
|
-
* Get message content from cache
|
|
22
|
-
* @param code - Message code (e.g., "ECASH_00001")
|
|
23
|
-
* @param language - Language code (e.g., "vi", "en")
|
|
24
|
-
* @returns Message content or null if not found
|
|
16
|
+
* Get message content from cache (hash field)
|
|
25
17
|
*/
|
|
26
18
|
get(code: string, language: string): Promise<string | null>;
|
|
27
19
|
/**
|
|
28
|
-
* Get all languages for a message code from cache
|
|
29
|
-
* @param code - Message code
|
|
30
|
-
* @returns Object with all language translations
|
|
20
|
+
* Get all languages for a message code from cache (entire hash)
|
|
31
21
|
*/
|
|
32
22
|
getAll(code: string): Promise<Record<string, string> | null>;
|
|
33
23
|
/**
|
|
34
|
-
* Set message content to cache
|
|
35
|
-
* @param code - Message code
|
|
36
|
-
* @param language - Language code
|
|
37
|
-
* @param content - Message content
|
|
38
|
-
* @param ttl - Time to live in seconds (optional, uses default)
|
|
24
|
+
* Set message content to cache (hash field)
|
|
39
25
|
*/
|
|
40
26
|
set(code: string, language: string, content: string, ttl?: number): Promise<void>;
|
|
41
27
|
/**
|
|
42
|
-
* Set all languages for a message code
|
|
43
|
-
* @param code - Message code
|
|
44
|
-
* @param content - Object with all language translations
|
|
45
|
-
* @param ttl - Time to live in seconds (optional)
|
|
28
|
+
* Set all languages for a message code (entire hash)
|
|
46
29
|
*/
|
|
47
30
|
setAll(code: string, content: Record<string, string>, ttl?: number): Promise<void>;
|
|
48
31
|
/**
|
|
49
|
-
* Delete message from cache (all languages)
|
|
50
|
-
* @param code - Message code
|
|
32
|
+
* Delete message from cache (all languages - delete hash)
|
|
51
33
|
*/
|
|
52
34
|
delete(code: string): Promise<void>;
|
|
53
35
|
/**
|
|
54
|
-
* Delete specific language from cache
|
|
55
|
-
* @param code - Message code
|
|
56
|
-
* @param language - Language code
|
|
36
|
+
* Delete specific language from cache (delete hash field)
|
|
57
37
|
*/
|
|
58
38
|
deleteLanguage(code: string, language: string): Promise<void>;
|
|
59
39
|
/**
|
|
60
|
-
* Clear all message cache
|
|
40
|
+
* Clear all message cache
|
|
61
41
|
*/
|
|
62
42
|
flush(): Promise<void>;
|
|
63
43
|
/**
|
|
@@ -65,11 +45,7 @@ export declare class MessageCache {
|
|
|
65
45
|
*/
|
|
66
46
|
exists(code: string, language: string): Promise<boolean>;
|
|
67
47
|
/**
|
|
68
|
-
*
|
|
69
|
-
*/
|
|
70
|
-
private delPattern;
|
|
71
|
-
/**
|
|
72
|
-
* Generate cache key
|
|
48
|
+
* Generate cache key (hash format like ecash-cms)
|
|
73
49
|
*/
|
|
74
50
|
private getKey;
|
|
75
51
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-cache.d.ts","sourceRoot":"","sources":["../../src/cache/message-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD
|
|
1
|
+
{"version":3,"file":"message-cache.d.ts","sourceRoot":"","sources":["../../src/cache/message-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;;;;;;;GAQG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,KAAK,EAAE,WAAW,EAAE,UAAU,GAAE,MAAa;IAKzD;;OAEG;IACG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASjE;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IASlE;;OAEG;IACG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvF;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxF;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKzC;;OAEG;IACG,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnE;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAM9D;;OAEG;IACH,OAAO,CAAC,MAAM;CAGf"}
|
|
@@ -5,15 +5,10 @@ exports.MessageCache = void 0;
|
|
|
5
5
|
* Redis Cache Adapter for Message System
|
|
6
6
|
* Handles caching of messages with TTL support
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* // implement methods using your redis wrapper
|
|
13
|
-
* }
|
|
14
|
-
*
|
|
15
|
-
* const adapter = new YourRedisAdapter();
|
|
16
|
-
* const cache = new MessageCache(adapter, 3600);
|
|
8
|
+
* Cache format (matches ecash-cms):
|
|
9
|
+
* - Key: `message:${code}` (Redis hash)
|
|
10
|
+
* - Fields: language codes (vi, en, ko, etc.)
|
|
11
|
+
* - Values: message content
|
|
17
12
|
*/
|
|
18
13
|
class MessageCache {
|
|
19
14
|
constructor(redis, defaultTTL = 3600) {
|
|
@@ -21,117 +16,77 @@ class MessageCache {
|
|
|
21
16
|
this.defaultTTL = defaultTTL;
|
|
22
17
|
}
|
|
23
18
|
/**
|
|
24
|
-
* Get message content from cache
|
|
25
|
-
* @param code - Message code (e.g., "ECASH_00001")
|
|
26
|
-
* @param language - Language code (e.g., "vi", "en")
|
|
27
|
-
* @returns Message content or null if not found
|
|
19
|
+
* Get message content from cache (hash field)
|
|
28
20
|
*/
|
|
29
21
|
async get(code, language) {
|
|
30
|
-
const key = this.getKey(code
|
|
31
|
-
const
|
|
32
|
-
|
|
22
|
+
const key = this.getKey(code);
|
|
23
|
+
const hash = await this.redis.hgetall(key);
|
|
24
|
+
if (hash && hash[language]) {
|
|
25
|
+
return hash[language];
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
33
28
|
}
|
|
34
29
|
/**
|
|
35
|
-
* Get all languages for a message code from cache
|
|
36
|
-
* @param code - Message code
|
|
37
|
-
* @returns Object with all language translations
|
|
30
|
+
* Get all languages for a message code from cache (entire hash)
|
|
38
31
|
*/
|
|
39
32
|
async getAll(code) {
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
if (keys.length
|
|
43
|
-
return
|
|
44
|
-
}
|
|
45
|
-
const result = {};
|
|
46
|
-
for (const key of keys) {
|
|
47
|
-
const value = await this.redis.get(key);
|
|
48
|
-
if (value) {
|
|
49
|
-
// Extract language from key: "message:ECASH_00001:vi" -> "vi"
|
|
50
|
-
const language = key.split(":").pop();
|
|
51
|
-
if (language) {
|
|
52
|
-
result[language] = value;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
33
|
+
const key = this.getKey(code);
|
|
34
|
+
const hash = await this.redis.hgetall(key);
|
|
35
|
+
if (hash && Object.keys(hash).length > 0) {
|
|
36
|
+
return hash;
|
|
55
37
|
}
|
|
56
|
-
return
|
|
38
|
+
return null;
|
|
57
39
|
}
|
|
58
40
|
/**
|
|
59
|
-
* Set message content to cache
|
|
60
|
-
* @param code - Message code
|
|
61
|
-
* @param language - Language code
|
|
62
|
-
* @param content - Message content
|
|
63
|
-
* @param ttl - Time to live in seconds (optional, uses default)
|
|
41
|
+
* Set message content to cache (hash field)
|
|
64
42
|
*/
|
|
65
43
|
async set(code, language, content, ttl) {
|
|
66
|
-
const key = this.getKey(code
|
|
67
|
-
await this.redis.
|
|
44
|
+
const key = this.getKey(code);
|
|
45
|
+
await this.redis.hset(key, language, content);
|
|
68
46
|
}
|
|
69
47
|
/**
|
|
70
|
-
* Set all languages for a message code
|
|
71
|
-
* @param code - Message code
|
|
72
|
-
* @param content - Object with all language translations
|
|
73
|
-
* @param ttl - Time to live in seconds (optional)
|
|
48
|
+
* Set all languages for a message code (entire hash)
|
|
74
49
|
*/
|
|
75
50
|
async setAll(code, content, ttl) {
|
|
76
|
-
const
|
|
77
|
-
const keyValues = {};
|
|
51
|
+
const key = this.getKey(code);
|
|
78
52
|
for (const [language, message] of Object.entries(content)) {
|
|
79
|
-
|
|
80
|
-
keyValues[key] = message;
|
|
81
|
-
}
|
|
82
|
-
await this.redis.mset(keyValues);
|
|
83
|
-
// Set TTL for each key individually since mset doesn't support TTL
|
|
84
|
-
for (const key of Object.keys(keyValues)) {
|
|
85
|
-
await this.redis.set(key, keyValues[key], expireTtl);
|
|
53
|
+
await this.redis.hset(key, language, message);
|
|
86
54
|
}
|
|
87
55
|
}
|
|
88
56
|
/**
|
|
89
|
-
* Delete message from cache (all languages)
|
|
90
|
-
* @param code - Message code
|
|
57
|
+
* Delete message from cache (all languages - delete hash)
|
|
91
58
|
*/
|
|
92
59
|
async delete(code) {
|
|
93
|
-
const
|
|
94
|
-
await this.
|
|
60
|
+
const key = this.getKey(code);
|
|
61
|
+
await this.redis.hdel(key);
|
|
95
62
|
}
|
|
96
63
|
/**
|
|
97
|
-
* Delete specific language from cache
|
|
98
|
-
* @param code - Message code
|
|
99
|
-
* @param language - Language code
|
|
64
|
+
* Delete specific language from cache (delete hash field)
|
|
100
65
|
*/
|
|
101
66
|
async deleteLanguage(code, language) {
|
|
102
|
-
const key = this.getKey(code
|
|
103
|
-
await this.redis.
|
|
67
|
+
const key = this.getKey(code);
|
|
68
|
+
await this.redis.hdel(key, language);
|
|
104
69
|
}
|
|
105
70
|
/**
|
|
106
|
-
* Clear all message cache
|
|
71
|
+
* Clear all message cache
|
|
107
72
|
*/
|
|
108
73
|
async flush() {
|
|
109
74
|
const pattern = "message:*";
|
|
110
|
-
await this.delPattern(pattern);
|
|
75
|
+
await this.redis.delPattern(pattern);
|
|
111
76
|
}
|
|
112
77
|
/**
|
|
113
78
|
* Check if message exists in cache
|
|
114
79
|
*/
|
|
115
80
|
async exists(code, language) {
|
|
116
|
-
const key = this.getKey(code
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Helper to delete keys by pattern
|
|
121
|
-
*/
|
|
122
|
-
async delPattern(pattern) {
|
|
123
|
-
// This requires the adapter to implement delPattern properly
|
|
124
|
-
// For fastify.redis, keys() returns array, then we call del()
|
|
125
|
-
const keys = [];
|
|
126
|
-
// We need to scan for keys matching pattern
|
|
127
|
-
// Since IRedisCache.delPattern returns the deleted keys, we use it
|
|
128
|
-
return await this.redis.delPattern(pattern);
|
|
81
|
+
const key = this.getKey(code);
|
|
82
|
+
const hash = await this.redis.hgetall(key);
|
|
83
|
+
return hash !== undefined && hash[language] !== undefined;
|
|
129
84
|
}
|
|
130
85
|
/**
|
|
131
|
-
* Generate cache key
|
|
86
|
+
* Generate cache key (hash format like ecash-cms)
|
|
132
87
|
*/
|
|
133
|
-
getKey(code
|
|
134
|
-
return `message:${code}
|
|
88
|
+
getKey(code) {
|
|
89
|
+
return `message:${code}`;
|
|
135
90
|
}
|
|
136
91
|
}
|
|
137
92
|
exports.MessageCache = MessageCache;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-helper.d.ts","sourceRoot":"","sources":["../../src/message/message-helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,cAAc,EACvB,WAAW,GAAE,MAAa,GACzB,MAAM,CAgBR;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,UAAU,CAC9B,cAAc,EAAE,kBAAkB,EAClC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"message-helper.d.ts","sourceRoot":"","sources":["../../src/message/message-helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,cAAc,EACvB,WAAW,GAAE,MAAa,GACzB,MAAM,CAgBR;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,UAAU,CAC9B,cAAc,EAAE,kBAAkB,EAClC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,CAAC,CA8BjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,aAAa,GACrB,MAAM,CAeR;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,cAAc,EACvB,cAAc,EAAE,kBAAkB,EAClC,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,CAAC,CAGjB"}
|
|
@@ -65,19 +65,17 @@ async function getMessage(messageService, code, language, params) {
|
|
|
65
65
|
console.error(`Error getting message ${code} in ${language}:`, error);
|
|
66
66
|
}
|
|
67
67
|
// Fallback to Vietnamese if available
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return formatMessage(fallback.message, params);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
console.error(`Error getting fallback message ${code}:`, error);
|
|
68
|
+
try {
|
|
69
|
+
const fallback = await messageService.getMessageContentByCode("ECASH_0000", language);
|
|
70
|
+
if (fallback?.message) {
|
|
71
|
+
return formatMessage(fallback.message, params);
|
|
77
72
|
}
|
|
78
73
|
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
console.error(`Error getting fallback message ${code}:`, error);
|
|
76
|
+
}
|
|
79
77
|
// Final fallback - return code
|
|
80
|
-
return `
|
|
78
|
+
return `Có lỗi xẩy ra, vui lòng thử lại sau.`;
|
|
81
79
|
}
|
|
82
80
|
/**
|
|
83
81
|
* Replace {key} placeholders in message template with actual values
|
package/package.json
CHANGED