dt-common-device 1.3.0 → 2.0.0

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 (132) hide show
  1. package/TROUBLESHOOTING.md +184 -0
  2. package/dist/config/config.d.ts +9 -2
  3. package/dist/config/config.js +97 -14
  4. package/dist/constants/Event.d.ts +75 -0
  5. package/dist/constants/Event.js +78 -0
  6. package/dist/db/db.d.ts +1 -0
  7. package/dist/db/db.js +18 -2
  8. package/dist/device/local/entities/AlertBuilder.d.ts +87 -0
  9. package/dist/device/local/entities/AlertBuilder.example.d.ts +11 -0
  10. package/dist/device/local/entities/AlertBuilder.example.js +117 -0
  11. package/dist/device/local/entities/AlertBuilder.js +179 -0
  12. package/dist/device/local/entities/IssueBuilder.d.ts +109 -0
  13. package/dist/device/local/entities/IssueBuilder.example.d.ts +16 -0
  14. package/dist/device/local/entities/IssueBuilder.example.js +196 -0
  15. package/dist/device/local/entities/IssueBuilder.js +237 -0
  16. package/dist/device/local/entities/index.d.ts +2 -0
  17. package/dist/device/local/entities/index.js +7 -0
  18. package/dist/device/local/interfaces/IDevice.d.ts +10 -9
  19. package/dist/device/local/interfaces/IDevice.js +7 -0
  20. package/dist/device/local/models/Alert.model.d.ts +28 -0
  21. package/dist/device/local/models/Alert.model.js +222 -0
  22. package/dist/device/local/models/Issue.model.d.ts +28 -0
  23. package/dist/device/local/models/Issue.model.js +260 -0
  24. package/dist/device/local/repository/Alert.repository.d.ts +106 -0
  25. package/dist/device/local/repository/Alert.repository.js +374 -0
  26. package/dist/device/local/repository/Device.repository.d.ts +10 -2
  27. package/dist/device/local/repository/Device.repository.js +153 -30
  28. package/dist/device/local/repository/Hub.repository.d.ts +1 -1
  29. package/dist/device/local/repository/Hub.repository.js +60 -18
  30. package/dist/device/local/repository/Issue.repository.d.ts +113 -0
  31. package/dist/device/local/repository/Issue.repository.js +401 -0
  32. package/dist/device/local/repository/Schedule.repository.d.ts +1 -1
  33. package/dist/device/local/repository/Schedule.repository.js +14 -18
  34. package/dist/device/local/services/Alert.service.d.ts +135 -5
  35. package/dist/device/local/services/Alert.service.js +471 -7
  36. package/dist/device/local/services/AlertService.example.d.ts +55 -0
  37. package/dist/device/local/services/AlertService.example.js +148 -0
  38. package/dist/device/local/services/Device.service.d.ts +8 -5
  39. package/dist/device/local/services/Device.service.js +58 -40
  40. package/dist/device/local/services/Issue.service.d.ts +168 -0
  41. package/dist/device/local/services/Issue.service.js +642 -0
  42. package/dist/device/local/services/IssueService.example.d.ts +68 -0
  43. package/dist/device/local/services/IssueService.example.js +177 -0
  44. package/dist/device/local/services/index.d.ts +7 -5
  45. package/dist/device/local/services/index.js +21 -11
  46. package/dist/events/BaseEventHandler.d.ts +43 -0
  47. package/dist/events/BaseEventHandler.js +111 -0
  48. package/dist/events/BaseEventTransformer.d.ts +26 -0
  49. package/dist/events/BaseEventTransformer.js +72 -0
  50. package/dist/events/DeviceEventHandler.d.ts +15 -0
  51. package/dist/events/DeviceEventHandler.js +152 -0
  52. package/dist/events/DeviceEventTransformerFactory.d.ts +27 -0
  53. package/dist/events/DeviceEventTransformerFactory.js +116 -0
  54. package/dist/events/EventHandler.d.ts +11 -0
  55. package/dist/events/EventHandler.js +106 -0
  56. package/dist/events/EventHandlerOrchestrator.d.ts +35 -0
  57. package/dist/events/EventHandlerOrchestrator.js +141 -0
  58. package/dist/events/EventProcessingService.d.ts +43 -0
  59. package/dist/events/EventProcessingService.js +243 -0
  60. package/dist/events/InternalEventSubscription.d.ts +44 -0
  61. package/dist/events/InternalEventSubscription.js +152 -0
  62. package/dist/events/index.d.ts +9 -0
  63. package/dist/events/index.js +21 -0
  64. package/dist/events/interfaces/DeviceEvent.d.ts +48 -0
  65. package/dist/events/interfaces/DeviceEvent.js +2 -0
  66. package/dist/events/interfaces/IEventHandler.d.ts +23 -0
  67. package/dist/events/interfaces/IEventHandler.js +2 -0
  68. package/dist/events/interfaces/IEventTransformer.d.ts +7 -0
  69. package/dist/events/interfaces/IEventTransformer.js +2 -0
  70. package/dist/events/interfaces/IInternalEvent.d.ts +42 -0
  71. package/dist/events/interfaces/IInternalEvent.js +2 -0
  72. package/dist/events/interfaces/index.d.ts +4 -0
  73. package/dist/events/interfaces/index.js +20 -0
  74. package/dist/index.d.ts +6 -2
  75. package/dist/index.js +9 -2
  76. package/dist/types/alert.types.d.ts +57 -0
  77. package/dist/types/alert.types.js +22 -0
  78. package/dist/types/config.types.d.ts +15 -4
  79. package/dist/types/index.d.ts +2 -0
  80. package/dist/types/index.js +2 -0
  81. package/dist/types/issue.types.d.ts +90 -0
  82. package/dist/types/issue.types.js +40 -0
  83. package/dist/utils/http-utils.d.ts +13 -0
  84. package/dist/utils/http-utils.js +117 -0
  85. package/package.json +2 -1
  86. package/src/config/config.ts +117 -14
  87. package/src/{device/local/events/Events.ts → constants/Event.ts} +34 -13
  88. package/src/db/db.ts +14 -5
  89. package/src/device/local/entities/AlertBuilder.example.ts +126 -0
  90. package/src/device/local/entities/AlertBuilder.ts +202 -0
  91. package/src/device/local/entities/IssueBuilder.example.ts +210 -0
  92. package/src/device/local/entities/IssueBuilder.ts +263 -0
  93. package/src/device/local/entities/README.md +173 -0
  94. package/src/device/local/entities/index.ts +2 -0
  95. package/src/device/local/interfaces/IDevice.ts +11 -9
  96. package/src/device/local/models/Alert.model.md +319 -0
  97. package/src/device/local/models/Alert.model.ts +283 -0
  98. package/src/device/local/models/Issue.model.md +386 -0
  99. package/src/device/local/models/Issue.model.ts +350 -0
  100. package/src/device/local/models/README.md +312 -0
  101. package/src/device/local/repository/Alert.repository.ts +465 -0
  102. package/src/device/local/repository/Device.repository.ts +241 -32
  103. package/src/device/local/repository/Hub.repository.ts +74 -18
  104. package/src/device/local/repository/Issue.repository.ts +517 -0
  105. package/src/device/local/repository/Schedule.repository.ts +28 -22
  106. package/src/device/local/services/Alert.service.ts +617 -5
  107. package/src/device/local/services/AlertService.example.ts +229 -0
  108. package/src/device/local/services/Device.service.ts +70 -50
  109. package/src/device/local/services/Issue.service.ts +872 -0
  110. package/src/device/local/services/IssueService.example.ts +307 -0
  111. package/src/device/local/services/index.ts +7 -5
  112. package/src/events/BaseEventHandler.ts +145 -0
  113. package/src/events/BaseEventTransformer.ts +97 -0
  114. package/src/events/DeviceEventHandler.ts +211 -0
  115. package/src/events/DeviceEventTransformerFactory.ts +77 -0
  116. package/src/{device/local/events → events}/EventHandler.ts +19 -15
  117. package/src/events/EventHandlerOrchestrator.ts +119 -0
  118. package/src/events/EventProcessingService.ts +248 -0
  119. package/src/events/InternalEventSubscription.ts +219 -0
  120. package/src/events/index.ts +9 -0
  121. package/src/events/interfaces/DeviceEvent.ts +56 -0
  122. package/src/events/interfaces/IEventHandler.ts +28 -0
  123. package/src/events/interfaces/IEventTransformer.ts +8 -0
  124. package/src/events/interfaces/IInternalEvent.ts +47 -0
  125. package/src/events/interfaces/index.ts +4 -0
  126. package/src/index.ts +9 -2
  127. package/src/types/alert.types.ts +64 -0
  128. package/src/types/config.types.ts +17 -4
  129. package/src/types/index.ts +2 -0
  130. package/src/types/issue.types.ts +98 -0
  131. package/src/utils/http-utils.ts +143 -0
  132. package/src/device/local/events/index.ts +0 -2
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
16
16
  };
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.getConfig = exports.initialize = exports.LocalScheduleService = exports.LocalPropertyService = exports.LocalConnectionService = exports.LocalHubService = exports.LocalDeviceService = exports.DeviceFactory = exports.CloudDeviceService = exports.CloudDevice = void 0;
18
+ exports.shutdown = exports.getConfig = exports.initialize = exports.LocalScheduleService = exports.LocalPropertyService = exports.LocalConnectionService = exports.LocalHubService = exports.LocalDeviceService = exports.DeviceFactory = exports.CloudDeviceService = exports.CloudDevice = void 0;
19
19
  // Cloud exports
