dt-common-device 2.0.7 → 3.0.1

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 (211) hide show
  1. package/README.md +352 -98
  2. package/dist/alerts/Alert.model.d.ts +28 -0
  3. package/dist/alerts/Alert.model.js +222 -0
  4. package/dist/alerts/Alert.repository.d.ts +106 -0
  5. package/dist/alerts/Alert.repository.js +374 -0
  6. package/dist/alerts/Alert.service.d.ts +137 -0
  7. package/dist/alerts/Alert.service.js +476 -0
  8. package/dist/alerts/AlertBuilder.d.ts +87 -0
  9. package/dist/alerts/AlertBuilder.example.d.ts +11 -0
  10. package/dist/alerts/AlertBuilder.example.js +117 -0
  11. package/dist/alerts/AlertBuilder.js +185 -0
  12. package/dist/alerts/AlertService.example.d.ts +55 -0
  13. package/dist/alerts/AlertService.example.js +148 -0
  14. package/dist/alerts/alert.types.d.ts +57 -0
  15. package/dist/alerts/alert.types.js +22 -0
  16. package/dist/alerts/index.d.ts +3 -0
  17. package/dist/alerts/index.js +19 -0
  18. package/dist/config/config.d.ts +4 -4
  19. package/dist/config/config.js +3 -3
  20. package/dist/config/config.types.d.ts +19 -0
  21. package/dist/config/config.types.js +2 -0
  22. package/dist/connection/Connection.repository.d.ts +8 -0
  23. package/dist/connection/Connection.repository.js +92 -0
  24. package/dist/connection/Connection.service.d.ts +8 -0
  25. package/dist/connection/Connection.service.js +32 -0
  26. package/dist/connection/IConnection.d.ts +26 -0
  27. package/dist/connection/IConnection.js +14 -0
  28. package/dist/connection/index.d.ts +2 -0
  29. package/dist/connection/index.js +18 -0
  30. package/dist/device/cloud/entities/CloudDevice.d.ts +2 -2
  31. package/dist/device/cloud/entities/CloudDeviceService.d.ts +1 -1
  32. package/dist/device/cloud/entities/DeviceFactory.d.ts +1 -1
  33. package/dist/device/cloud/entities/DeviceFactory.js +1 -1
  34. package/dist/device/cloud/interface.d.ts +101 -0
  35. package/dist/device/cloud/interface.js +3 -0
  36. package/dist/device/cloud/interfaces/ICloudDeviceService.d.ts +1 -1
  37. package/dist/device/cloud/interfaces/IDeviceConnectionService.d.ts +7 -0
  38. package/dist/device/cloud/interfaces/IDeviceConnectionService.js +3 -0
  39. package/dist/device/cloud/interfaces/IDevicesService.d.ts +9 -0
  40. package/dist/device/cloud/interfaces/IDevicesService.js +2 -0
  41. package/dist/device/cloud/interfaces/IRawDevice.d.ts +1 -1
  42. package/dist/device/cloud/services/Device.service.d.ts +39 -0
  43. package/dist/device/cloud/services/Device.service.js +9 -0
  44. package/dist/device/cloud/services/DeviceCloudService.d.ts +42 -0
  45. package/dist/device/cloud/services/DeviceCloudService.js +59 -0
  46. package/dist/device/cloud/services/DeviceHub.service.d.ts +3 -0
  47. package/dist/device/cloud/services/DeviceHub.service.js +6 -0
  48. package/dist/device/cloud/services/Hub.service.d.ts +25 -0
  49. package/dist/device/cloud/services/Hub.service.js +9 -0
  50. package/dist/device/cloud/services/SmartThingsDeviceService.d.ts +38 -0
  51. package/dist/device/cloud/services/SmartThingsDeviceService.js +52 -0
  52. package/dist/device/index.d.ts +4 -0
  53. package/dist/device/index.js +20 -0
  54. package/dist/device/local/events/EventHandler.js +6 -6
  55. package/dist/device/local/events/Events.d.ts +12 -33
  56. package/dist/device/local/events/Events.js +12 -33
  57. package/dist/device/local/interface.d.ts +0 -0
  58. package/dist/device/local/interface.js +1 -0
  59. package/dist/device/local/interfaces/index.d.ts +2 -3
  60. package/dist/device/local/interfaces/index.js +2 -3
  61. package/dist/device/local/repository/Device.repository.js +3 -3
  62. package/dist/device/local/repository/Hub.repository.js +4 -4
  63. package/dist/device/local/repository/Schedule.repository.js +2 -2
  64. package/dist/device/local/services/Device.service.d.ts +2 -2
  65. package/dist/device/local/services/Device.service.js +1 -1
  66. package/dist/device/local/services/DeviceHub.service.d.ts +11 -0
  67. package/dist/device/local/services/DeviceHub.service.js +40 -0
  68. package/dist/device/local/services/index.d.ts +0 -4
  69. package/dist/device/local/services/index.js +0 -4
  70. package/dist/events/BaseEventHandler.d.ts +2 -2
  71. package/dist/events/BaseEventHandler.js +2 -2
  72. package/dist/events/BaseEventTransformer.d.ts +1 -1
  73. package/dist/events/BaseEventTransformer.js +1 -1
  74. package/dist/events/DeviceEventHandler.d.ts +1 -1
  75. package/dist/events/DeviceEventHandler.js +2 -2
  76. package/dist/events/EventHandler.js +1 -1
  77. package/dist/events/EventHandlerOrchestrator.js +1 -1
  78. package/dist/events/EventProcessingService.js +1 -1
  79. package/dist/events/InternalEventSubscription.js +1 -1
  80. package/dist/index.d.ts +7 -5
  81. package/dist/index.js +16 -13
  82. package/dist/issues/Issue.model.d.ts +28 -0
  83. package/dist/issues/Issue.model.js +260 -0
  84. package/dist/issues/Issue.repository.d.ts +113 -0
  85. package/dist/issues/Issue.repository.js +401 -0
  86. package/dist/issues/Issue.service.d.ts +168 -0
  87. package/dist/issues/Issue.service.js +642 -0
  88. package/dist/issues/IssueBuilder.d.ts +109 -0
  89. package/dist/issues/IssueBuilder.example.d.ts +16 -0
  90. package/dist/issues/IssueBuilder.example.js +196 -0
  91. package/dist/issues/IssueBuilder.js +237 -0
  92. package/dist/issues/IssueService.example.d.ts +68 -0
  93. package/dist/issues/IssueService.example.js +177 -0
  94. package/dist/issues/index.d.ts +2 -0
  95. package/dist/issues/index.js +18 -0
  96. package/dist/issues/issue.types.d.ts +90 -0
  97. package/dist/issues/issue.types.js +40 -0
  98. package/dist/property/IProperty.d.ts +29 -0
  99. package/dist/property/IProperty.js +2 -0
  100. package/dist/property/Property.repository.d.ts +8 -0
  101. package/dist/property/Property.repository.js +95 -0
  102. package/dist/property/Property.service.d.ts +8 -0
  103. package/dist/property/Property.service.js +36 -0
  104. package/dist/property/index.d.ts +2 -0
  105. package/dist/property/index.js +18 -0
  106. package/dist/queue/entities/HybridHttpQueue.d.ts +24 -0
  107. package/dist/queue/entities/HybridHttpQueue.js +241 -0
  108. package/dist/queue/entities/index.d.ts +1 -0
  109. package/dist/queue/entities/index.js +17 -0
  110. package/dist/queue/index.d.ts +5 -0
  111. package/dist/queue/index.js +22 -0
  112. package/dist/queue/interfaces/IHttpRequestJob.d.ts +9 -0
  113. package/dist/queue/interfaces/IHttpRequestJob.js +2 -0
  114. package/dist/queue/interfaces/IHybridHttpQueue.d.ts +17 -0
  115. package/dist/queue/interfaces/IHybridHttpQueue.js +2 -0
  116. package/dist/queue/interfaces/IJobResult.d.ts +14 -0
  117. package/dist/queue/interfaces/IJobResult.js +2 -0
  118. package/dist/queue/interfaces/IRateLimitConfig.d.ts +5 -0
  119. package/dist/queue/interfaces/IRateLimitConfig.js +2 -0
  120. package/dist/queue/interfaces/index.d.ts +4 -0
  121. package/dist/queue/interfaces/index.js +20 -0
  122. package/dist/queue/services/QueueService.d.ts +19 -0
  123. package/dist/queue/services/QueueService.js +73 -0
  124. package/dist/queue/services/index.d.ts +1 -0
  125. package/dist/queue/services/index.js +17 -0
  126. package/dist/queue/types/http.types.d.ts +21 -0
  127. package/dist/queue/types/http.types.js +2 -0
  128. package/dist/queue/types/index.d.ts +2 -0
  129. package/dist/queue/types/index.js +18 -0
  130. package/dist/queue/types/queue.types.d.ts +31 -0
  131. package/dist/queue/types/queue.types.js +2 -0
  132. package/dist/queue/utils/index.d.ts +3 -0
  133. package/dist/queue/utils/index.js +19 -0
  134. package/dist/queue/utils/jobUtils.d.ts +10 -0
  135. package/dist/queue/utils/jobUtils.js +64 -0
  136. package/dist/queue/utils/queueUtils.d.ts +5 -0
  137. package/dist/queue/utils/queueUtils.js +60 -0
  138. package/dist/queue/utils/rateLimit.utils.d.ts +10 -0
  139. package/dist/queue/utils/rateLimit.utils.js +97 -0
  140. package/package.json +2 -1
  141. package/src/{device/local/models → alerts}/Alert.model.ts +1 -1
  142. package/src/{device/local/repository → alerts}/Alert.repository.ts +2 -2
  143. package/src/{device/local/services → alerts}/Alert.service.ts +14 -7
  144. package/src/{device/local/entities → alerts}/AlertBuilder.example.ts +2 -2
  145. package/src/{device/local/entities → alerts}/AlertBuilder.ts +14 -8
  146. package/src/{device/local/services → alerts}/AlertService.example.ts +6 -5
  147. package/src/{types → alerts}/alert.types.ts +2 -2
  148. package/src/alerts/index.ts +3 -0
  149. package/src/config/config.ts +7 -7
  150. package/src/{types → config}/config.types.ts +1 -1
  151. package/src/{device/local/repository → connection}/Connection.repository.ts +2 -2
  152. package/src/{device/local/services → connection}/Connection.service.ts +2 -2
  153. package/src/connection/index.ts +3 -0
  154. package/src/device/cloud/entities/CloudDevice.ts +2 -2
  155. package/src/device/cloud/entities/CloudDeviceService.ts +1 -1
  156. package/src/device/cloud/entities/DeviceFactory.ts +2 -2
  157. package/src/device/cloud/interfaces/ICloudDeviceService.ts +1 -1
  158. package/src/device/cloud/interfaces/IRawDevice.ts +1 -1
  159. package/src/device/local/interfaces/index.ts +2 -3
  160. package/src/device/local/repository/Device.repository.ts +3 -3
  161. package/src/device/local/repository/Hub.repository.ts +4 -4
  162. package/src/device/local/repository/Schedule.repository.ts +2 -2
  163. package/src/device/local/services/Device.service.ts +1 -1
  164. package/src/device/local/services/index.ts +0 -4
  165. package/{TROUBLESHOOTING.md → src/docs/TROUBLESHOOTING.md} +2 -2
  166. package/src/events/BaseEventHandler.ts +3 -3
  167. package/src/events/BaseEventTransformer.ts +2 -2
  168. package/src/events/DeviceEventHandler.ts +3 -3
  169. package/src/events/EventHandler.ts +1 -1
  170. package/src/events/EventHandlerOrchestrator.ts +2 -2
  171. package/src/events/EventProcessingService.ts +2 -2
  172. package/src/events/InternalEventSubscription.ts +2 -2
  173. package/src/index.ts +19 -13
  174. package/src/{device/local/models → issues}/Issue.model.ts +1 -1
  175. package/src/{device/local/repository → issues}/Issue.repository.ts +2 -2
  176. package/src/{device/local/services → issues}/Issue.service.ts +4 -4
  177. package/src/{device/local/entities → issues}/IssueBuilder.example.ts +1 -1
  178. package/src/{device/local/entities → issues}/IssueBuilder.ts +1 -1
  179. package/src/{device/local/services → issues}/IssueService.example.ts +6 -5
  180. package/src/issues/index.ts +2 -0
  181. package/src/{device/local/repository → property}/Property.repository.ts +2 -2
  182. package/src/{device/local/services → property}/Property.service.ts +1 -1
  183. package/src/property/index.ts +2 -0
  184. package/src/queue/entities/HybridHttpQueue.ts +272 -0
  185. package/src/queue/entities/index.ts +1 -0
  186. package/src/queue/index.ts +6 -0
  187. package/src/queue/interfaces/IHttpRequestJob.ts +10 -0
  188. package/src/queue/interfaces/IHybridHttpQueue.ts +24 -0
  189. package/src/queue/interfaces/IJobResult.ts +15 -0
  190. package/src/queue/interfaces/IRateLimitConfig.ts +5 -0
  191. package/src/queue/interfaces/index.ts +4 -0
  192. package/src/queue/services/QueueService.ts +39 -0
  193. package/src/queue/services/index.ts +1 -0
  194. package/src/queue/types/http.types.ts +22 -0
  195. package/src/queue/types/index.ts +2 -0
  196. package/src/queue/types/queue.types.ts +21 -0
  197. package/src/queue/utils/index.ts +3 -0
  198. package/src/queue/utils/jobUtils.ts +80 -0
  199. package/src/queue/utils/queueUtils.ts +91 -0
  200. package/src/queue/utils/rateLimit.utils.ts +131 -0
  201. package/tsconfig.json +4 -0
  202. package/src/device/local/entities/README.md +0 -173
  203. package/src/device/local/entities/index.ts +0 -2
  204. package/src/types/index.ts +0 -3
  205. /package/src/{device/local/interfaces → connection}/IConnection.ts +0 -0
  206. /package/src/{device/local/models → docs}/Alert.model.md +0 -0
  207. /package/src/{device/local/models/README.md → docs/Alerts&IssuesModel.md} +0 -0
  208. /package/src/{device/local/models → docs}/Issue.model.md +0 -0
  209. /package/{SECURITY.md → src/docs/SECURITY.md} +0 -0
  210. /package/src/{types → issues}/issue.types.ts +0 -0
  211. /package/src/{device/local/interfaces → property}/IProperty.ts +0 -0
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JobUtils = void 0;
4
+ class JobUtils {
5
+ static async waitForJobCompletion(job, queueKey, jobResults) {
6
+ return new Promise((resolve, reject) => {
7
+ let timeoutId;
8
+ let checkCount = 0;
9
+ const maxChecks = 600;
10
+ const checkJob = async () => {
11
+ if (++checkCount >= maxChecks) {
12
+ clearTimeout(timeoutId);
13
+ return reject(new Error("Job timeout: Request took too long"));
14
+ }
15
+ try {
16
+ const state = await job.getState();
17
+ if (state === "completed") {
18
+ clearTimeout(timeoutId);
19
+ const memoryResult = jobResults.get(job.id);
20
+ if (memoryResult?.resolved) {
21
+ return memoryResult.result !== undefined
22
+ ? resolve(memoryResult.result)
23
+ : reject(new Error(memoryResult.error || "Unknown error"));
24
+ }
25
+ // Fallback to job result
26
+ resolve(await job.returnvalue);
27
+ }
28
+ else if (state === "failed") {
29
+ clearTimeout(timeoutId);
30
+ const memoryResult = jobResults.get(job.id);
31
+ const errorMsg = memoryResult?.error ||
32
+ (await job.failedReason) ||
33
+ "Unknown error";
34
+ reject(new Error(`Job failed: ${errorMsg}`));
35
+ }
36
+ else {
37
+ timeoutId = setTimeout(checkJob, checkCount < 10 ? 50 : 100);
38
+ }
39
+ }
40
+ catch (error) {
41
+ clearTimeout(timeoutId);
42
+ reject(new Error(`Error checking job: ${error.message}`));
43
+ }
44
+ };
45
+ checkJob();
46
+ // Backup timeout
47
+ setTimeout(() => {
48
+ clearTimeout(timeoutId);
49
+ reject(new Error("Request timeout: Maximum wait time exceeded"));
50
+ }, 60000);
51
+ });
52
+ }
53
+ static extractConnectionDetails(options) {
54
+ const { connectionId, connectionProvider: provider, microservice, } = options?.queueOptions ?? {};
55
+ if (!connectionId)
56
+ throw new Error("Connection ID not found in options");
57
+ if (!provider)
58
+ throw new Error("Connection provider not found in options");
59
+ if (!microservice)
60
+ throw new Error("Microservice not found in options");
61
+ return { connectionId, provider, microservice };
62
+ }
63
+ }
64
+ exports.JobUtils = JobUtils;
@@ -0,0 +1,5 @@
1
+ export declare class QueueUtils {
2
+ static getQueueKey(microservice: string, connectionId: string, provider: string): string;
3
+ static getOrCreateQueue(queueKey: string, queues: Map<string, any>): any;
4
+ static getOrCreateWorker(queueKey: string, workers: Map<string, any>, processFunction: (job: any) => Promise<any>, jobResults: Map<string, any>): void;
5
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.QueueUtils = void 0;
4
+ const config_1 = require("../../config/config");
5
+ const redis_1 = require("../../db/redis");
6
+ class QueueUtils {
7
+ static getQueueKey(microservice, connectionId, provider) {
8
+ return `${microservice}_${provider}_${connectionId}`;
9
+ }
10
+ static getOrCreateQueue(queueKey, queues) {
11
+ return (queues.get(queueKey) ??
12
+ queues
13
+ .set(queueKey, new (require("bullmq").Queue)(queueKey, {
14
+ connection: (0, redis_1.getRedisClient)(),
15
+ }))
16
+ .get(queueKey));
17
+ }
18
+ static getOrCreateWorker(queueKey, workers, processFunction, jobResults) {
19
+ if (workers.has(queueKey))
20
+ return;
21
+ const { Worker } = require("bullmq");
22
+ const worker = new Worker(queueKey, processFunction, {
23
+ connection: (0, redis_1.getRedisClient)(),
24
+ concurrency: 1,
25
+ removeOnComplete: { age: 300, count: 1 },
26
+ removeOnFail: { age: 300, count: 1 },
27
+ lockDuration: 300000,
28
+ stalledInterval: 60000,
29
+ });
30
+ // Simplified event handlers
31
+ worker.on("completed", (job) => {
32
+ (0, config_1.getConfig)().LOGGER.info(`HTTP request completed: ${job.id} [${queueKey}]`);
33
+ job.returnvalue
34
+ .then((result) => jobResults.set(job.id, {
35
+ result,
36
+ resolved: true,
37
+ timestamp: Date.now(),
38
+ }))
39
+ .catch((error) => jobResults.set(job.id, {
40
+ error: error.message,
41
+ resolved: true,
42
+ timestamp: Date.now(),
43
+ }));
44
+ });
45
+ worker.on("failed", (job, err) => {
46
+ (0, config_1.getConfig)().LOGGER.error(`HTTP request failed: ${job?.id} [${queueKey}], Error: ${err.message}`);
47
+ jobResults.set(job.id, {
48
+ error: err.message,
49
+ resolved: true,
50
+ timestamp: Date.now(),
51
+ });
52
+ });
53
+ worker.on("error", (err) => (0, config_1.getConfig)().LOGGER.error(`Worker error for ${queueKey}: ${err.message}`));
54
+ worker.on("stalled", (jobId) => (0, config_1.getConfig)().LOGGER.warn(`Job ${jobId} stalled in worker ${queueKey}`));
55
+ worker.on("active", (job) => (0, config_1.getConfig)().LOGGER.info(`HTTP request started: ${job.id} [${queueKey}]`));
56
+ workers.set(queueKey, worker);
57
+ (0, config_1.getConfig)().LOGGER.info(`Worker initialized for queue: ${queueKey}`);
58
+ }
59
+ }
60
+ exports.QueueUtils = QueueUtils;
@@ -0,0 +1,10 @@
1
+ import { IRateLimitConfig } from "../interfaces";
2
+ export declare class RateLimitUtils {
3
+ private static redisClient;
4
+ static checkRateLimit(connectionId: string, provider: string, rateLimitConfigs: Map<string, IRateLimitConfig>): Promise<boolean>;
5
+ static initializeRateLimitConfigs(): Map<string, IRateLimitConfig>;
6
+ static isRateLimitAllowed(connectionId: string, provider: string, rateLimitConfigs: Map<string, IRateLimitConfig>): Promise<boolean>;
7
+ static recordRequest(connectionId: string, provider: string): Promise<void>;
8
+ static getRawRequestTimestamps(key: string): Promise<number[]>;
9
+ static getRateLimitConfig(provider: string): IRateLimitConfig | undefined;
10
+ }
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RateLimitUtils = void 0;
4
+ const redis_1 = require("../../db/redis");
5
+ const config_1 = require("../../config/config");
6
+ class RateLimitUtils {
7
+ static async checkRateLimit(connectionId, provider, rateLimitConfigs) {
8
+ const config = rateLimitConfigs.get(provider);
9
+ if (!config) {
10
+ (0, config_1.getConfig)().LOGGER.warn(`No rate limit config found for provider: ${provider}`);
11
+ return true;
12
+ }
13
+ const key = `rate_limit:${provider}:${connectionId}`;
14
+ const now = Date.now();
15
+ const windowStart = now - config.windowMs;
16
+ try {
17
+ const data = await this.redisClient.get(key);
18
+ const requests = data
19
+ ? JSON.parse(data).filter((t) => t > windowStart)
20
+ : [];
21
+ if (requests.length >= config.maxRequests)
22
+ return false;
23
+ requests.push(now);
24
+ await this.redisClient.setex(key, Math.ceil(config.windowMs / 1000), JSON.stringify(requests));
25
+ return true;
26
+ }
27
+ catch (error) {
28
+ (0, config_1.getConfig)().LOGGER.error(`Rate limit check error: ${error}`);
29
+ return true;
30
+ }
31
+ }
32
+ static initializeRateLimitConfigs() {
33
+ const configs = new Map();
34
+ // Configure rate limits for different providers
35
+ configs.set("Sensibo", {
36
+ maxRequests: 5,
37
+ windowMs: 60000,
38
+ provider: "Sensibo",
39
+ });
40
+ return configs;
41
+ }
42
+ static async isRateLimitAllowed(connectionId, provider, rateLimitConfigs) {
43
+ const config = rateLimitConfigs.get(provider);
44
+ if (!config) {
45
+ (0, config_1.getConfig)().LOGGER.warn(`No rate limit config found for provider: ${provider}`);
46
+ return true;
47
+ }
48
+ const key = `rate_limit:${provider}:${connectionId}`;
49
+ const now = Date.now();
50
+ const windowStart = now - config.windowMs;
51
+ try {
52
+ const data = await this.redisClient.get(key);
53
+ const requests = data
54
+ ? JSON.parse(data).filter((t) => t > windowStart)
55
+ : [];
56
+ return requests.length < config.maxRequests;
57
+ }
58
+ catch (error) {
59
+ (0, config_1.getConfig)().LOGGER.error(`Rate limit check error: ${error}`);
60
+ return true;
61
+ }
62
+ }
63
+ static async recordRequest(connectionId, provider) {
64
+ const config = this.getRateLimitConfig(provider);
65
+ if (!config)
66
+ return;
67
+ const key = `rate_limit:${provider}:${connectionId}`;
68
+ const now = Date.now();
69
+ const windowStart = now - config.windowMs;
70
+ try {
71
+ const data = await this.redisClient.get(key);
72
+ const requests = data
73
+ ? JSON.parse(data).filter((t) => t > windowStart)
74
+ : [];
75
+ requests.push(now);
76
+ await this.redisClient.setex(key, Math.ceil(config.windowMs / 1000), JSON.stringify(requests));
77
+ }
78
+ catch (error) {
79
+ (0, config_1.getConfig)().LOGGER.error(`Rate limit record error: ${error}`);
80
+ }
81
+ }
82
+ static async getRawRequestTimestamps(key) {
83
+ try {
84
+ const data = await this.redisClient.get(key);
85
+ return data ? JSON.parse(data) : [];
86
+ }
87
+ catch (error) {
88
+ (0, config_1.getConfig)().LOGGER.error(`Error fetching raw request timestamps: ${error}`);
89
+ return [];
90
+ }
91
+ }
92
+ static getRateLimitConfig(provider) {
93
+ return this.initializeRateLimitConfigs().get(provider);
94
+ }
95
+ }
96
+ exports.RateLimitUtils = RateLimitUtils;
97
+ RateLimitUtils.redisClient = (0, redis_1.getRedisClient)();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dt-common-device",
3
- "version": "2.0.7",
3
+ "version": "3.0.1",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {
@@ -39,6 +39,7 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "axios": "1.10.0",
42
+ "bullmq": "5.56.4",
42
43
  "dt-audit-library": "^1.0.3",
43
44
  "dt-pub-sub": "^1.0.0",
44
45
  "ioredis": "5.6.1",
@@ -6,7 +6,7 @@ import {
6
6
  AlertDocument as IAlertDocument,
7
7
  CreateAlertData,
8
8
  UpdateAlertData,
9
- } from "../../../types/alert.types";
9
+ } from "./alert.types";
10
10
 
11
11
  // Interface for instance methods
12
12
  interface IAlertMethods {
@@ -1,12 +1,12 @@
1
1
  import { Service } from "typedi";
2
- import { AlertModel, IAlertDocument } from "../models/Alert.model";
2
+ import { AlertModel, IAlertDocument } from "./Alert.model";
3
3
  import {
4
4
  CreateAlertData,
5
5
  UpdateAlertData,
6
6
  AlertCategory,
7
7
  AlertSeverity,
8
8
  EntityType,
9
- } from "../../../types/alert.types";
9
+ } from "./alert.types";
10
10
 
11
11
  @Service()
12
12
  export class AlertRepository {
@@ -1,14 +1,14 @@
1
1
  import { Service } from "typedi";
2
- import { AlertRepository } from "../repository/Alert.repository";
3
- import { AlertModel, IAlertDocument } from "../models/Alert.model";
2
+ import { AlertRepository } from "./Alert.repository";
3
+ import { AlertModel, IAlertDocument } from "./Alert.model";
4
4
  import {
5
5
  CreateAlertData,
6
6
  UpdateAlertData,
7
7
  AlertCategory,
8
8
  AlertSeverity,
9
9
  EntityType,
10
- } from "../../../types/alert.types";
11
- import { AlertBuilder } from "../entities/AlertBuilder";
10
+ } from "./alert.types";
11
+ import { AlertBuilder } from "./AlertBuilder";
12
12
 
13
13
  @Service()
14
14
  export class AlertService {
@@ -156,7 +156,9 @@ export class AlertService {
156
156
  * Create a new alert with business logic validation
157
157
  * Accepts either a CreateAlertData object or an AlertBuilder instance
158
158
  */
159
- async createAlert(alertData: CreateAlertData | AlertBuilder): Promise<IAlertDocument> {
159
+ async createAlert(
160
+ alertData: CreateAlertData | AlertBuilder
161
+ ): Promise<IAlertDocument> {
160
162
  let processedAlertData: CreateAlertData;
161
163
 
162
164
  // Handle AlertBuilder instance
@@ -171,11 +173,16 @@ export class AlertService {
171
173
 
172
174
  // Business logic: Set default severity if not provided
173
175
  if (!processedAlertData.severity) {
174
- processedAlertData.severity = this.determineDefaultSeverity(processedAlertData.category);
176
+ processedAlertData.severity = this.determineDefaultSeverity(
177
+ processedAlertData.category
178
+ );
175
179
  }
176
180
 
177
181
  // Business logic: Validate snooze date is in the future
178
- if (processedAlertData.snoozeUntil && processedAlertData.snoozeUntil <= new Date()) {
182
+ if (
183
+ processedAlertData.snoozeUntil &&
184
+ processedAlertData.snoozeUntil <= new Date()
185
+ ) {
179
186
  throw new Error("Snooze date must be in the future");
180
187
  }
181
188
 
@@ -1,5 +1,5 @@
1
1
  import { AlertBuilder } from "./AlertBuilder";
2
- import { AlertCategory, AlertSeverity, EntityType } from "../../../types/alert.types";
2
+ import { AlertCategory, AlertSeverity, EntityType } from "./alert.types";
3
3
 
4
4
  /**
5
5
  * Example usage of AlertBuilder
@@ -123,4 +123,4 @@ export function createMultipleAlerts() {
123
123
  .build();
124
124
 
125
125
  return [alert1, alert2];
126
- }
126
+ }
@@ -3,15 +3,15 @@ import {
3
3
  AlertCategory,
4
4
  AlertSeverity,
5
5
  EntityType,
6
- } from "../../../types/alert.types";
6
+ } from "./alert.types";
7
7
 
8
8
  /**
9
9
  * AlertBuilder - A builder pattern implementation for constructing CreateAlertData objects
10
- *
10
+ *
11
11
  * This builder provides a fluent interface for creating alert data with proper validation
12
12
  * and default values. It follows the Builder pattern which is a standard design pattern
13
13
  * in TypeScript for constructing complex objects.
14
- *
14
+ *
15
15
  * Usage example:
16
16
  * const alertData = new AlertBuilder()
17
17
  * .setCategory(AlertCategory.OPERATIONS)
@@ -120,8 +120,16 @@ export class AlertBuilder {
120
120
  * Validates that all required fields are present
121
121
  */
122
122
  private validate(): void {
123
- const requiredFields = ["category", "propertyId", "title", "description", "entityType"];
124
- const missingFields = requiredFields.filter(field => !this.data[field as keyof CreateAlertData]);
123
+ const requiredFields = [
124
+ "category",
125
+ "propertyId",
126
+ "title",
127
+ "description",
128
+ "entityType",
129
+ ];
130
+ const missingFields = requiredFields.filter(
131
+ (field) => !this.data[field as keyof CreateAlertData]
132
+ );
125
133
 
126
134
  if (missingFields.length > 0) {
127
135
  throw new Error(`Missing required fields: ${missingFields.join(", ")}`);
@@ -197,6 +205,4 @@ export class AlertBuilder {
197
205
  .setEntityId(hubId)
198
206
  .setPropertyId(propertyId);
199
207
  }
200
-
201
-
202
- }
208
+ }
@@ -1,6 +1,6 @@
1
1
  import { AlertService } from "./Alert.service";
2
- import { AlertBuilder } from "../entities/AlertBuilder";
3
- import { AlertCategory, AlertSeverity, EntityType } from "../../../types/alert.types";
2
+ import { AlertBuilder } from "./AlertBuilder";
3
+ import { AlertCategory, AlertSeverity, EntityType } from "./alert.types";
4
4
 
5
5
  /**
6
6
  * Example usage of the updated AlertService with AlertBuilder integration
@@ -215,15 +215,16 @@ export class AlertServiceExample {
215
215
  category: AlertCategory.OPERATIONS,
216
216
  propertyId: "prop123",
217
217
  title: "Legacy Alert",
218
- description: "This alert was created using the old CreateAlertData format",
218
+ description:
219
+ "This alert was created using the old CreateAlertData format",
219
220
  entityId: "device456",
220
221
  entityType: EntityType.DEVICE,
221
222
  severity: AlertSeverity.MEDIUM,
222
- createdBy: "legacy-system"
223
+ createdBy: "legacy-system",
223
224
  };
224
225
 
225
226
  // This still works with the updated createAlert method
226
227
  const alert = await this.alertService.createAlert(alertData);
227
228
  return alert;
228
229
  }
229
- }
230
+ }
@@ -1,4 +1,4 @@
1
- import { EntityType } from "./issue.types";
1
+ import { EntityType } from "../issues/issue.types";
2
2
 
3
3
  export enum AlertCategory {
4
4
  READINESS = "READINESS",
@@ -61,4 +61,4 @@ export interface UpdateAlertData {
61
61
  }
62
62
 
63
63
  // Re-export EntityType from issue.types.ts to avoid duplication
64
- export { EntityType } from "./issue.types";
64
+ export { EntityType } from "../issues/issue.types";
@@ -0,0 +1,3 @@
1
+ export * from "./Alert.service";
2
+ export * from "./AlertBuilder";
3
+ export * from "./alert.types";
@@ -1,17 +1,17 @@
1
- import { DeviceConfig } from "../types";
2
1
  import { initializeAudit } from "dt-audit-library";
3
- import { connectDatabase } from "../db/db";
2
+ import { connectDatabase } from "src/db/db";
4
3
  import dotenv from "dotenv";
5
- import { InternalEventSubscription } from "../events";
6
- import { validateServiceUrl } from "../utils/http.utils";
4
+ import { InternalEventSubscription } from "src/events";
5
+ import { validateServiceUrl } from "src/utils/http.utils";
6
+ import { IConfig } from "./config.types";
7
7
 
8
8
  dotenv.config();
9
9
 
10
- let config: DeviceConfig | null = null;
10
+ let config: IConfig | null = null;
11
11
  let auditInitialized = false;
12
12
  let eventSubscription: InternalEventSubscription | null = null;
13
13
 
14
- export async function initialize(cfg: DeviceConfig): Promise<void> {
14
+ export async function initialize(cfg: IConfig): Promise<void> {
15
15
  // Initialize config
16
16
  config = { ...cfg };
17
17
 
@@ -77,7 +77,7 @@ export async function initialize(cfg: DeviceConfig): Promise<void> {
77
77
  console.log("dt-common-device: Initialization completed successfully");
78
78
  }
79
79
 
80
- export function getConfig(): DeviceConfig {
80
+ export function getConfig(): IConfig {
81
81
  if (!config) {
82
82
  throw new Error(
83
83
  "dt-common-device: Library not initialized. Call initialize() first."
@@ -8,7 +8,7 @@ export interface ILogger {
8
8
 
9
9
  type AllowedSource = "ACCESS_SERVICE" | "ADMIN_SERVICE" | "ENERGY_SERVICE";
10
10
 
11
- export type DeviceConfig = {
11
+ export type IConfig = {
12
12
  SOURCE: AllowedSource;
13
13
  SQS_QUEUE_URL: string;
14
14
  DEVICE_SERVICE?: string;
@@ -1,5 +1,5 @@
1
- import { getPostgresClient } from "../../../db";
2
- import { IConnection } from "../interfaces/IConnection";
1
+ import { getPostgresClient } from "src/db";
2
+ import { IConnection } from "./IConnection";
3
3
  import { Service } from "typedi";
4
4
 
5
5
  @Service()
@@ -1,6 +1,6 @@
1
1
  import { Container } from "typedi";
2
- import { ConnectionRepository } from "../repository/Connection.repository";
3
- import { IConnection } from "../interfaces/IConnection";
2
+ import { ConnectionRepository } from "./Connection.repository";
3
+ import { IConnection } from "./IConnection";
4
4
 
5
5
  export class LocalConnectionService {
6
6
  private readonly connectionRepository: ConnectionRepository;
@@ -0,0 +1,3 @@
1
+ export * from "./IConnection";
2
+ export * from "./Connection.service";
3
+
@@ -1,7 +1,7 @@
1
- import { IDevice } from "../../local/interfaces";
1
+ import { IDevice } from "src/device/local/interfaces";
2
2
  import { ICloudDevice } from "../interfaces/ICloudDevice";
3
3
  import { ICloudDeviceService } from "../interfaces/ICloudDeviceService";
4
- import { IConnection } from "../../local/interfaces/IConnection";
4
+ import { IConnection } from "src/connection";
5
5
 
6
6
  export abstract class CloudDevice implements ICloudDevice {
7
7
  deviceId: string;
@@ -1,5 +1,5 @@
1
1
  import { ICloudDeviceService } from "../interfaces/ICloudDeviceService";
2
- import { IConnection } from "../../local/interfaces/IConnection";
2
+ import { IConnection } from "src/connection";
3
3
 
4
4
  export class CloudDeviceService implements ICloudDeviceService {
5
5
  async getConnection(deviceId: string): Promise<IConnection> {
@@ -1,5 +1,5 @@
1
- import { IDevice } from "../../local/interfaces";
2
- import { LocalDeviceService } from "../../local/services/Device.service";
1
+ import { IDevice } from "src/device/local/interfaces";
2
+ import { LocalDeviceService } from "src/device/local/services/Device.service";
3
3
  import { IDeviceFactory } from "../interfaces/IDeviceFactory";
4
4
 
5
5
  export class DeviceFactory implements IDeviceFactory {
@@ -1,5 +1,5 @@
1
1
  // Interface for CloudDeviceService
2
- import { IConnection } from "../../local/interfaces/IConnection";
2
+ import { IConnection } from "../../../connection";
3
3
 
4
4
  export interface ICloudDeviceService {
5
5
  getConnection(deviceId: string): Promise<IConnection>;
@@ -1,4 +1,4 @@
1
- import { IConnection } from "../../local/interfaces";
1
+ import { IConnection } from "../../../connection";
2
2
 
3
3
  export enum DeviceType {
4
4
  HUB = "HUB",
@@ -1,4 +1,3 @@
1
1
  export * from "./IDevice";
2
- export * from "./IProperty";
3
- export * from "./IConnection";
4
- export * from "./IProperty";
2
+ export * from "./IDtDevice";
3
+ export * from "./ISchedule";
@@ -1,9 +1,9 @@
1
1
  import { IDevice, IStatus } from "../interfaces/IDevice";
2
- import { getConfig } from "../../../config/config";
3
- import { getPostgresClient } from "../../../db";
2
+ import { getConfig } from "src/config/config";
3
+ import { getPostgresClient } from "src/db";
4
4
  import { Service } from "typedi";
5
5
  import { IDtDevice } from "../interfaces/IDtDevice";
6
- import { getDeviceServiceAxiosInstance } from "../../../utils/http.utils";
6
+ import { getDeviceServiceAxiosInstance } from "src/utils/http.utils";
7
7
 
8
8
  @Service()
9
9
  export class DeviceRepository {
@@ -1,8 +1,8 @@
1
- import { getConfig } from "../../../config/config";
2
- import { getPostgresClient } from "../../../db";
1
+ import { getConfig } from "src/config/config";
2
+ import { getPostgresClient } from "src/db";
3
3
  import { Service } from "typedi";
4
4
  import { IDevice } from "../interfaces";
5
- import { getDeviceServiceAxiosInstance } from "../../../utils/http.utils";
5
+ import { getDeviceServiceAxiosInstance } from "src/utils/http.utils";
6
6
 
7
7
  @Service()
8
8
  export class HubRepository {
@@ -26,7 +26,7 @@ export class HubRepository {
26
26
 
27
27
  async getHubs(hubIds: string[]): Promise<IDevice[]> {
28
28
  try {
29
- const query = hubIds && hubIds.length ? `?ids=${hubIds.join(",")}` : "";
29
+ const query = hubIds?.length ? `?ids=${hubIds.join(",")}` : "";
30
30
  const response = await this.axiosInstance.get(`/devices/hubs${query}`);
31
31
  return response.data;
32
32
  } catch (error: any) {
@@ -1,7 +1,7 @@
1
1
  import { Service } from "typedi";
2
- import { getConfig } from "../../../config/config";
2
+ import { getConfig } from "src/config/config";
3
3
  import { ISchedule } from "../interfaces/ISchedule";
4
- import { getDeviceServiceAxiosInstance } from "../../../utils/http.utils";
4
+ import { getDeviceServiceAxiosInstance } from "src/utils/http.utils";
5
5
 
6
6
  @Service()
7
7
  export class ScheduleRepository {
@@ -1,5 +1,5 @@
1
1
  import { IDevice, IStatus } from "../interfaces";
2
- import { EventHandler } from "../../../events/EventHandler";
2
+ import { EventHandler } from "src/events/EventHandler";
3
3
  import { isEqual } from "lodash";
4
4
  import { DeviceRepository } from "../repository/Device.repository";
5
5
  import Container from "typedi";
@@ -1,7 +1,3 @@
1
- export * from "./Alert.service";
2
- export * from "./Connection.service";
3
1
  export * from "./Device.service";
4
2
  export * from "./Hub.service";
5
- export * from "./Issue.service";
6
- export * from "./Property.service";
7
3
  export * from "./Schedule.service";
@@ -20,7 +20,7 @@ This error typically occurs when HTTP requests fail due to network connectivity
20
20
 
21
21
  ```typescript
22
22
  // Ensure DEVICE_SERVICE URL is properly configured
23
- const config: DeviceConfig = {
23
+ const config: IConfig = {
24
24
  DEVICE_SERVICE: "http://localhost:3000", // or your actual service URL
25
25
  // ... other config
26
26
  };
@@ -41,7 +41,7 @@ This error typically occurs when HTTP requests fail due to network connectivity
41
41
 
42
42
  4. **Enable Debug Logging**
43
43
  ```typescript
44
- const config: DeviceConfig = {
44
+ const config: IConfig = {
45
45
  LOGGER: {
46
46
  info: (msg, ...args) => console.log(msg, ...args),
47
47
  warn: (msg, ...args) => console.warn(msg, ...args),