@ecashlib/shared-message 1.0.1 → 1.0.3

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.
@@ -0,0 +1,17 @@
1
+ import { MessageContent } from "./message";
2
+ /**
3
+ * Adapter for fetching messages from CMS API
4
+ */
5
+ export declare class MessageCMSAdapter {
6
+ private readonly cmsApiUrl;
7
+ private readonly cmsContextPath;
8
+ constructor();
9
+ /**
10
+ * Fetch message content from CMS API
11
+ * @param code Message code
12
+ * @param language Language code
13
+ * @returns Message content or null if not found
14
+ */
15
+ getMessageContentByCode(code: string, language: string): Promise<MessageContent | null>;
16
+ }
17
+ //# sourceMappingURL=message-cms.adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-cms.adapter.d.ts","sourceRoot":"","sources":["../src/message-cms.adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAuB3C;;GAEG;AACH,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;;IAOxC;;;;;OAKG;IACG,uBAAuB,CACzB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;CAyCpC"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MessageCMSAdapter = void 0;
4
+ /**
5
+ * Adapter for fetching messages from CMS API
6
+ */
7
+ class MessageCMSAdapter {
8
+ constructor() {
9
+ this.cmsApiUrl = process.env.CMS_API_URL || "";
10
+ this.cmsContextPath = process.env.CMS_CONTEXT_PATH || "";
11
+ }
12
+ /**
13
+ * Fetch message content from CMS API
14
+ * @param code Message code
15
+ * @param language Language code
16
+ * @returns Message content or null if not found
17
+ */
18
+ async getMessageContentByCode(code, language) {
19
+ const fullUrl = `${this.cmsApiUrl}${this.cmsContextPath}/api/v1/messages/${encodeURIComponent(code)}/content/${encodeURIComponent(language)}`;
20
+ try {
21
+ const response = await fetch(fullUrl, {
22
+ method: "GET",
23
+ headers: {
24
+ "Content-Type": "application/json"
25
+ }
26
+ });
27
+ // Handle 404 - message not found
28
+ if (response.status === 404) {
29
+ return null;
30
+ }
31
+ if (!response.ok) {
32
+ const errorData = await response.json();
33
+ throw new Error(`CMS API error: ${errorData.message || response.statusText}`);
34
+ }
35
+ const data = await response.json();
36
+ if (!data.success || !data.data) {
37
+ return null;
38
+ }
39
+ return {
40
+ code: data.data.code,
41
+ classificationCode: data.data.classificationCode,
42
+ message: data.data.message,
43
+ popup: data.data.popup
44
+ };
45
+ }
46
+ catch (error) {
47
+ throw new Error(`Không thể lấy thông tin message từ CMS API: ${error.message}`);
48
+ }
49
+ }
50
+ }
51
+ exports.MessageCMSAdapter = MessageCMSAdapter;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Message content structure returned from CMS API
3
+ */
4
+ export interface MessagePopup {
5
+ title: string;
6
+ left: string | null;
7
+ middle: string | null;
8
+ right: string | null;
9
+ count: number;
10
+ }
11
+ export interface MessageContent {
12
+ code: string;
13
+ classificationCode: string;
14
+ message: string;
15
+ popup?: MessagePopup;
16
+ }
17
+ /**
18
+ * Port interface for message service implementations
19
+ * This allows different implementations (direct API, cached, mock, etc.)
20
+ */
21
+ export interface MessageServicePort {
22
+ /**
23
+ * Get message content by code and language
24
+ * @param code Message code
25
+ * @param language Language code (e.g., 'vi', 'en')
26
+ * @returns Message content or null if not found
27
+ */
28
+ getMessageContentByCode(code: string, language: string): Promise<MessageContent | null>;
29
+ }
30
+ //# sourceMappingURL=message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../src/message.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,YAAY,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IAC/B;;;;;OAKG;IACH,uBAAuB,CACnB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CACrC"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,35 @@
1
+ import { FastifyInstance } from "fastify";
2
+ import { MessageContent, MessageServicePort } from "./message";
3
+ declare module "fastify" {
4
+ interface FastifyInstance {
5
+ messageUtil: MessageUtil;
6
+ }
7
+ }
8
+ /**
9
+ * Message utility with cache-first strategy
10
+ * Checks Redis cache first, then calls CMS API if not cached
11
+ */
12
+ export declare class MessageUtil implements MessageServicePort {
13
+ private readonly redisRepository;
14
+ private readonly cmsAdapter;
15
+ private readonly logger;
16
+ private readonly defaultTTL;
17
+ constructor(fastify: FastifyInstance);
18
+ /**
19
+ * Get message content by code and language with cache-first strategy
20
+ * @param code Message code
21
+ * @param language Language code (e.g., 'vi', 'en')
22
+ * @returns Message content or null if not found
23
+ */
24
+ getMessageContentByCode(code: string, language: string): Promise<MessageContent | null>;
25
+ /**
26
+ * Invalidate cached message
27
+ * @param code Message code
28
+ * @param language Language code
29
+ * @returns true if cache was deleted
30
+ */
31
+ invalidateCache(code: string, language: string): Promise<boolean>;
32
+ }
33
+ declare const _default: (fastify: FastifyInstance) => Promise<void>;
34
+ export default _default;
35
+ //# sourceMappingURL=message.util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message.util.d.ts","sourceRoot":"","sources":["../src/message.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAI/D,OAAO,QAAQ,SAAS,CAAC;IACrB,UAAU,eAAe;QACrB,WAAW,EAAE,WAAW,CAAC;KAC5B;CACJ;AAED;;;GAGG;AACH,qBAAa,WAAY,YAAW,kBAAkB;IAClD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;gBAE/B,OAAO,EAAE,eAAe;IAMpC;;;;;OAKG;IACG,uBAAuB,CACzB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IA4CjC;;;;;OAKG;IACG,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAgB1E;kCAGmB,eAAe;AADnC,wBAME"}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MessageUtil = void 0;
7
+ const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
8
+ const message_cms_adapter_1 = require("./message-cms.adapter");
9
+ /**
10
+ * Message utility with cache-first strategy
11
+ * Checks Redis cache first, then calls CMS API if not cached
12
+ */
13
+ class MessageUtil {
14
+ constructor(fastify) {
15
+ this.defaultTTL = 3600; // 1 hour
16
+ this.redisRepository = fastify.redisRepository;
17
+ this.cmsAdapter = new message_cms_adapter_1.MessageCMSAdapter();
18
+ this.logger = fastify.log;
19
+ }
20
+ /**
21
+ * Get message content by code and language with cache-first strategy
22
+ * @param code Message code
23
+ * @param language Language code (e.g., 'vi', 'en')
24
+ * @returns Message content or null if not found
25
+ */
26
+ async getMessageContentByCode(code, language) {
27
+ const cacheKey = `message:${code}:${language}`;
28
+ try {
29
+ // Step 1: Check Redis cache
30
+ const cachedMessage = await this.redisRepository.getObject(cacheKey);
31
+ if (cachedMessage) {
32
+ this.logger.debug(`Message found in cache - code: ${code}, language: ${language}`);
33
+ return cachedMessage;
34
+ }
35
+ this.logger.debug(`Message not in cache, fetching from CMS - code: ${code}, language: ${language}`);
36
+ // Step 2: Fetch from CMS API
37
+ const messageContent = await this.cmsAdapter.getMessageContentByCode(code, language);
38
+ // Step 3: Cache the result if found
39
+ if (messageContent) {
40
+ await this.redisRepository.setObject(cacheKey, messageContent, this.defaultTTL);
41
+ this.logger.debug(`Message cached - code: ${code}, language: ${language}, ttl: ${this.defaultTTL}s`);
42
+ }
43
+ return messageContent;
44
+ }
45
+ catch (error) {
46
+ console.log(error);
47
+ this.logger.error(`Error getting message - code: ${code}, language: ${language}`, error);
48
+ // Return null on error to prevent breaking the application
49
+ return null;
50
+ }
51
+ }
52
+ /**
53
+ * Invalidate cached message
54
+ * @param code Message code
55
+ * @param language Language code
56
+ * @returns true if cache was deleted
57
+ */
58
+ async invalidateCache(code, language) {
59
+ const cacheKey = `message:${code}:${language}`;
60
+ try {
61
+ const deleted = await this.redisRepository.delete(cacheKey);
62
+ this.logger.debug(`Cache invalidated - code: ${code}, language: ${language}, deleted: ${deleted}`);
63
+ return deleted;
64
+ }
65
+ catch (error) {
66
+ this.logger.error(`Error invalidating cache - code: ${code}, language: ${language}`, error);
67
+ return false;
68
+ }
69
+ }
70
+ }
71
+ exports.MessageUtil = MessageUtil;
72
+ exports.default = (0, fastify_plugin_1.default)(async (fastify) => {
73
+ const util = new MessageUtil(fastify);
74
+ fastify.decorate("messageUtil", util);
75
+ }, { name: "message-util", dependencies: ["redis-repository"] });
@@ -0,0 +1,213 @@
1
+ import { FastifyInstance } from "fastify";
2
+ import { Redis } from "ioredis";
3
+ declare module "fastify" {
4
+ interface FastifyInstance {
5
+ redis: Redis;
6
+ redisRepository: RedisRepository;
7
+ }
8
+ }
9
+ export declare class RedisRepository {
10
+ private readonly redis;
11
+ private readonly logger;
12
+ constructor(fastify: FastifyInstance);
13
+ /**
14
+ * Set a string value with TTL (Time To Live)
15
+ * @param key Redis key
16
+ * @param value String value to store
17
+ * @param ttlSeconds TTL in seconds
18
+ */
19
+ setString(key: string, value: string, ttlSeconds?: number): Promise<void>;
20
+ /**
21
+ * Get a string value by key
22
+ * @param key Redis key
23
+ * @returns Promise<string | null> The stored value or null if not found
24
+ */
25
+ getString(key: string): Promise<string | null>;
26
+ /**
27
+ * Set an object as JSON string with optional TTL
28
+ * @param key Redis key
29
+ * @param object Object to store
30
+ * @param ttlSeconds Optional TTL in seconds
31
+ */
32
+ setObject<T>(key: string, object: T, ttlSeconds?: number): Promise<void>;
33
+ /**
34
+ * Get an object by key and parse as JSON
35
+ * @param key Redis key
36
+ * @returns Promise<T | null> The parsed object or null if not found
37
+ */
38
+ getObject<T>(key: string): Promise<T | null>;
39
+ /**
40
+ * Get a Redis hash map operations
41
+ * @param mapName Hash map name
42
+ * @returns RedisHashMap instance for operations
43
+ */
44
+ getMap(mapName: string): RedisHashMap;
45
+ /**
46
+ * Delete a key from Redis
47
+ * @param key Redis key to delete
48
+ * @returns Promise<boolean> true if key was deleted, false if key didn't exist
49
+ */
50
+ delete(key: string): Promise<boolean>;
51
+ /**
52
+ * Check if a key exists in Redis
53
+ * @param key Redis key to check
54
+ * @returns Promise<boolean> true if key exists, false otherwise
55
+ */
56
+ exists(key: string): Promise<boolean>;
57
+ /**
58
+ * Set expiry time for an existing key
59
+ * @param key Redis key
60
+ * @param ttlSeconds TTL in seconds
61
+ * @returns Promise<boolean> true if expiry was set, false if key doesn't exist
62
+ */
63
+ expire(key: string, ttlSeconds: number): Promise<boolean>;
64
+ /**
65
+ * Get TTL (time to live) for a key
66
+ * @param key Redis key
67
+ * @returns Promise<number> TTL in seconds, -1 if no expiry, -2 if key doesn't exist
68
+ */
69
+ getTTL(key: string): Promise<number>;
70
+ /**
71
+ * Increment a numeric value stored at key
72
+ * @param key Redis key
73
+ * @param increment Amount to increment by (default: 1)
74
+ * @returns Promise<number> The new value after increment
75
+ */
76
+ increment(key: string, increment?: number): Promise<number>;
77
+ /**
78
+ * Get multiple keys at once
79
+ * @param keys Array of Redis keys
80
+ * @returns Promise<(string | null)[]> Array of values corresponding to keys
81
+ */
82
+ getMultiple(keys: string[]): Promise<(string | null)[]>;
83
+ /**
84
+ * Set multiple key-value pairs at once
85
+ * @param keyValues Object containing key-value pairs
86
+ * @returns Promise<void>
87
+ */
88
+ setMultiple(keyValues: Record<string, string>): Promise<void>;
89
+ /**
90
+ * Find keys matching a pattern using KEYS command
91
+ * WARNING: This command can be slow on large datasets. Consider using SCAN for production.
92
+ * @param pattern Pattern to match keys (supports wildcards: *, ?, [])
93
+ * @returns Promise<string[]> Array of matching key names
94
+ *
95
+ * Pattern examples:
96
+ * - "user:*" - matches all keys starting with "user:"
97
+ * - "session:*:data" - matches keys like "session:123:data"
98
+ * - "cache:user:[0-9]*" - matches keys like "cache:user:123"
99
+ */
100
+ keys(pattern: string): Promise<string[]>;
101
+ /**
102
+ * Scan keys matching a pattern using SCAN command (recommended for production)
103
+ * This is more efficient than KEYS for large datasets as it doesn't block Redis
104
+ * @param pattern Pattern to match keys
105
+ * @param count Number of keys to return per iteration (default: 10)
106
+ * @returns Promise<string[]> Array of matching key names
107
+ */
108
+ scanKeys(pattern: string, count?: number): Promise<string[]>;
109
+ /**
110
+ * Add one or more members to a Redis set
111
+ * @param key Redis set key
112
+ * @param members Members to add to the set
113
+ * @returns Promise<number> Number of members that were added (excluding already existing members)
114
+ */
115
+ setAdd(key: string, ...members: string[]): Promise<number>;
116
+ /**
117
+ * Remove one or more members from a Redis set
118
+ * @param key Redis set key
119
+ * @param members Members to remove from the set
120
+ * @returns Promise<number> Number of members that were removed
121
+ */
122
+ setRemove(key: string, ...members: string[]): Promise<number>;
123
+ /**
124
+ * Get the number of members in a Redis set
125
+ * @param key Redis set key
126
+ * @returns Promise<number> Number of members in the set
127
+ */
128
+ setSize(key: string): Promise<number>;
129
+ /**
130
+ * Check if a member exists in a Redis set
131
+ * @param key Redis set key
132
+ * @param member Member to check
133
+ * @returns Promise<boolean> true if member exists in the set
134
+ */
135
+ setContains(key: string, member: string): Promise<boolean>;
136
+ /**
137
+ * Get all members of a Redis set
138
+ * @param key Redis set key
139
+ * @returns Promise<string[]> Array of all members in the set
140
+ */
141
+ setMembers(key: string): Promise<string[]>;
142
+ /**
143
+ * Get a random member from a Redis set
144
+ * @param key Redis set key
145
+ * @param count Number of random members to return (default: 1)
146
+ * @returns Promise<string[]> Array of random members
147
+ */
148
+ setRandomMembers(key: string, count?: number): Promise<string[]>;
149
+ /**
150
+ * Pop (remove and return) a random member from a Redis set
151
+ * @param key Redis set key
152
+ * @param count Number of members to pop (default: 1)
153
+ * @returns Promise<string[]> Array of popped members
154
+ */
155
+ setPop(key: string, count?: number): Promise<string[]>;
156
+ hSet<T>(key: string, field: string, value: T): Promise<void>;
157
+ hSetMultiple(key: string, values: Record<string, any>): Promise<void>;
158
+ hGet<T>(key: string, field: string): Promise<T | null>;
159
+ hGetAll<T>(key: string): Promise<T>;
160
+ hDel(key: string): Promise<void>;
161
+ hDelItem(key: string, field: string): Promise<void>;
162
+ }
163
+ /**
164
+ * Helper class for Redis Hash Map operations
165
+ */
166
+ export declare class RedisHashMap {
167
+ private mapName;
168
+ private redis;
169
+ private logger;
170
+ constructor(mapName: string, redis: FastifyInstance["redis"], logger: FastifyInstance["log"]);
171
+ /**
172
+ * Set a field in the hash map
173
+ * @param field Hash field name
174
+ * @param value Value to set
175
+ */
176
+ set<T>(field: string, value: T): Promise<void>;
177
+ /**
178
+ * Get a field from the hash map
179
+ * @param field Hash field name
180
+ * @returns Promise<T | null> The field value or null if not found
181
+ */
182
+ get<T>(field: string): Promise<T | null>;
183
+ /**
184
+ * Get all fields and values from the hash map
185
+ * @returns Promise<Record<string, string>> All field-value pairs
186
+ */
187
+ getAll(): Promise<Record<string, string>>;
188
+ /**
189
+ * Delete a field from the hash map
190
+ * @param field Hash field name
191
+ * @returns Promise<boolean> true if field was deleted
192
+ */
193
+ delete(field: string): Promise<boolean>;
194
+ /**
195
+ * Check if a field exists in the hash map
196
+ * @param field Hash field name
197
+ * @returns Promise<boolean> true if field exists
198
+ */
199
+ exists(field: string): Promise<boolean>;
200
+ /**
201
+ * Get all field names in the hash map
202
+ * @returns Promise<string[]> Array of field names
203
+ */
204
+ getKeys(): Promise<string[]>;
205
+ /**
206
+ * Get the number of fields in the hash map
207
+ * @returns Promise<number> Number of fields
208
+ */
209
+ size(): Promise<number>;
210
+ }
211
+ declare const _default: (fastify: FastifyInstance) => Promise<void>;
212
+ export default _default;
213
+ //# sourceMappingURL=redis.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.repository.d.ts","sourceRoot":"","sources":["../src/redis.repository.ts"],"names":[],"mappings":"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"}