dt-common-device 3.0.2 → 3.0.4

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 (80) hide show
  1. package/README.md +7 -2
  2. package/dist/alerts/Alert.model.js +8 -2
  3. package/dist/alerts/Alert.repository.d.ts +3 -3
  4. package/dist/alerts/Alert.repository.js +28 -5
  5. package/dist/alerts/Alert.service.d.ts +18 -4
  6. package/dist/alerts/Alert.service.js +34 -3
  7. package/dist/alerts/AlertBuilder.d.ts +1 -1
  8. package/dist/alerts/AlertBuilder.js +1 -1
  9. package/dist/alerts/AlertService.example.js +5 -3
  10. package/dist/alerts/alert.types.d.ts +3 -3
  11. package/dist/config/config.d.ts +1 -1
  12. package/dist/config/config.js +3 -3
  13. package/dist/connection/Connection.repository.js +1 -1
  14. package/dist/constants/ConnectionProviders.d.ts +11 -0
  15. package/dist/constants/ConnectionProviders.js +14 -0
  16. package/dist/constants/Event.d.ts +14 -0
  17. package/dist/constants/Event.js +14 -0
  18. package/dist/constants/Service.d.ts +15 -0
  19. package/dist/constants/Service.js +19 -0
  20. package/dist/constants/index.d.ts +3 -0
  21. package/dist/constants/index.js +19 -0
  22. package/dist/db/redis.js +1 -0
  23. package/dist/device/cloud/entities/CloudDevice.d.ts +2 -2
  24. package/dist/device/cloud/entities/CloudDeviceService.d.ts +1 -1
  25. package/dist/device/cloud/entities/DeviceFactory.d.ts +1 -1
  26. package/dist/device/cloud/entities/DeviceFactory.js +1 -1
  27. package/dist/device/local/interfaces/IDevice.d.ts +3 -2
  28. package/dist/device/local/repository/Device.repository.js +3 -3
  29. package/dist/device/local/repository/Hub.repository.js +3 -3
  30. package/dist/device/local/repository/Schedule.repository.js +2 -2
  31. package/dist/device/local/services/Device.service.d.ts +11 -2
  32. package/dist/device/local/services/Device.service.js +145 -25
  33. package/dist/events/BaseEventHandler.d.ts +2 -2
  34. package/dist/events/BaseEventHandler.js +2 -2
  35. package/dist/events/BaseEventTransformer.d.ts +1 -1
  36. package/dist/events/BaseEventTransformer.js +1 -1
  37. package/dist/events/DeviceEventHandler.d.ts +1 -1
  38. package/dist/events/DeviceEventHandler.js +4 -3
  39. package/dist/events/EventHandler.js +1 -1
  40. package/dist/events/EventHandlerOrchestrator.js +1 -1
  41. package/dist/events/EventProcessingService.js +1 -1
  42. package/dist/events/InternalEventSubscription.js +1 -1
  43. package/dist/index.d.ts +1 -0
  44. package/dist/index.js +2 -0
  45. package/dist/issues/Issue.service.d.ts +11 -1
  46. package/dist/issues/Issue.service.js +16 -3
  47. package/dist/issues/IssueService.example.js +4 -2
  48. package/package.json +1 -1
  49. package/src/alerts/Alert.model.ts +8 -2
  50. package/src/alerts/Alert.repository.ts +28 -6
  51. package/src/alerts/Alert.service.ts +91 -7
  52. package/src/alerts/AlertBuilder.ts +2 -2
  53. package/src/alerts/AlertService.example.ts +5 -3
  54. package/src/alerts/alert.types.ts +3 -3
  55. package/src/config/config.ts +3 -3
  56. package/src/connection/Connection.repository.ts +1 -1
  57. package/src/constants/ConnectionProviders.ts +11 -0
  58. package/src/constants/Event.ts +14 -0
  59. package/src/constants/Service.ts +17 -0
  60. package/src/constants/index.ts +3 -0
  61. package/src/db/redis.ts +1 -0
  62. package/src/device/cloud/entities/CloudDevice.ts +2 -2
  63. package/src/device/cloud/entities/CloudDeviceService.ts +1 -1
  64. package/src/device/cloud/entities/DeviceFactory.ts +2 -2
  65. package/src/device/local/interfaces/IDevice.ts +3 -2
  66. package/src/device/local/repository/Device.repository.ts +3 -3
  67. package/src/device/local/repository/Hub.repository.ts +3 -3
  68. package/src/device/local/repository/Schedule.repository.ts +2 -2
  69. package/src/device/local/services/Device.service.ts +231 -29
  70. package/src/events/BaseEventHandler.ts +3 -3
  71. package/src/events/BaseEventTransformer.ts +2 -2
  72. package/src/events/DeviceEventHandler.ts +6 -4
  73. package/src/events/EventHandler.ts +1 -1
  74. package/src/events/EventHandlerOrchestrator.ts +2 -2
  75. package/src/events/EventProcessingService.ts +2 -2
  76. package/src/events/InternalEventSubscription.ts +2 -2
  77. package/src/index.ts +3 -0
  78. package/src/issues/Issue.service.ts +67 -7
  79. package/src/issues/IssueService.example.ts +4 -2
  80. package/tsconfig.json +0 -4
