dt-common-device 3.0.10 → 3.0.12
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.
- package/dist/audit/AuditProperties.d.ts +16 -0
- package/dist/audit/AuditUtils.d.ts +2 -0
- package/dist/audit/AuditUtils.js +36 -0
- package/dist/config/config.d.ts +1 -2
- package/dist/config/config.js +4 -5
- package/dist/constants/Service.d.ts +1 -0
- package/dist/device/local/events/EventHandler.js +6 -6
- package/dist/device/local/events/Events.d.ts +33 -12
- package/dist/device/local/events/Events.js +33 -12
- package/dist/device/local/repository/Schedule.repository.d.ts +0 -1
- package/dist/device/local/repository/Schedule.repository.js +6 -6
- package/dist/queue/entities/HybridHttpQueue.d.ts +4 -14
- package/dist/queue/entities/HybridHttpQueue.js +31 -119
- package/dist/queue/interfaces/IHybridHttpQueue.d.ts +2 -12
- package/dist/queue/interfaces/IJobResult.d.ts +1 -8
- package/dist/queue/interfaces/index.d.ts +0 -1
- package/dist/queue/interfaces/index.js +0 -1
- package/dist/queue/services/QueueService.d.ts +2 -12
- package/dist/queue/types/http.types.d.ts +6 -4
- package/dist/queue/types/queue.types.d.ts +12 -29
- package/dist/queue/utils/jobUtils.d.ts +2 -4
- package/dist/queue/utils/jobUtils.js +0 -48
- package/dist/queue/utils/queueUtils.d.ts +7 -0
- package/dist/queue/utils/queueUtils.js +114 -4
- package/dist/queue/utils/rateLimit.utils.d.ts +1 -1
- package/dist/queue/utils/rateLimit.utils.js +38 -2
- package/package.json +6 -1
- package/.eslintrc.js +0 -44
- package/dist/device/cloud/interface.d.ts +0 -101
- package/dist/device/cloud/interface.js +0 -3
- package/dist/device/cloud/interfaces/IDeviceConnectionService.d.ts +0 -7
- package/dist/device/cloud/interfaces/IDeviceConnectionService.js +0 -3
- package/dist/device/cloud/interfaces/IDevicesService.d.ts +0 -9
- package/dist/device/cloud/services/Device.service.d.ts +0 -39
- package/dist/device/cloud/services/Device.service.js +0 -9
- package/dist/device/cloud/services/DeviceCloudService.d.ts +0 -42
- package/dist/device/cloud/services/DeviceCloudService.js +0 -59
- package/dist/device/cloud/services/DeviceHub.service.d.ts +0 -3
- package/dist/device/cloud/services/DeviceHub.service.js +0 -6
- package/dist/device/cloud/services/Hub.service.d.ts +0 -25
- package/dist/device/cloud/services/Hub.service.js +0 -9
- package/dist/device/cloud/services/SmartThingsDeviceService.d.ts +0 -38
- package/dist/device/cloud/services/SmartThingsDeviceService.js +0 -52
- package/dist/device/index.d.ts +0 -4
- package/dist/device/index.js +0 -20
- package/dist/device/local/interface.d.ts +0 -0
- package/dist/device/local/interface.js +0 -1
- package/dist/device/local/services/DeviceHub.service.d.ts +0 -11
- package/dist/device/local/services/DeviceHub.service.js +0 -40
- package/src/alerts/Alert.model.ts +0 -289
- package/src/alerts/Alert.repository.ts +0 -487
- package/src/alerts/Alert.service.ts +0 -711
- package/src/alerts/AlertBuilder.example.ts +0 -126
- package/src/alerts/AlertBuilder.ts +0 -208
- package/src/alerts/AlertService.example.ts +0 -232
- package/src/alerts/alert.types.ts +0 -64
- package/src/alerts/index.ts +0 -3
- package/src/config/config.ts +0 -202
- package/src/config/config.types.ts +0 -21
- package/src/connection/Connection.repository.ts +0 -52
- package/src/connection/Connection.service.ts +0 -39
- package/src/connection/IConnection.ts +0 -27
- package/src/connection/index.ts +0 -3
- package/src/constants/ConnectionProviders.ts +0 -11
- package/src/constants/Event.ts +0 -89
- package/src/constants/Service.ts +0 -17
- package/src/constants/index.ts +0 -3
- package/src/db/db.ts +0 -24
- package/src/db/index.ts +0 -2
- package/src/db/redis.ts +0 -20
- package/src/device/cloud/entities/CloudDevice.ts +0 -40
- package/src/device/cloud/entities/CloudDeviceService.ts +0 -8
- package/src/device/cloud/entities/DeviceFactory.ts +0 -27
- package/src/device/cloud/entities/index.ts +0 -3
- package/src/device/cloud/interfaces/ICloudDevice.ts +0 -14
- package/src/device/cloud/interfaces/ICloudDeviceService.ts +0 -6
- package/src/device/cloud/interfaces/IDeviceFactory.ts +0 -5
- package/src/device/cloud/interfaces/IRawDataTransformer.ts +0 -5
- package/src/device/cloud/interfaces/IRawDevice.ts +0 -19
- package/src/device/cloud/interfaces/index.ts +0 -5
- package/src/device/local/interfaces/IDevice.ts +0 -62
- package/src/device/local/interfaces/IDtDevice.ts +0 -16
- package/src/device/local/interfaces/ISchedule.ts +0 -40
- package/src/device/local/interfaces/index.ts +0 -3
- package/src/device/local/repository/Device.repository.ts +0 -368
- package/src/device/local/repository/Hub.repository.ts +0 -107
- package/src/device/local/repository/Schedule.repository.ts +0 -72
- package/src/device/local/services/Device.service.ts +0 -436
- package/src/device/local/services/Hub.service.ts +0 -57
- package/src/device/local/services/Schedule.service.ts +0 -26
- package/src/device/local/services/index.ts +0 -3
- package/src/docs/Alert.model.md +0 -319
- package/src/docs/Alerts&IssuesModel.md +0 -312
- package/src/docs/Issue.model.md +0 -386
- package/src/docs/SECURITY.md +0 -67
- package/src/docs/TROUBLESHOOTING.md +0 -184
- package/src/events/BaseEventHandler.ts +0 -145
- package/src/events/BaseEventTransformer.ts +0 -97
- package/src/events/DeviceEventHandler.ts +0 -213
- package/src/events/DeviceEventTransformerFactory.ts +0 -77
- package/src/events/EventHandler.ts +0 -124
- package/src/events/EventHandlerOrchestrator.ts +0 -119
- package/src/events/EventProcessingService.ts +0 -248
- package/src/events/InternalEventSubscription.ts +0 -194
- package/src/events/index.ts +0 -9
- package/src/events/interfaces/DeviceEvent.ts +0 -56
- package/src/events/interfaces/IEventHandler.ts +0 -28
- package/src/events/interfaces/IEventTransformer.ts +0 -8
- package/src/events/interfaces/IInternalEvent.ts +0 -33
- package/src/events/interfaces/index.ts +0 -4
- package/src/index.ts +0 -43
- package/src/issues/Issue.model.ts +0 -350
- package/src/issues/Issue.repository.ts +0 -517
- package/src/issues/Issue.service.ts +0 -932
- package/src/issues/IssueBuilder.example.ts +0 -210
- package/src/issues/IssueBuilder.ts +0 -263
- package/src/issues/IssueService.example.ts +0 -310
- package/src/issues/index.ts +0 -2
- package/src/issues/issue.types.ts +0 -98
- package/src/property/IProperty.ts +0 -30
- package/src/property/Property.repository.ts +0 -53
- package/src/property/Property.service.ts +0 -38
- package/src/property/index.ts +0 -2
- package/src/queue/entities/HybridHttpQueue.ts +0 -274
- package/src/queue/entities/index.ts +0 -1
- package/src/queue/index.ts +0 -6
- package/src/queue/interfaces/IHttpRequestJob.ts +0 -10
- package/src/queue/interfaces/IHybridHttpQueue.ts +0 -25
- package/src/queue/interfaces/IJobResult.ts +0 -15
- package/src/queue/interfaces/IRateLimitConfig.ts +0 -5
- package/src/queue/interfaces/index.ts +0 -4
- package/src/queue/services/QueueService.ts +0 -40
- package/src/queue/services/index.ts +0 -1
- package/src/queue/types/http.types.ts +0 -23
- package/src/queue/types/index.ts +0 -2
- package/src/queue/types/queue.types.ts +0 -21
- package/src/queue/utils/index.ts +0 -3
- package/src/queue/utils/jobUtils.ts +0 -79
- package/src/queue/utils/queueUtils.ts +0 -84
- package/src/queue/utils/rateLimit.utils.ts +0 -131
- package/src/utils/http.utils.ts +0 -143
- package/src/utils/index.ts +0 -2
- package/src/utils/redis.utils.ts +0 -74
- package/tsconfig.json +0 -20
- /package/dist/{device/cloud/interfaces/IDevicesService.js → audit/AuditProperties.js} +0 -0
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import { IncomingHttpHeaders } from "http";
|
|
2
|
+
import { SERVICE_NAME } from "../../constants";
|
|
1
3
|
export interface HttpCallOption {
|
|
2
|
-
headers?:
|
|
4
|
+
headers?: IncomingHttpHeaders;
|
|
3
5
|
body?: any;
|
|
4
6
|
params?: Record<string, any>;
|
|
5
7
|
queueOptions?: {
|
|
6
8
|
connectionId: string;
|
|
7
9
|
connectionProvider: string;
|
|
8
|
-
microservice:
|
|
10
|
+
microservice: SERVICE_NAME;
|
|
9
11
|
};
|
|
10
12
|
}
|
|
11
13
|
export interface HttpRequestOptions {
|
|
@@ -13,10 +15,10 @@ export interface HttpRequestOptions {
|
|
|
13
15
|
url: string;
|
|
14
16
|
body?: any;
|
|
15
17
|
params?: Record<string, any>;
|
|
16
|
-
headers?:
|
|
18
|
+
headers?: IncomingHttpHeaders;
|
|
17
19
|
queueOptions?: {
|
|
18
20
|
connectionId: string;
|
|
19
21
|
connectionProvider: string;
|
|
20
|
-
microservice:
|
|
22
|
+
microservice: SERVICE_NAME;
|
|
21
23
|
};
|
|
22
24
|
}
|
|
@@ -1,31 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { IncomingHttpHeaders } from "http";
|
|
2
|
+
import { SERVICE_NAME } from "../../constants";
|
|
3
|
+
export interface RequestQueueOptions {
|
|
4
|
+
method: string;
|
|
5
|
+
url: string;
|
|
6
|
+
body?: any;
|
|
7
|
+
params?: Record<string, any>;
|
|
8
|
+
headers?: IncomingHttpHeaders;
|
|
9
|
+
queueOptions?: {
|
|
10
|
+
connectionId: string;
|
|
11
|
+
connectionProvider: string;
|
|
12
|
+
microservice: SERVICE_NAME;
|
|
6
13
|
};
|
|
7
|
-
removeOnFail: {
|
|
8
|
-
age: number;
|
|
9
|
-
count: number;
|
|
10
|
-
};
|
|
11
|
-
lockDuration: number;
|
|
12
|
-
stalledInterval: number;
|
|
13
|
-
}
|
|
14
|
-
export interface JobOptions {
|
|
15
|
-
attempts: number;
|
|
16
|
-
removeOnComplete: {
|
|
17
|
-
age: number;
|
|
18
|
-
count: number;
|
|
19
|
-
};
|
|
20
|
-
removeOnFail: {
|
|
21
|
-
age: number;
|
|
22
|
-
count: number;
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
export interface QueueMetrics {
|
|
26
|
-
totalJobs: number;
|
|
27
|
-
completedJobs: number;
|
|
28
|
-
failedJobs: number;
|
|
29
|
-
pendingJobs: number;
|
|
30
|
-
activeJobs: number;
|
|
31
14
|
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { IJobResult } from "../interfaces";
|
|
1
|
+
import { SERVICE_NAME } from "../../constants";
|
|
3
2
|
export declare class JobUtils {
|
|
4
|
-
static waitForJobCompletion(job: Job, queueKey: string, jobResults: Map<string, IJobResult>): Promise<any>;
|
|
5
3
|
static extractConnectionDetails(options: any): {
|
|
6
4
|
connectionId: string;
|
|
7
5
|
provider: string;
|
|
8
|
-
microservice:
|
|
6
|
+
microservice: SERVICE_NAME;
|
|
9
7
|
};
|
|
10
8
|
}
|
|
@@ -2,54 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.JobUtils = void 0;
|
|
4
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
5
|
static extractConnectionDetails(options) {
|
|
54
6
|
const { connectionId, connectionProvider: provider, microservice, } = options?.queueOptions ?? {};
|
|
55
7
|
if (!connectionId)
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
import { HttpCallOption } from "../types/http.types";
|
|
2
|
+
import { IRateLimitConfig } from "../interfaces";
|
|
1
3
|
export declare class QueueUtils {
|
|
2
4
|
static getQueueKey(microservice: string, connectionId: string, provider: string): string;
|
|
5
|
+
static getRequestQueueKey(connectionId: string, provider: string): string;
|
|
3
6
|
static getOrCreateQueue(queueKey: string, queues: Map<string, any>): any;
|
|
4
7
|
static getOrCreateWorker(queueKey: string, workers: Map<string, any>, processFunction: (job: any) => Promise<any>, jobResults: Map<string, any>): void;
|
|
8
|
+
static waitForRateLimitExpiry(connectionId: string, provider: string, rateLimitConfigs: Map<string, IRateLimitConfig>): Promise<void>;
|
|
9
|
+
static executeHttpRequest(url: string, method: string, options: HttpCallOption, connectionId: string, provider: string): Promise<any>;
|
|
10
|
+
static addJobToQueue(queueKey: string, jobData: any, delay: number, queues: Map<string, any>): Promise<string>;
|
|
11
|
+
static waitForJobCompletion(jobId: string, queueKey: string, jobResults: Map<string, any>): Promise<any>;
|
|
5
12
|
}
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.QueueUtils = void 0;
|
|
7
|
+
const rateLimit_utils_1 = require("./rateLimit.utils");
|
|
8
|
+
const axios_1 = __importDefault(require("axios"));
|
|
9
|
+
const dt_audit_library_1 = require("dt-audit-library");
|
|
4
10
|
const config_1 = require("../../config/config");
|
|
5
11
|
const redis_1 = require("../../db/redis");
|
|
6
12
|
class QueueUtils {
|
|
7
13
|
static getQueueKey(microservice, connectionId, provider) {
|
|
8
14
|
return `${microservice}_${provider}_${connectionId}`;
|
|
9
15
|
}
|
|
16
|
+
static getRequestQueueKey(connectionId, provider) {
|
|
17
|
+
return `${connectionId}_${provider}`;
|
|
18
|
+
}
|
|
10
19
|
static getOrCreateQueue(queueKey, queues) {
|
|
11
20
|
return (queues.get(queueKey) ??
|
|
12
21
|
queues
|
|
@@ -27,10 +36,9 @@ class QueueUtils {
|
|
|
27
36
|
lockDuration: 300000,
|
|
28
37
|
stalledInterval: 60000,
|
|
29
38
|
});
|
|
30
|
-
//
|
|
39
|
+
// Event handlers for job tracking
|
|
31
40
|
worker.on("completed", (job) => {
|
|
32
41
|
(0, config_1.getConfig)().LOGGER.info(`HTTP request completed: ${job.id} [${queueKey}]`);
|
|
33
|
-
// job.returnvalue is the actual result, not a Promise
|
|
34
42
|
const result = job.returnvalue;
|
|
35
43
|
jobResults.set(job.id, {
|
|
36
44
|
result,
|
|
@@ -47,10 +55,112 @@ class QueueUtils {
|
|
|
47
55
|
});
|
|
48
56
|
});
|
|
49
57
|
worker.on("error", (err) => (0, config_1.getConfig)().LOGGER.error(`Worker error for ${queueKey}: ${err.message}`));
|
|
50
|
-
worker.on("stalled", (jobId) => (0, config_1.getConfig)().LOGGER.warn(`Job ${jobId} stalled in worker ${queueKey}`));
|
|
51
|
-
worker.on("active", (job) => (0, config_1.getConfig)().LOGGER.info(`HTTP request started: ${job.id} [${queueKey}]`));
|
|
52
58
|
workers.set(queueKey, worker);
|
|
53
59
|
(0, config_1.getConfig)().LOGGER.info(`Worker initialized for queue: ${queueKey}`);
|
|
54
60
|
}
|
|
61
|
+
static async waitForRateLimitExpiry(connectionId, provider, rateLimitConfigs) {
|
|
62
|
+
const key = `rate_limit:${provider}:${connectionId}`;
|
|
63
|
+
const config = rateLimitConfigs.get(provider);
|
|
64
|
+
if (!config)
|
|
65
|
+
return;
|
|
66
|
+
while (true) {
|
|
67
|
+
const timestamps = await rateLimit_utils_1.RateLimitUtils.getRawRequestTimestamps(key);
|
|
68
|
+
const now = Date.now();
|
|
69
|
+
const windowStart = now - config.windowMs;
|
|
70
|
+
const recentRequests = timestamps.filter((t) => t > windowStart);
|
|
71
|
+
if (recentRequests.length < config.maxRequests) {
|
|
72
|
+
// Rate limit not exceeded, we can proceed
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
// Calculate when the earliest request will expire
|
|
76
|
+
const earliestRequest = recentRequests[0];
|
|
77
|
+
const nextAvailableTime = earliestRequest + config.windowMs;
|
|
78
|
+
const delay = Math.max(nextAvailableTime - now, 1000); // At least 1 second
|
|
79
|
+
(0, config_1.getConfig)().LOGGER.info(`Rate limit exceeded for ${provider} [${connectionId}]. Waiting ${delay}ms until next allowed request. Current requests in window: ${recentRequests.length}/${config.maxRequests}`);
|
|
80
|
+
// Wait for the calculated delay
|
|
81
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
static async executeHttpRequest(url, method, options, connectionId, provider) {
|
|
85
|
+
(0, config_1.getConfig)().LOGGER.info(`Executing: ${method} ${url} -> ${provider} [${connectionId}]`);
|
|
86
|
+
try {
|
|
87
|
+
// Record the request first
|
|
88
|
+
await rateLimit_utils_1.RateLimitUtils.recordRequest(connectionId, provider);
|
|
89
|
+
// Execute the HTTP request
|
|
90
|
+
const response = await (0, axios_1.default)({
|
|
91
|
+
method: method.toLowerCase(),
|
|
92
|
+
url: url,
|
|
93
|
+
headers: options.headers || {},
|
|
94
|
+
timeout: 30000,
|
|
95
|
+
...(options.body && { data: options.body }),
|
|
96
|
+
...(options.params && { params: options.params }),
|
|
97
|
+
});
|
|
98
|
+
(0, config_1.getConfig)().LOGGER.info(`HTTP request successful: ${method} ${url} for ${provider} [${connectionId}]`);
|
|
99
|
+
// Return only the response data
|
|
100
|
+
return response.data;
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
(0, config_1.getConfig)().LOGGER.error(`HTTP request failed: ${error.message}`);
|
|
104
|
+
await (0, dt_audit_library_1.publishAudit)({
|
|
105
|
+
eventType: "http.request.error",
|
|
106
|
+
properties: {
|
|
107
|
+
connectionId,
|
|
108
|
+
provider,
|
|
109
|
+
endpoint: url,
|
|
110
|
+
method,
|
|
111
|
+
timestamp: Date.now(),
|
|
112
|
+
reason: "execution_error",
|
|
113
|
+
errorMessage: error.message,
|
|
114
|
+
error: error,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
// Throw the error instead of returning it
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
static async addJobToQueue(queueKey, jobData, delay, queues) {
|
|
122
|
+
const queue = this.getOrCreateQueue(queueKey, queues);
|
|
123
|
+
const job = await queue.add("http-request", jobData, {
|
|
124
|
+
delay,
|
|
125
|
+
attempts: 1,
|
|
126
|
+
removeOnComplete: { age: 300, count: 1 },
|
|
127
|
+
removeOnFail: { age: 300, count: 1 },
|
|
128
|
+
});
|
|
129
|
+
return job.id;
|
|
130
|
+
}
|
|
131
|
+
static async waitForJobCompletion(jobId, queueKey, jobResults) {
|
|
132
|
+
return new Promise((resolve, reject) => {
|
|
133
|
+
let timeoutId;
|
|
134
|
+
let checkCount = 0;
|
|
135
|
+
const maxChecks = 600;
|
|
136
|
+
const checkJob = async () => {
|
|
137
|
+
if (++checkCount >= maxChecks) {
|
|
138
|
+
clearTimeout(timeoutId);
|
|
139
|
+
return reject(new Error("Job timeout: Request took too long"));
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
const memoryResult = jobResults.get(jobId);
|
|
143
|
+
if (memoryResult?.resolved) {
|
|
144
|
+
clearTimeout(timeoutId);
|
|
145
|
+
return memoryResult.result !== undefined
|
|
146
|
+
? resolve(memoryResult.result)
|
|
147
|
+
: reject(new Error(memoryResult.error || "Unknown error"));
|
|
148
|
+
}
|
|
149
|
+
// Continue checking
|
|
150
|
+
timeoutId = setTimeout(checkJob, checkCount < 10 ? 50 : 100);
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
clearTimeout(timeoutId);
|
|
154
|
+
reject(new Error(`Error checking job: ${error.message}`));
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
checkJob();
|
|
158
|
+
// Backup timeout
|
|
159
|
+
setTimeout(() => {
|
|
160
|
+
clearTimeout(timeoutId);
|
|
161
|
+
reject(new Error("Request timeout: Maximum wait time exceeded"));
|
|
162
|
+
}, 60000);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
55
165
|
}
|
|
56
166
|
exports.QueueUtils = QueueUtils;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IRateLimitConfig } from "../interfaces";
|
|
2
2
|
export declare class RateLimitUtils {
|
|
3
|
-
private static redisClient;
|
|
3
|
+
private static readonly redisClient;
|
|
4
4
|
static checkRateLimit(connectionId: string, provider: string, rateLimitConfigs: Map<string, IRateLimitConfig>): Promise<boolean>;
|
|
5
5
|
static initializeRateLimitConfigs(): Map<string, IRateLimitConfig>;
|
|
6
6
|
static isRateLimitAllowed(connectionId: string, provider: string, rateLimitConfigs: Map<string, IRateLimitConfig>): Promise<boolean>;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.RateLimitUtils = void 0;
|
|
4
4
|
const redis_1 = require("../../db/redis");
|
|
5
5
|
const config_1 = require("../../config/config");
|
|
6
|
+
const constants_1 = require("../../constants");
|
|
6
7
|
class RateLimitUtils {
|
|
7
8
|
static async checkRateLimit(connectionId, provider, rateLimitConfigs) {
|
|
8
9
|
const config = rateLimitConfigs.get(provider);
|
|
@@ -32,10 +33,45 @@ class RateLimitUtils {
|
|
|
32
33
|
static initializeRateLimitConfigs() {
|
|
33
34
|
const configs = new Map();
|
|
34
35
|
// Configure rate limits for different providers
|
|
35
|
-
configs.set(
|
|
36
|
+
configs.set(constants_1.CONNECTION_PROVIDERS.SENSIBO, {
|
|
36
37
|
maxRequests: 5,
|
|
37
38
|
windowMs: 60000,
|
|
38
|
-
provider:
|
|
39
|
+
provider: constants_1.CONNECTION_PROVIDERS.SENSIBO,
|
|
40
|
+
});
|
|
41
|
+
configs.set(constants_1.CONNECTION_PROVIDERS.TTLOCK, {
|
|
42
|
+
maxRequests: 5,
|
|
43
|
+
windowMs: 60000,
|
|
44
|
+
provider: constants_1.CONNECTION_PROVIDERS.TTLOCK,
|
|
45
|
+
});
|
|
46
|
+
configs.set(constants_1.CONNECTION_PROVIDERS.SCHLAGE, {
|
|
47
|
+
maxRequests: 5,
|
|
48
|
+
windowMs: 60000,
|
|
49
|
+
provider: constants_1.CONNECTION_PROVIDERS.SCHLAGE,
|
|
50
|
+
});
|
|
51
|
+
configs.set(constants_1.CONNECTION_PROVIDERS.SMARTTHINGS, {
|
|
52
|
+
maxRequests: 5,
|
|
53
|
+
windowMs: 60000,
|
|
54
|
+
provider: constants_1.CONNECTION_PROVIDERS.SMARTTHINGS,
|
|
55
|
+
});
|
|
56
|
+
configs.set(constants_1.CONNECTION_PROVIDERS.YALEWIFI, {
|
|
57
|
+
maxRequests: 5,
|
|
58
|
+
windowMs: 60000,
|
|
59
|
+
provider: constants_1.CONNECTION_PROVIDERS.YALEWIFI,
|
|
60
|
+
});
|
|
61
|
+
configs.set(constants_1.CONNECTION_PROVIDERS.TUYA, {
|
|
62
|
+
maxRequests: 5,
|
|
63
|
+
windowMs: 1000,
|
|
64
|
+
provider: constants_1.CONNECTION_PROVIDERS.TUYA,
|
|
65
|
+
});
|
|
66
|
+
configs.set(constants_1.CONNECTION_PROVIDERS.SALTOKS, {
|
|
67
|
+
maxRequests: 5,
|
|
68
|
+
windowMs: 60000,
|
|
69
|
+
provider: constants_1.CONNECTION_PROVIDERS.SALTOKS,
|
|
70
|
+
});
|
|
71
|
+
configs.set(constants_1.CONNECTION_PROVIDERS.VERDANT, {
|
|
72
|
+
maxRequests: 5,
|
|
73
|
+
windowMs: 60000,
|
|
74
|
+
provider: constants_1.CONNECTION_PROVIDERS.VERDANT,
|
|
39
75
|
});
|
|
40
76
|
return configs;
|
|
41
77
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dt-common-device",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.12",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"README.md",
|
|
9
|
+
"LICENSE"
|
|
10
|
+
],
|
|
6
11
|
"scripts": {
|
|
7
12
|
"build": "tsc",
|
|
8
13
|
"patch": "npm version patch && npm run build && npm publish",
|
package/.eslintrc.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
parser: "@typescript-eslint/parser",
|
|
3
|
-
extends: ["eslint:recommended", "@typescript-eslint/recommended"],
|
|
4
|
-
plugins: ["@typescript-eslint"],
|
|
5
|
-
env: {
|
|
6
|
-
node: true,
|
|
7
|
-
es2020: true,
|
|
8
|
-
},
|
|
9
|
-
parserOptions: {
|
|
10
|
-
ecmaVersion: 2020,
|
|
11
|
-
sourceType: "module",
|
|
12
|
-
},
|
|
13
|
-
rules: {
|
|
14
|
-
// Security rules
|
|
15
|
-
"no-eval": "error",
|
|
16
|
-
"no-implied-eval": "error",
|
|
17
|
-
"no-new-func": "error",
|
|
18
|
-
"no-script-url": "error",
|
|
19
|
-
"no-unsafe-finally": "error",
|
|
20
|
-
|
|
21
|
-
// TypeScript security
|
|
22
|
-
"@typescript-eslint/no-explicit-any": "warn",
|
|
23
|
-
"@typescript-eslint/no-unsafe-assignment": "warn",
|
|
24
|
-
"@typescript-eslint/no-unsafe-call": "warn",
|
|
25
|
-
"@typescript-eslint/no-unsafe-member-access": "warn",
|
|
26
|
-
"@typescript-eslint/no-unsafe-return": "warn",
|
|
27
|
-
|
|
28
|
-
// Code quality
|
|
29
|
-
"@typescript-eslint/explicit-function-return-type": "warn",
|
|
30
|
-
"@typescript-eslint/no-unused-vars": "error",
|
|
31
|
-
"@typescript-eslint/prefer-const": "error",
|
|
32
|
-
"@typescript-eslint/no-var-requires": "error",
|
|
33
|
-
|
|
34
|
-
// Error handling
|
|
35
|
-
"no-console": "warn",
|
|
36
|
-
"no-throw-literal": "error",
|
|
37
|
-
|
|
38
|
-
// Best practices
|
|
39
|
-
"prefer-const": "error",
|
|
40
|
-
"no-var": "error",
|
|
41
|
-
"object-shorthand": "error",
|
|
42
|
-
},
|
|
43
|
-
ignorePatterns: ["dist/", "node_modules/", "*.js"],
|
|
44
|
-
};
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { IConnection, IConnectionConnectParams, IDevice, IDeviceAccountResponse, IDeviceCommand, ISmartthingsDeviceCommand, ICommandResponse } from "./types";
|
|
2
|
-
/**
|
|
3
|
-
* Class interface for device cloud operations and connection management
|
|
4
|
-
*/
|
|
5
|
-
export interface IDeviceCloudService {
|
|
6
|
-
/**
|
|
7
|
-
* Creates a new connection for device management
|
|
8
|
-
* @param data - Connection data
|
|
9
|
-
* @param userId - User identifier
|
|
10
|
-
* @returns Promise with connection result
|
|
11
|
-
*/
|
|
12
|
-
createConnection(data: IConnection, userId: string): Promise<any>;
|
|
13
|
-
/**
|
|
14
|
-
* Gets device account information for a connection
|
|
15
|
-
* @param connection - Connection object
|
|
16
|
-
* @returns Promise with device account response
|
|
17
|
-
*/
|
|
18
|
-
getDeviceAccount(connection: IConnection): Promise<IDeviceAccountResponse>;
|
|
19
|
-
/**
|
|
20
|
-
* Gets all devices for a connection
|
|
21
|
-
* @param connection - Connection object
|
|
22
|
-
* @returns Promise with array of devices
|
|
23
|
-
*/
|
|
24
|
-
getDevices(connection: IConnection): Promise<IDevice[]>;
|
|
25
|
-
/**
|
|
26
|
-
* Filters devices based on connection and device list
|
|
27
|
-
* @param connection - Connection object
|
|
28
|
-
* @param devices - Array of devices to filter
|
|
29
|
-
* @returns Promise with filtered devices
|
|
30
|
-
*/
|
|
31
|
-
filterDevices(connection: IConnection, devices: any[]): Promise<IDevice[]>;
|
|
32
|
-
/**
|
|
33
|
-
* Connects to a device service
|
|
34
|
-
* @param connection - Connection object
|
|
35
|
-
* @param connectionConnect - Connection parameters
|
|
36
|
-
* @returns Promise with connection result
|
|
37
|
-
*/
|
|
38
|
-
connect(connection: IConnection, connectionConnect: IConnectionConnectParams): Promise<any>;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Interface for device command operations
|
|
42
|
-
*/
|
|
43
|
-
export interface IDeviceCommandManager {
|
|
44
|
-
/**
|
|
45
|
-
* Invokes a command on a device
|
|
46
|
-
* @param command - Device command to execute
|
|
47
|
-
* @param deviceId - Device identifier
|
|
48
|
-
* @returns Promise with command response
|
|
49
|
-
*/
|
|
50
|
-
invokeCommand(command: IDeviceCommand, deviceId: string): Promise<ICommandResponse>;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Interface for SmartThings specific device command operations
|
|
54
|
-
*/
|
|
55
|
-
export interface ISmartthingsDeviceCommandManager extends IDeviceCommandManager {
|
|
56
|
-
/**
|
|
57
|
-
* Performs device action for SmartThings
|
|
58
|
-
* @param commands - Array of SmartThings device commands
|
|
59
|
-
* @param deviceId - Device identifier
|
|
60
|
-
* @param accessToken - Access token for authentication
|
|
61
|
-
* @returns Promise with action result
|
|
62
|
-
*/
|
|
63
|
-
performDeviceAction(commands: ISmartthingsDeviceCommand[], deviceId: string, accessToken: string): Promise<any>;
|
|
64
|
-
/**
|
|
65
|
-
* Gets device status for SmartThings
|
|
66
|
-
* @param deviceId - Device identifier
|
|
67
|
-
* @param accessToken - Access token for authentication
|
|
68
|
-
* @returns Promise with device status
|
|
69
|
-
*/
|
|
70
|
-
getDeviceStatus(deviceId: string, accessToken: string): Promise<any>;
|
|
71
|
-
/**
|
|
72
|
-
* Gets device lock status for SmartThings
|
|
73
|
-
* @param deviceId - Device identifier
|
|
74
|
-
* @param accessToken - Access token for authentication
|
|
75
|
-
* @returns Promise with lock status
|
|
76
|
-
*/
|
|
77
|
-
getDeviceLockStatus(deviceId: string, accessToken: string): Promise<any>;
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Interface for device command factory
|
|
81
|
-
*/
|
|
82
|
-
export interface IDeviceCommandManagerFactory {
|
|
83
|
-
/**
|
|
84
|
-
* Creates a device command manager for a specific connection provider
|
|
85
|
-
* @param connectionProvider - Connection provider type
|
|
86
|
-
* @param connection - Connection object
|
|
87
|
-
* @returns Device command manager instance
|
|
88
|
-
*/
|
|
89
|
-
createDeviceCommandManager(connectionProvider: string, connection: IConnection): IDeviceCommandManager;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Interface for device command classes
|
|
93
|
-
*/
|
|
94
|
-
export interface IDeviceCommandClass {
|
|
95
|
-
/**
|
|
96
|
-
* Creates a SmartThings device command from a generic device command
|
|
97
|
-
* @param deviceCommand - Generic device command
|
|
98
|
-
* @returns SmartThings device command
|
|
99
|
-
*/
|
|
100
|
-
fromDeviceCommand(deviceCommand: IDeviceCommand): ISmartthingsDeviceCommand;
|
|
101
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { IConnection, IConnectionConnectParams, IDeviceAccountResponse } from "../types";
|
|
2
|
-
export interface IDeviceConnectionService {
|
|
3
|
-
createConnection(data: IConnection, userId: string): Promise<any>;
|
|
4
|
-
getDeviceAccount(connection: IConnection): Promise<IDeviceAccountResponse>;
|
|
5
|
-
getDevices(connection: IConnection): Promise<any>;
|
|
6
|
-
connect(connection: IConnection, connectionConnect: IConnectionConnectParams): Promise<any>;
|
|
7
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { IConnection } from "../types";
|
|
2
|
-
export interface IDeviceService {
|
|
3
|
-
getDevices(connection: IConnection): Promise<Record<string, any>[]>;
|
|
4
|
-
getDevice(connectionId: string, deviceId: string): Promise<Record<string, any>>;
|
|
5
|
-
getStatus(connectionId: string, deviceId: string): Promise<string | null>;
|
|
6
|
-
getState(deviceId: string): Promise<Record<string, any>>;
|
|
7
|
-
getGateways(connectionId: string): Promise<any[] | null>;
|
|
8
|
-
getGatewayDetails(connectionId: string, gatewayId: string): Promise<any>;
|
|
9
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { IDeviceService } from "../interfaces";
|
|
2
|
-
import { IConnection, IDevice } from "../types";
|
|
3
|
-
export declare abstract class DeviceService implements IDeviceService {
|
|
4
|
-
deviceId: string;
|
|
5
|
-
propertyId: string;
|
|
6
|
-
name: string;
|
|
7
|
-
hubId: string[];
|
|
8
|
-
deviceType: {
|
|
9
|
-
id: string;
|
|
10
|
-
type: string;
|
|
11
|
-
};
|
|
12
|
-
status: {
|
|
13
|
-
online: boolean;
|
|
14
|
-
error?: {
|
|
15
|
-
type?: string;
|
|
16
|
-
message?: string;
|
|
17
|
-
};
|
|
18
|
-
lastUpdated?: string;
|
|
19
|
-
};
|
|
20
|
-
state?: Record<string, any>;
|
|
21
|
-
metaData?: Record<string, any>;
|
|
22
|
-
zone?: {
|
|
23
|
-
id: string;
|
|
24
|
-
name: string;
|
|
25
|
-
zoneType: string;
|
|
26
|
-
parentZone?: {
|
|
27
|
-
id: string;
|
|
28
|
-
name: string;
|
|
29
|
-
zoneType: string;
|
|
30
|
-
};
|
|
31
|
-
};
|
|
32
|
-
connection: IConnection;
|
|
33
|
-
constructor(device: IDevice);
|
|
34
|
-
abstract getDevices(connection: IConnection): Promise<Record<string, any>[]>;
|
|
35
|
-
abstract getDevice(connectionId: string, deviceId: string): Promise<any>;
|
|
36
|
-
abstract getBattery(deviceId: string): Promise<number | string>;
|
|
37
|
-
abstract getStatus(connectionId: string, deviceId: string): Promise<string>;
|
|
38
|
-
abstract getState(deviceId: string): Promise<string>;
|
|
39
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { IDeviceCloudService } from "../interface";
|
|
2
|
-
import { IConnection, IDevice, IDeviceAccountResponse, IConnectionConnectParams } from "../types";
|
|
3
|
-
/**
|
|
4
|
-
* Device Cloud Service Class
|
|
5
|
-
* Implements IDeviceCloudService interface with empty implementations
|
|
6
|
-
* Implementation will be provided by the consuming project
|
|
7
|
-
*/
|
|
8
|
-
export declare class DeviceCloudService implements IDeviceCloudService {
|
|
9
|
-
/**
|
|
10
|
-
* Creates a new connection for device management
|
|
11
|
-
* @param data - Connection data
|
|
12
|
-
* @param userId - User identifier
|
|
13
|
-
* @returns Promise with connection result
|
|
14
|
-
*/
|
|
15
|
-
createConnection(data: IConnection, userId: string): Promise<any>;
|
|
16
|
-
/**
|
|
17
|
-
* Gets device account information for a connection
|
|
18
|
-
* @param connection - Connection object
|
|
19
|
-
* @returns Promise with device account response
|
|
20
|
-
*/
|
|
21
|
-
getDeviceAccount(connection: IConnection): Promise<IDeviceAccountResponse>;
|
|
22
|
-
/**
|
|
23
|
-
* Gets all devices for a connection
|
|
24
|
-
* @param connection - Connection object
|
|
25
|
-
* @returns Promise with array of devices
|
|
26
|
-
*/
|
|
27
|
-
getDevices(connection: IConnection): Promise<IDevice[]>;
|
|
28
|
-
/**
|
|
29
|
-
* Filters devices based on connection and device list
|
|
30
|
-
* @param connection - Connection object
|
|
31
|
-
* @param devices - Array of devices to filter
|
|
32
|
-
* @returns Promise with filtered devices
|
|
33
|
-
*/
|
|
34
|
-
filterDevices(connection: IConnection, devices: any[]): Promise<IDevice[]>;
|
|
35
|
-
/**
|
|
36
|
-
* Connects to a device service
|
|
37
|
-
* @param connection - Connection object
|
|
38
|
-
* @param connectionConnect - Connection parameters
|
|
39
|
-
* @returns Promise with connection result
|
|
40
|
-
*/
|
|
41
|
-
connect(connection: IConnection, connectionConnect: IConnectionConnectParams): Promise<any>;
|
|
42
|
-
}
|