20
20
  var entities_1 = require("./device/cloud/entities");
21
21
  Object.defineProperty(exports, "CloudDevice", { enumerable: true, get: function () { return entities_1.CloudDevice; } });
@@ -27,11 +27,18 @@ Object.defineProperty(exports, "LocalHubService", { enumerable: true, get: funct
27
27
  Object.defineProperty(exports, "LocalConnectionService", { enumerable: true, get: function () { return services_1.LocalConnectionService; } });
28
28
  Object.defineProperty(exports, "LocalPropertyService", { enumerable: true, get: function () { return services_1.LocalPropertyService; } });
29
29
  Object.defineProperty(exports, "LocalScheduleService", { enumerable: true, get: function () { return services_1.LocalScheduleService; } });
30
+ // Events exports
31
+ __exportStar(require("./events"), exports);
32
+ __exportStar(require("./events/interfaces"), exports);
30
33
  __exportStar(require("./device/cloud/interfaces"), exports);
31
34
  // Local exports
32
35
  __exportStar(require("./device/local/interfaces"), exports);
33
- __exportStar(require("./device/local/events"), exports);
36
+ __exportStar(require("./events"), exports);
37
+ __exportStar(require("./events/interfaces"), exports);
38
+ // Types exports
39
+ __exportStar(require("./types"), exports);
34
40
  //initialize export
35
41
  var config_1 = require("./config/config");
36
42
  Object.defineProperty(exports, "initialize", { enumerable: true, get: function () { return config_1.initialize; } });
37
43
  Object.defineProperty(exports, "getConfig", { enumerable: true, get: function () { return config_1.getConfig; } });
44
+ Object.defineProperty(exports, "shutdown", { enumerable: true, get: function () { return config_1.shutdown; } });
@@ -0,0 +1,57 @@
1
+ import { EntityType } from "./issue.types";
2
+ export declare enum AlertCategory {
3
+ READINESS = "READINESS",
4
+ OPERATIONS = "OPERATIONS",
5
+ SECURITY = "SECURITY",
6
+ ENERGY = "ENERGY",
7
+ OTHER = "OTHER"
8
+ }
9
+ export declare enum AlertSeverity {
10
+ INFO = "INFO",
11
+ LOW = "LOW",
12
+ MEDIUM = "MEDIUM",
13
+ HIGH = "HIGH",
14
+ CRITICAL = "CRITICAL"
15
+ }
16
+ export interface AlertDocument {
17
+ _id: string;
18
+ category: AlertCategory;
19
+ propertyId: string;
20
+ title: string;
21
+ description: string;
22
+ entityId?: string;
23
+ entityType: EntityType;
24
+ severity: AlertSeverity;
25
+ isRead: boolean;
26
+ isActive: boolean;
27
+ isDeleted: boolean;
28
+ snoozeUntil?: Date;
29
+ createdBy?: string;
30
+ updatedBy?: string;
31
+ createdAt: Date;
32
+ updatedAt: Date;
33
+ }
34
+ export interface CreateAlertData {
35
+ category: AlertCategory;
36
+ propertyId: string;
37
+ title: string;
38
+ description: string;
39
+ entityId?: string;
40
+ entityType: EntityType;
41
+ severity?: AlertSeverity;
42
+ createdBy?: string;
43
+ snoozeUntil?: Date;
44
+ }
45
+ export interface UpdateAlertData {
46
+ category?: AlertCategory;
47
+ title?: string;
48
+ description?: string;
49
+ entityId?: string;
50
+ entityType?: EntityType;
51
+ severity?: AlertSeverity;
52
+ isRead?: boolean;
53
+ isActive?: boolean;
54
+ snoozeUntil?: Date;
55
+ updatedBy?: string;
56
+ }
57
+ export { EntityType } from "./issue.types";
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EntityType = exports.AlertSeverity = exports.AlertCategory = void 0;
4
+ var AlertCategory;
5
+ (function (AlertCategory) {
6
+ AlertCategory["READINESS"] = "READINESS";
7
+ AlertCategory["OPERATIONS"] = "OPERATIONS";
8
+ AlertCategory["SECURITY"] = "SECURITY";
9
+ AlertCategory["ENERGY"] = "ENERGY";
10
+ AlertCategory["OTHER"] = "OTHER";
11
+ })(AlertCategory || (exports.AlertCategory = AlertCategory = {}));
12
+ var AlertSeverity;
13
+ (function (AlertSeverity) {
14
+ AlertSeverity["INFO"] = "INFO";
15
+ AlertSeverity["LOW"] = "LOW";
16
+ AlertSeverity["MEDIUM"] = "MEDIUM";
17
+ AlertSeverity["HIGH"] = "HIGH";
18
+ AlertSeverity["CRITICAL"] = "CRITICAL";
19
+ })(AlertSeverity || (exports.AlertSeverity = AlertSeverity = {}));
20
+ // Re-export EntityType from issue.types.ts to avoid duplication
21
+ var issue_types_1 = require("./issue.types");
22
+ Object.defineProperty(exports, "EntityType", { enumerable: true, get: function () { return issue_types_1.EntityType; } });
@@ -1,8 +1,19 @@
1
+ import { IInternalEvent } from "../events/interfaces/IInternalEvent";
2
+ export interface ILogger {
3
+ info(message: string, ...args: any[]): void;
4
+ warn(message: string, ...args: any[]): void;
5
+ error(message: string, ...args: any[]): void;
6
+ }
7
+ type AllowedSource = "ACCESS_SERVICE" | "ADMIN_SERVICE" | "ENERGY_SERVICE";
1
8
  export type DeviceConfig = {
2
- ADMIN_SERVICE?: string;
3
- OPERATIONAL_SERVICE?: string;
9
+ SOURCE: AllowedSource;
10
+ SQS_QUEUE_URL: string;
4
11
  DEVICE_SERVICE?: string;
5
- MONITORING_SERVICE?: string;
12
+ ADMIN_SERVICE?: string;
13
+ ACCESS_SERVICE?: string;
6
14
  ENERGY_SERVICE?: string;
7
- [key: string]: string | undefined;
15
+ INTERNAL_EVENT_HANDLER: IInternalEvent;
16
+ LOGGER: ILogger;
17
+ [key: string]: any;
8
18
  };
19
+ export {};
@@ -1 +1,3 @@
1
1
  export * from "./config.types";
2
+ export * from "./issue.types";
3
+ export * from "./alert.types";
@@ -15,3 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./config.types"), exports);
18
+ __exportStar(require("./issue.types"), exports);
19
+ __exportStar(require("./alert.types"), exports);
@@ -0,0 +1,90 @@
1
+ export declare enum IssuesCategory {
2
+ READINESS = "READINESS",
3
+ OPERATIONS = "OPERATIONS",
4
+ SECURITY = "SECURITY",
5
+ ENERGY = "ENERGY",
6
+ OTHER = "OTHER"
7
+ }
8
+ export declare enum EntityType {
9
+ DEVICE = "DEVICE",
10
+ COLLECTION = "COLLECTION",
11
+ USER = "USER",
12
+ INTEGRATION = "INTEGRATION",
13
+ PROPERTY = "PROPERTY",
14
+ HUB = "HUB",
15
+ SCHEDULE = "SCHEDULE",
16
+ ALERT = "ALERT",
17
+ OTHER = "OTHER"
18
+ }
19
+ export declare enum IssueStatus {
20
+ PENDING = "PENDING",
21
+ IN_PROGRESS = "IN_PROGRESS",
22
+ RESOLVED = "RESOLVED",
23
+ CLOSED = "CLOSED",
24
+ CANCELLED = "CANCELLED",
25
+ ON_HOLD = "ON_HOLD"
26
+ }
27
+ export declare enum IssuePriority {
28
+ LOW = "LOW",
29
+ MEDIUM = "MEDIUM",
30
+ HIGH = "HIGH",
31
+ CRITICAL = "CRITICAL",
32
+ URGENT = "URGENT"
33
+ }
34
+ export interface IssueComment {
35
+ id: string;
36
+ userId: string;
37
+ content: string;
38
+ createdAt: Date;
39
+ updatedAt?: Date;
40
+ }
41
+ export interface IssueDocument {
42
+ _id: string;
43
+ category: IssuesCategory;
44
+ propertyId: string;
45
+ title: string;
46
+ description: string;
47
+ entityId?: string;
48
+ entityType: EntityType;
49
+ status: IssueStatus;
50
+ priority: IssuePriority;
51
+ assignedTo?: string;
52
+ createdBy: string;
53
+ updatedBy?: string;
54
+ isDeleted: boolean;
55
+ createdAt: Date;
56
+ updatedAt: Date;
57
+ resolvedAt?: Date;
58
+ dueDate?: Date;
59
+ comments?: IssueComment[];
60
+ }
61
+ export interface CreateIssueData {
62
+ category: IssuesCategory;
63
+ propertyId: string;
64
+ title: string;
65
+ description: string;
66
+ entityId?: string;
67
+ entityType: EntityType;
68
+ priority?: IssuePriority;
69
+ assignedTo?: string;
70
+ createdBy: string;
71
+ dueDate?: Date;
72
+ }
73
+ export interface UpdateIssueData {
74
+ category?: IssuesCategory;
75
+ title?: string;
76
+ description?: string;
77
+ entityId?: string;
78
+ entityType?: EntityType;
79
+ status?: IssueStatus;
80
+ priority?: IssuePriority;
81
+ assignedTo?: string;
82
+ updatedBy: string;
83
+ resolvedAt?: Date;
84
+ dueDate?: Date;
85
+ isDeleted?: boolean;
86
+ }
87
+ export interface AddCommentData {
88
+ userId: string;
89
+ content: string;
90
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IssuePriority = exports.IssueStatus = exports.EntityType = exports.IssuesCategory = void 0;
4
+ var IssuesCategory;
5
+ (function (IssuesCategory) {
6
+ IssuesCategory["READINESS"] = "READINESS";
7
+ IssuesCategory["OPERATIONS"] = "OPERATIONS";
8
+ IssuesCategory["SECURITY"] = "SECURITY";
9
+ IssuesCategory["ENERGY"] = "ENERGY";
10
+ IssuesCategory["OTHER"] = "OTHER";
11
+ })(IssuesCategory || (exports.IssuesCategory = IssuesCategory = {}));
12
+ var EntityType;
13
+ (function (EntityType) {
14
+ EntityType["DEVICE"] = "DEVICE";
15
+ EntityType["COLLECTION"] = "COLLECTION";
16
+ EntityType["USER"] = "USER";
17
+ EntityType["INTEGRATION"] = "INTEGRATION";
18
+ EntityType["PROPERTY"] = "PROPERTY";
19
+ EntityType["HUB"] = "HUB";
20
+ EntityType["SCHEDULE"] = "SCHEDULE";
21
+ EntityType["ALERT"] = "ALERT";
22
+ EntityType["OTHER"] = "OTHER";
23
+ })(EntityType || (exports.EntityType = EntityType = {}));
24
+ var IssueStatus;
25
+ (function (IssueStatus) {
26
+ IssueStatus["PENDING"] = "PENDING";
27
+ IssueStatus["IN_PROGRESS"] = "IN_PROGRESS";
28
+ IssueStatus["RESOLVED"] = "RESOLVED";
29
+ IssueStatus["CLOSED"] = "CLOSED";
30
+ IssueStatus["CANCELLED"] = "CANCELLED";
31
+ IssueStatus["ON_HOLD"] = "ON_HOLD";
32
+ })(IssueStatus || (exports.IssueStatus = IssueStatus = {}));
33
+ var IssuePriority;
34
+ (function (IssuePriority) {
35
+ IssuePriority["LOW"] = "LOW";
36
+ IssuePriority["MEDIUM"] = "MEDIUM";
37
+ IssuePriority["HIGH"] = "HIGH";
38
+ IssuePriority["CRITICAL"] = "CRITICAL";
39
+ IssuePriority["URGENT"] = "URGENT";
40
+ })(IssuePriority || (exports.IssuePriority = IssuePriority = {}));
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Validates if a URL is properly formatted and accessible
3
+ */
4
+ export declare function validateServiceUrl(url: string): boolean;
5
+ /**
6
+ * Creates a properly configured axios instance with error handling
7
+ */
8
+ export declare function createAxiosInstance(baseURL?: string): import("axios").AxiosInstance;
9
+ export declare function getDeviceServiceAxiosInstance(): any;
10
+ /**
11
+ * Retry function for failed HTTP requests
12
+ */
13
+ export declare function retryRequest<T>(requestFn: () => Promise<T>, maxRetries?: number, delay?: number): Promise<T>;
@@ -0,0 +1,117 @@
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.validateServiceUrl = validateServiceUrl;
7
+ exports.createAxiosInstance = createAxiosInstance;
8
+ exports.getDeviceServiceAxiosInstance = getDeviceServiceAxiosInstance;
9
+ exports.retryRequest = retryRequest;
10
+ const config_1 = require("../config/config");
11
+ const axios_1 = __importDefault(require("axios"));
12
+ /**
13
+ * Validates if a URL is properly formatted and accessible
14
+ */
15
+ function validateServiceUrl(url) {
16
+ try {
17
+ const parsedUrl = new URL(url);
18
+ return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:";
19
+ }
20
+ catch (error) {
21
+ (0, config_1.getConfig)().LOGGER.error(`Invalid service URL: ${url}`, error);
22
+ return false;
23
+ }
24
+ }
25
+ /**
26
+ * Creates a properly configured axios instance with error handling
27
+ */
28
+ function createAxiosInstance(baseURL) {
29
+ const instance = axios_1.default.create({
30
+ baseURL,
31
+ timeout: 30000, // 30 seconds timeout
32
+ maxRedirects: 5,
33
+ validateStatus: (status) => status < 500, // Don't throw on 4xx errors
34
+ headers: {
35
+ "Content-Type": "application/json",
36
+ "User-Agent": "dt-common-device/1.3.0",
37
+ },
38
+ });
39
+ // Add request interceptor for logging
40
+ instance.interceptors.request.use((config) => {
41
+ const logger = (0, config_1.getConfig)().LOGGER;
42
+ logger.info(`Making request to: ${config.method?.toUpperCase()} ${config.url}`, {
43
+ baseURL: config.baseURL,
44
+ timeout: config.timeout,
45
+ });
46
+ return config;
47
+ }, (error) => {
48
+ (0, config_1.getConfig)().LOGGER.error("Request interceptor error:", error);
49
+ return Promise.reject(error);
50
+ });
51
+ // Add response interceptor for error handling
52
+ instance.interceptors.response.use((response) => {
53
+ return response;
54
+ }, (error) => {
55
+ const logger = (0, config_1.getConfig)().LOGGER;
56
+ const errorInfo = {
57
+ url: error.config?.url,
58
+ method: error.config?.method,
59
+ status: error.response?.status,
60
+ statusText: error.response?.statusText,
61
+ message: error.message,
62
+ code: error.code,
63
+ baseURL: error.config?.baseURL,
64
+ };
65
+ logger.error("HTTP request failed:", errorInfo);
66
+ // Log additional details for network errors
67
+ if (error.code === "ECONNREFUSED" || error.code === "ENOTFOUND") {
68
+ logger.error("Network connectivity issue detected. Please check:", {
69
+ serviceUrl: error.config?.baseURL,
70
+ errorCode: error.code,
71
+ errorMessage: error.message,
72
+ });
73
+ }
74
+ return Promise.reject(error);
75
+ });
76
+ return instance;
77
+ }
78
+ /**
79
+ * Centralized axios instance for device service
80
+ */
81
+ let deviceServiceAxiosInstance = null;
82
+ function getDeviceServiceAxiosInstance() {
83
+ if (!deviceServiceAxiosInstance) {
84
+ const { DEVICE_SERVICE } = (0, config_1.getConfig)();
85
+ if (!DEVICE_SERVICE) {
86
+ throw new Error("DEVICE_SERVICE is not configured. Call initialize() first with DEVICE_SERVICE.");
87
+ }
88
+ deviceServiceAxiosInstance = createAxiosInstance(DEVICE_SERVICE);
89
+ }
90
+ return deviceServiceAxiosInstance;
91
+ }
92
+ /**
93
+ * Retry function for failed HTTP requests
94
+ */
95
+ async function retryRequest(requestFn, maxRetries = 3, delay = 1000) {
96
+ let lastError;
97
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
98
+ try {
99
+ return await requestFn();
100
+ }
101
+ catch (error) {
102
+ lastError = error;
103
+ if (attempt === maxRetries) {
104
+ (0, config_1.getConfig)().LOGGER.error(`Request failed after ${maxRetries} attempts:`, error);
105
+ throw error;
106
+ }
107
+ (0, config_1.getConfig)().LOGGER.warn(`Request attempt ${attempt} failed, retrying in ${delay}ms:`, {
108
+ error: error.message,
109
+ attempt,
110
+ maxRetries,
111
+ });
112
+ await new Promise((resolve) => setTimeout(resolve, delay));
113
+ delay *= 2; // Exponential backoff
114
+ }
115
+ }
116
+ throw lastError;
117
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dt-common-device",
3
- "version": "1.3.0",
3
+ "version": "2.0.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {
@@ -43,6 +43,7 @@
43
43
  "dt-pub-sub": "^1.0.0",
44
44
  "ioredis": "5.6.1",
45
45
  "lodash": "^4.17.21",
46
+ "mongoose": "8.16.1",
46
47
  "pg": "8.16.3",
47
48
  "typedi": "0.10.0"
48
49
  }
@@ -1,25 +1,80 @@
1
1
  import { DeviceConfig } from "../types";
2
2
  import { initializeAudit } from "dt-audit-library";
3
+ import { connectDatabase } from "../db/db";
3
4
  import dotenv from "dotenv";
5
+ import { InternalEventSubscription } from "../events";
6
+ import { validateServiceUrl } from "../utils/http-utils";
7
+
4
8
  dotenv.config();
5
9
 
6
10
  let config: DeviceConfig | null = null;
7
11
  let auditInitialized = false;
12
+ let eventSubscription: InternalEventSubscription | null = null;
8
13
 
9
- export function initialize(cfg: DeviceConfig) {
10
- // Check if at least one service is provided
11
- const hasAtLeastOneService = [
12
- "ADMIN_SERVICE",
13
- "OPERATIONAL_SERVICE",
14
- "DEVICE_SERVICE",
15
- "MONITORING_SERVICE",
16
- "ENERGY_SERVICE",
17
- ].some((key) => Boolean(cfg[key]));
18
-
19
- if (!hasAtLeastOneService) {
20
- throw new Error("At least one http service must be initialized");
21
- }
14
+ export async function initialize(cfg: DeviceConfig): Promise<void> {
15
+ // Initialize config
22
16
  config = { ...cfg };
17
+
18
+ // Validate service URLs if provided
19
+ if (cfg.DEVICE_SERVICE && !validateServiceUrl(cfg.DEVICE_SERVICE)) {
20
+ throw new Error(`Invalid DEVICE_SERVICE URL: ${cfg.DEVICE_SERVICE}`);
21
+ }
22
+ if (cfg.ADMIN_SERVICE && !validateServiceUrl(cfg.ADMIN_SERVICE)) {
23
+ throw new Error(`Invalid ADMIN_SERVICE URL: ${cfg.ADMIN_SERVICE}`);
24
+ }
25
+ if (cfg.ACCESS_SERVICE && !validateServiceUrl(cfg.ACCESS_SERVICE)) {
26
+ throw new Error(`Invalid ACCESS_SERVICE URL: ${cfg.ACCESS_SERVICE}`);
27
+ }
28
+ if (cfg.ENERGY_SERVICE && !validateServiceUrl(cfg.ENERGY_SERVICE)) {
29
+ throw new Error(`Invalid ENERGY_SERVICE URL: ${cfg.ENERGY_SERVICE}`);
30
+ }
31
+
32
+ // Initialize internal event subscription if handler is provided
33
+ if (cfg.INTERNAL_EVENT_HANDLER) {
34
+ try {
35
+ eventSubscription = new InternalEventSubscription(
36
+ cfg.INTERNAL_EVENT_HANDLER
37
+ );
38
+ cfg.LOGGER.info("InternalEventSubscription initialized successfully");
39
+ } catch (error) {
40
+ cfg.LOGGER.error("Failed to initialize InternalEventSubscription", {
41
+ error,
42
+ });
43
+ throw error;
44
+ }
45
+ }
46
+
47
+ // Connect to databases
48
+ try {
49
+ await connectDatabase();
50
+ cfg.LOGGER.info("Database connections established successfully");
51
+ } catch (error) {
52
+ cfg.LOGGER.error("Failed to connect to databases", { error });
53
+ throw error;
54
+ }
55
+
56
+ // Subscribe to events if event subscription is available
57
+ if (eventSubscription) {
58
+ try {
59
+ await eventSubscription.subscribe();
60
+ cfg.LOGGER.info("Event subscription started successfully");
61
+ } catch (error: any) {
62
+ cfg.LOGGER.error(
63
+ `Failed to start event subscription: ${
64
+ error.message || error.toString()
65
+ }`
66
+ );
67
+ // Don't throw here as the main setup should continue
68
+ }
69
+ }
70
+
71
+ // Check if required env variables are set
72
+ checkRequiredEnv();
73
+
74
+ // Initialize audit
75
+ ensureAuditInitialized();
76
+
77
+ console.log("dt-common-device: Initialization completed successfully");
23
78
  }
24
79
 
25
80
  export function getConfig(): DeviceConfig {
@@ -31,12 +86,22 @@ export function getConfig(): DeviceConfig {
31
86
  return config;
32
87
  }
33
88
 
34
- export function checkAwsEnv() {
89
+ export function getEventSubscription(): InternalEventSubscription | null {
90
+ return eventSubscription;
91
+ }
92
+
93
+ export function checkRequiredEnv() {
35
94
  const requiredEnv = [
36
95
  "AWS_SECRET_ACCESS_KEY",
37
96
  "AWS_REGION",
38
97
  "AWS_ACCESS_KEY_ID",
39
98
  "EVENT_BUS_NAME",
99
+ "ADMIN_DB_URI",
100
+ "MONGODB_URI",
101
+ "REDIS_HOST",
102
+ "REDIS_PORT",
103
+ "POSTHOG_API_KEY",
104
+ "POSTHOG_HOST",
40
105
  ];
41
106
  const missing = requiredEnv.filter((key) => !process.env[key]);
42
107
  if (missing.length > 0) {
@@ -55,6 +120,9 @@ export function ensureAuditInitialized() {
55
120
  const host = process.env.POSTHOG_HOST;
56
121
 
57
122
  if (!apiKey || !host) {
123
+ getConfig().LOGGER.error(
124
+ "POSTHOG_API_KEY and POSTHOG_HOST must be set in environment variables"
125
+ );
58
126
  throw new Error(
59
127
  "dt-common-device: POSTHOG_API_KEY and POSTHOG_HOST must be set in environment variables"
60
128
  );
@@ -71,6 +139,9 @@ export function ensureAuditInitialized() {
71
139
  export function getPostgresDbUri(): string {
72
140
  const fullUri = process.env.ADMIN_DB_URI;
73
141
  if (!fullUri) {
142
+ getConfig().LOGGER.error(
143
+ "ADMIN_DB_URI must be set in environment variables or .env file"
144
+ );
74
145
  throw new Error(
75
146
  "dt-common-device: ADMIN_DB_URI must be set in environment variables or .env file"
76
147
  );
@@ -78,6 +149,19 @@ export function getPostgresDbUri(): string {
78
149
  return fullUri;
79
150
  }
80
151
 
152
+ export function getMongoUri(): string {
153
+ const fullUri = process.env.MONGODB_URI;
154
+ if (!fullUri) {
155
+ getConfig().LOGGER.error(
156
+ "MONGODB_URI must be set in environment variables or .env file"
157
+ );
158
+ throw new Error(
159
+ "dt-common-device: MONGODB_URI must be set in environment variables or .env file"
160
+ );
161
+ }
162
+ return fullUri;
163
+ }
164
+
81
165
  /**
82
166
  * Returns the Redis DB Host and port from environment variables.
83
167
  * Throws an error if not set.
@@ -86,9 +170,28 @@ export function getRedisDbHostAndPort(): { host: string; port: number } {
86
170
  const host = process.env.REDIS_HOST;
87
171
  const port = process.env.REDIS_PORT;
88
172
  if (!host || !port) {
173
+ getConfig().LOGGER.error(
174
+ "REDIS_HOST and REDIS_PORT must be set in environment variables"
175
+ );
89
176
  throw new Error(
90
177
  "dt-common-device: REDIS_HOST and REDIS_PORT must be set in environment variables"
91
178
  );
92
179
  }
93
180
  return { host, port: Number(port) };
94
181
  }
182
+
183
+ /**
184
+ * Graceful shutdown function
185
+ */
186
+ export async function shutdown(): Promise<void> {
187
+ if (eventSubscription) {
188
+ try {
189
+ await eventSubscription.unsubscribe();
190
+ getConfig().LOGGER.info("Event subscription stopped successfully");
191
+ } catch (error) {
192
+ getConfig().LOGGER.error("Failed to stop event subscription", { error });
193
+ }
194
+ }
195
+
196
+ getConfig().LOGGER.info("dt-common-device: Shutdown completed");
197
+ }
@@ -1,9 +1,16 @@
1
1
  export const DT_EVENT_TYPES = {
2
2
  DEVICE: {
3
- DEVICE: {
4
- CREATED: "device.device.created",
5
- UPDATED: "device.device.updated",
6
- DELETED: "device.device.deleted",
3
+ CREATE: {
4
+ SUCCESS: "device.create.success",
5
+ FAILED: "device.create.failed",
6
+ },
7
+ UPDATE: {
8
+ SUCCESS: "device.update.success",
9
+ FAILED: "device.update.failed",
10
+ },
11
+ DELETE: {
12
+ SUCCESS: "device.delete.success",
13
+ FAILED: "device.delete.failed",
7
14
  },
8
15
  STATE: {
9
16
  SET: "device.state.set",
@@ -34,21 +41,35 @@ export const DT_EVENT_TYPES = {
34
41
  },
35
42
  },
36
43
  CONNECTION: {
37
- CONNECTION: {
38
- CREATED: "connection.connection.created",
39
- UPDATED: "connection.connection.updated",
40
- DELETED: "connection.connection.deleted",
44
+ CREATE: {
45
+ SUCCESS: "connection.create.success",
46
+ FAILED: "connection.create.failed",
47
+ },
48
+ UPDATE: {
49
+ SUCCESS: "connection.update.success",
50
+ FAILED: "connection.update.failed",
51
+ },
52
+ DELETE: {
53
+ SUCCESS: "connection.delete.success",
54
+ FAILED: "connection.delete.failed",
41
55
  },
42
56
  },
43
57
  PROPERTY: {
44
- PROPERTY: {
45
- CREATED: "property.property.created",
46
- UPDATED: "property.property.updated",
47
- DELETED: "property.property.deleted",
58
+ CREATE: {
59
+ SUCCESS: "property.create.success",
60
+ FAILED: "property.create.failed",
61
+ },
62
+ UPDATE: {
63
+ SUCCESS: "property.update.success",
64
+ FAILED: "property.update.failed",
65
+ },
66
+ DELETE: {
67
+ SUCCESS: "property.delete.success",
68
+ FAILED: "property.delete.failed",
48
69
  },
49
70
  PREFERENCES: {
50
71
  UPDATED: "property.preferences.updated",
51
72
  CREATED: "property.preferences.created",
52
73
  },
53
74
  },
54
- };
75
+ };