@@ -8,7 +8,9 @@ import {
8
8
  AlertSeverity,
9
9
  EntityType,
10
10
  } from "./alert.types";
11
+ import { Source } from "../constants/Service";
11
12
  import { AlertBuilder } from "./AlertBuilder";
13
+ import { IDevice } from "../device/local/interfaces";
12
14
 
13
15
  @Service()
14
16
  export class AlertService {
@@ -114,9 +116,9 @@ export class AlertService {
114
116
  propertyId: string,
115
117
  title: string,
116
118
  description: string,
117
- category?: AlertCategory,
119
+ category?: AlertCategory | AlertCategory[],
118
120
  severity?: AlertSeverity,
119
- createdBy?: string
121
+ source?: Source
120
122
  ): Promise<IAlertDocument> {
121
123
  const alertBuilder = AlertBuilder.createDeviceAlert(deviceId, propertyId)
122
124
  .setTitle(title)
@@ -124,7 +126,7 @@ export class AlertService {
124
126
 
125
127
  if (category) alertBuilder.setCategory(category);
126
128
  if (severity) alertBuilder.setSeverity(severity);
127
- if (createdBy) alertBuilder.setCreatedBy(createdBy);
129
+ if (source) alertBuilder.setCreatedBy(source);
128
130
 
129
131
  return await this.createAlert(alertBuilder);
130
132
  }
@@ -137,7 +139,7 @@ export class AlertService {
137
139
  propertyId: string,
138
140
  title: string,
139
141
  description: string,
140
- category?: AlertCategory,
142
+ category?: AlertCategory | AlertCategory[],
141
143
  severity?: AlertSeverity,
142
144
  createdBy?: string
143
145
  ): Promise<IAlertDocument> {
@@ -152,6 +154,68 @@ export class AlertService {
152
154
  return await this.createAlert(alertBuilder);
153
155
  }
154
156
 
157
+ /**
158
+ * Raise alert for device going offline
159
+ */
160
+ async raiseDeviceOfflineAlert(
161
+ device: IDevice,
162
+ source: Source,
163
+ reason?: string
164
+ ): Promise<IAlertDocument> {
165
+ return await this.raiseDeviceAlert(
166
+ device.deviceId,
167
+ device.propertyId,
168
+ "Device Offline",
169
+ `Device ${device.name} (${device.deviceId}) has gone offline. ${
170
+ reason ? `Reason: ${reason}` : ""
171
+ }`,
172
+ [AlertCategory.OPERATIONS],
173
+ AlertSeverity.HIGH,
174
+ source
175
+ );
176
+ }
177
+
178
+ /**
179
+ * Raise alert for device coming online
180
+ */
181
+ async raiseDeviceOnlineAlert(
182
+ device: IDevice,
183
+ source: Source,
184
+ reason?: string
185
+ ): Promise<IAlertDocument> {
186
+ return await this.raiseDeviceAlert(
187
+ device.deviceId,
188
+ device.propertyId,
189
+ "Device Online",
190
+ `Device ${device.name} (${device.deviceId}) is now online. ${
191
+ reason ? `Reason: ${reason}` : ""
192
+ }`,
193
+ [AlertCategory.OPERATIONS],
194
+ AlertSeverity.INFO,
195
+ source
196
+ );
197
+ }
198
+
199
+ /**
200
+ * Raise alert for device battery level below threshold
201
+ */
202
+ async raiseDeviceBatteryAlert(
203
+ device: IDevice,
204
+ batteryLevel: number,
205
+ threshold: number,
206
+ source: Source
207
+ ): Promise<IAlertDocument> {
208
+ return await this.raiseDeviceAlert(
209
+ device.deviceId,
210
+ device.propertyId,
211
+ "Device Battery Low",
212
+ `Device ${device.name} (${device.deviceId}) battery level is ${batteryLevel}%, which is below the property threshold of ${threshold}%.`,
213
+ [AlertCategory.ENERGY],
214
+ AlertSeverity.MEDIUM,
215
+ source
216
+ );
217
+ }
218
+
155
219
  /**
156
220
  * Create a new alert with business logic validation
157
221
  * Accepts either a CreateAlertData object or an AlertBuilder instance
@@ -216,7 +280,7 @@ export class AlertService {
216
280
  async getAlerts(
217
281
  filters: {
218
282
  propertyId?: string;
219
- category?: AlertCategory;
283
+ category?: AlertCategory | AlertCategory[];
220
284
  severity?: AlertSeverity;
221
285
  entityType?: EntityType;
222
286
  entityId?: string;
@@ -440,7 +504,7 @@ export class AlertService {
440
504
  * Get alerts by category with business logic
441
505
  */
442
506
  async getAlertsByCategory(
443
- category: AlertCategory,
507
+ category: AlertCategory | AlertCategory[],
444
508
  includeDeleted = false
445
509
  ): Promise<IAlertDocument[]> {
446
510
  if (!category) {
@@ -600,7 +664,9 @@ export class AlertService {
600
664
  }
601
665
  }
602
666
 
603
- private determineDefaultSeverity(category: AlertCategory): AlertSeverity {
667
+ private determineDefaultSeverity(
668
+ category: AlertCategory | AlertCategory[]
669
+ ): AlertSeverity {
604
670
  // Business logic: Determine default severity based on category
605
671
  const categorySeverities: Record<AlertCategory, AlertSeverity> = {
606
672
  [AlertCategory.READINESS]: AlertSeverity.MEDIUM,
@@ -610,6 +676,24 @@ export class AlertService {
610
676
  [AlertCategory.OTHER]: AlertSeverity.MEDIUM,
611
677
  };
612
678
 
679
+ // If it's an array, use the highest severity category
680
+ if (Array.isArray(category)) {
681
+ const severities = category.map(
682
+ (cat) => categorySeverities[cat] || AlertSeverity.MEDIUM
683
+ );
684
+ const severityOrder = [
685
+ AlertSeverity.CRITICAL,
686
+ AlertSeverity.HIGH,
687
+ AlertSeverity.MEDIUM,
688
+ AlertSeverity.LOW,
689
+ AlertSeverity.INFO,
690
+ ];
691
+ return (
692
+ severityOrder.find((severity) => severities.includes(severity)) ||
693
+ AlertSeverity.MEDIUM
694
+ );
695
+ }
696
+
613
697
  return categorySeverities[category] || AlertSeverity.MEDIUM;
614
698
  }
615
699
 
@@ -30,8 +30,8 @@ export class AlertBuilder {
30
30
  /**
31
31
  * Sets the alert category
32
32
  */
33
- setCategory(category: AlertCategory): AlertBuilder {
34
- this.data.category = category;
33
+ setCategory(category: AlertCategory | AlertCategory[]): AlertBuilder {
34
+ this.data.category = Array.isArray(category) ? category : [category];
35
35
  return this;
36
36
  }
37
37
 
@@ -1,3 +1,4 @@
1
+ import { Source } from "../constants/Service";
1
2
  import { AlertService } from "./Alert.service";
2
3
  import { AlertBuilder } from "./AlertBuilder";
3
4
  import { AlertCategory, AlertSeverity, EntityType } from "./alert.types";
@@ -88,7 +89,7 @@ export class AlertServiceExample {
88
89
  "Device battery level is below 20%",
89
90
  undefined, // Use default category
90
91
  undefined, // Use default severity
91
- "system"
92
+ Source.CLOUD_EVENT
92
93
  );
93
94
 
94
95
  // Create a device alert with custom category and severity
@@ -99,7 +100,7 @@ export class AlertServiceExample {
99
100
  "New firmware version is available for installation",
100
101
  AlertCategory.READINESS,
101
102
  AlertSeverity.MEDIUM,
102
- "firmware-manager"
103
+ Source.CLOUD_EVENT
103
104
  );
104
105
 
105
106
  return { deviceAlert1, deviceAlert2 };
@@ -212,7 +213,7 @@ export class AlertServiceExample {
212
213
  */
213
214
  async createAlertWithLegacyData() {
214
215
  const alertData = {
215
- category: AlertCategory.OPERATIONS,
216
+ category: [AlertCategory.OPERATIONS],
216
217
  propertyId: "prop123",
217
218
  title: "Legacy Alert",
218
219
  description:
@@ -221,6 +222,7 @@ export class AlertServiceExample {
221
222
  entityType: EntityType.DEVICE,
222
223
  severity: AlertSeverity.MEDIUM,
223
224
  createdBy: "legacy-system",
225
+ source: Source.CLOUD_EVENT,
224
226
  };
225
227
 
226
228
  // This still works with the updated createAlert method
@@ -18,7 +18,7 @@ export enum AlertSeverity {
18
18
 
19
19
  export interface AlertDocument {
20
20
  _id: string;
21
- category: AlertCategory;
21
+ category: AlertCategory[];
22
22
  propertyId: string;
23
23
  title: string;
24
24
  description: string;
@@ -36,7 +36,7 @@ export interface AlertDocument {
36
36
  }
37
37
 
38
38
  export interface CreateAlertData {
39
- category: AlertCategory;
39
+ category: AlertCategory[];
40
40
  propertyId: string;
41
41
  title: string;
42
42
  description: string;
@@ -48,7 +48,7 @@ export interface CreateAlertData {
48
48
  }
49
49
 
50
50
  export interface UpdateAlertData {
51
- category?: AlertCategory;
51
+ category?: AlertCategory[];
52
52
  title?: string;
53
53
  description?: string;
54
54
  entityId?: string;
@@ -1,8 +1,8 @@
1
1
  import { initializeAudit } from "dt-audit-library";
2
- import { connectDatabase } from "src/db/db";
2
+ import { connectDatabase } from "../db/db";
3
3
  import dotenv from "dotenv";
4
- import { InternalEventSubscription } from "src/events";
5
- import { validateServiceUrl } from "src/utils/http.utils";
4
+ import { InternalEventSubscription } from "../events";
5
+ import { validateServiceUrl } from "../utils/http.utils";
6
6
  import { IConfig } from "./config.types";
7
7
 
8
8
  dotenv.config();
@@ -1,4 +1,4 @@
1
- import { getPostgresClient } from "src/db";
1
+ import { getPostgresClient } from "../db";
2
2
  import { IConnection } from "./IConnection";
3
3
  import { Service } from "typedi";
4
4
 
@@ -0,0 +1,11 @@
1
+ export const CONNECTION_PROVIDERS = {
2
+ DEVICETHREAD: "Devicethread",
3
+ SALTOKS: "SaltoKS",
4
+ SCHLAGE: "Schlage",
5
+ SENSIBO: "Sensibo",
6
+ SMARTTHINGS: "Smartthings",
7
+ TTLOCK: "TTLock",
8
+ TUYA: "Tuya",
9
+ VERDANT: "Verdant",
10
+ YALEWIFI: "YaleWifi",
11
+ } as const;
@@ -39,6 +39,20 @@ export const DT_EVENT_TYPES = {
39
39
  UPDATED: "device.metaData.updated",
40
40
  CHANGED: "device.metaData.changed",
41
41
  },
42
+ EVENT: {
43
+ RECEIVED: "device.event.received",
44
+ REGISTERED: "device.event.registered",
45
+ UNREGISTERED: "device.event.unregistered",
46
+ PROCESSED: "device.event.processed",
47
+ UNPROCESSED: "device.event.unprocessed",
48
+ },
49
+ WEBHOOK: {
50
+ RECEIVED: "device.webhook.received",
51
+ REGISTERED: "device.webhook.registered",
52
+ UNREGISTERED: "device.webhook.unregistered",
53
+ PROCESSED: "device.webhook.processed",
54
+ UNPROCESSED: "device.webhook.unprocessed",
55
+ },
42
56
  },
43
57
  CONNECTION: {
44
58
  CREATE: {
@@ -0,0 +1,17 @@
1
+ export const SERVICE_NAMES = {
2
+ CLOUD: "smart-cloud",
3
+ ACCESS: "smart-access",
4
+ ENERGY: "smart-energy",
5
+ SCHEDULE: "smart-schedule",
6
+ DEVICE: "smart-device",
7
+ } as const;
8
+
9
+
10
+ export enum Source {
11
+ USER = "user",
12
+ CLOUD_EVENT = "cloud-event",
13
+ CLOUD_WEBHOOK = "cloud-webhook",
14
+ HEARTBEAT = "heartbeat",
15
+ CODE_ACTION = "code-action",
16
+ DEVICE_ACTION = "device-action",
17
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./ConnectionProviders";
2
+ export * from "./Event";
3
+ export * from "./Service";
package/src/db/redis.ts CHANGED
@@ -10,6 +10,7 @@ export function getRedisClient() {
10
10
  redisClient = new Redis({
11
11
  host,
12
12
  port,
13
+ maxRetriesPerRequest: null,
13
14
  });
14
15
  redisClient.on("error", (error) => {
15
16
  console.error("Redis error:", error);
@@ -1,7 +1,7 @@
1
- import { IDevice } from "src/device/local/interfaces";
1
+ import { IDevice } from "../../local/interfaces";
2
2
  import { ICloudDevice } from "../interfaces/ICloudDevice";
3
3
  import { ICloudDeviceService } from "../interfaces/ICloudDeviceService";
4
- import { IConnection } from "src/connection";
4
+ import { IConnection } from "../../../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 "src/connection";
2
+ import { IConnection } from "../../../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 "src/device/local/interfaces";
2
- import { LocalDeviceService } from "src/device/local/services/Device.service";
1
+ import { IDevice } from "../../local/interfaces";
2
+ import { LocalDeviceService } from "../../local/services/Device.service";
3
3
  import { IDeviceFactory } from "../interfaces/IDeviceFactory";
4
4
 
5
5
  export class DeviceFactory implements IDeviceFactory {
@@ -42,8 +42,8 @@ export interface IDevice {
42
42
  value: boolean;
43
43
  lastUpdated: string;
44
44
  };
45
- state?: object;
46
- metaData?: object;
45
+ state?: Record<string, any>;
46
+ metaData?: Record<string, any>;
47
47
  createdAt?: Date;
48
48
  updatedAt?: Date;
49
49
  hubDeviceDetails?: IDevice[];
@@ -51,6 +51,7 @@ export interface IDevice {
51
51
 
52
52
  export class IStatus {
53
53
  online: boolean = false;
54
+ liveStatus?: "ONLINE" | "OFFLINE";
54
55
  error?: {
55
56
  type?: string;
56
57
  message?: string;
@@ -1,9 +1,9 @@
1
1
  import { IDevice, IStatus } from "../interfaces/IDevice";
2
- import { getConfig } from "src/config/config";
3
- import { getPostgresClient } from "src/db";
2
+ import { getConfig } from "../../../config/config";
3
+ import { getPostgresClient } from "../../../db";
4
4
  import { Service } from "typedi";
5
5
  import { IDtDevice } from "../interfaces/IDtDevice";
6
- import { getDeviceServiceAxiosInstance } from "src/utils/http.utils";
6
+ import { getDeviceServiceAxiosInstance } from "../../../utils/http.utils";
7
7
 
8
8
  @Service()
9
9
  export class DeviceRepository {
@@ -1,8 +1,8 @@
1
- import { getConfig } from "src/config/config";
2
- import { getPostgresClient } from "src/db";
1
+ import { getConfig } from "../../../config/config";
2
+ import { getPostgresClient } from "../../../db";
3
3
  import { Service } from "typedi";
4
4
  import { IDevice } from "../interfaces";
5
- import { getDeviceServiceAxiosInstance } from "src/utils/http.utils";
5
+ import { getDeviceServiceAxiosInstance } from "../../../utils/http.utils";
6
6
 
7
7
  @Service()
8
8
  export class HubRepository {
@@ -1,7 +1,7 @@
1
1
  import { Service } from "typedi";
2
- import { getConfig } from "src/config/config";
2
+ import { getConfig } from "../../../config/config";
3
3
  import { ISchedule } from "../interfaces/ISchedule";
4
- import { getDeviceServiceAxiosInstance } from "src/utils/http.utils";
4
+ import { getDeviceServiceAxiosInstance } from "../../../utils/http.utils";
5
5
 
6
6
  @Service()
7
7
  export class ScheduleRepository {