dt-common-device 12.0.1 → 12.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/config.js +5 -0
- package/dist/config/config.types.d.ts +1 -1
- package/dist/config/constants.d.ts +7 -0
- package/dist/config/constants.js +7 -2
- package/dist/constants/ConnectionProviders.d.ts +2 -0
- package/dist/constants/ConnectionProviders.js +2 -0
- package/dist/entities/admin/Admin.repository.d.ts +2 -1
- package/dist/entities/admin/Admin.repository.js +15 -19
- package/dist/entities/admin/Admin.service.d.ts +1 -1
- package/dist/entities/admin/Admin.service.js +2 -2
- package/dist/entities/connection/Connection.repository.d.ts +0 -1
- package/dist/entities/connection/Connection.repository.js +0 -22
- package/dist/entities/connection/Connection.service.d.ts +0 -1
- package/dist/entities/connection/Connection.service.js +0 -3
- package/dist/entities/pms/IPms.d.ts +2 -1
- package/dist/entities/pms/IPms.js +1 -0
- package/dist/issues/Issue.service.js +1 -1
- package/dist/issues/issue.types.d.ts +1 -0
- package/dist/issues/issue.types.js +1 -0
- package/dist/queue/utils/rateLimit.utils.js +12 -0
- package/package.json +1 -1
package/dist/config/config.js
CHANGED
|
@@ -69,6 +69,11 @@ async function initialize(cfg) {
|
|
|
69
69
|
db_keys = constants_1.CONFIG_KEYS.MIGRATION.db_keys;
|
|
70
70
|
await validateServiceConfig(cfg);
|
|
71
71
|
}
|
|
72
|
+
if (cfg.SOURCE === "OPERATION_NODE_SERVICE") {
|
|
73
|
+
sourceKey = "OPERATION_NODE";
|
|
74
|
+
db_keys = constants_1.CONFIG_KEYS.OPERATION_NODE.db_keys;
|
|
75
|
+
await validateServiceConfig(cfg);
|
|
76
|
+
}
|
|
72
77
|
// Connect to databases
|
|
73
78
|
try {
|
|
74
79
|
await (0, db_1.connectDatabase)();
|
|
@@ -4,7 +4,7 @@ export interface ILogger {
|
|
|
4
4
|
warn(message: string, ...args: any[]): void;
|
|
5
5
|
error(message: string, ...args: any[]): void;
|
|
6
6
|
}
|
|
7
|
-
type AllowedSource = "ACCESS_SERVICE" | "ADMIN_SERVICE" | "ENERGY_SERVICE" | "REMOTE_SERVICE" | "SCHEDULE_SERVICE" | "MIGRATION";
|
|
7
|
+
type AllowedSource = "ACCESS_SERVICE" | "ADMIN_SERVICE" | "ENERGY_SERVICE" | "REMOTE_SERVICE" | "SCHEDULE_SERVICE" | "MIGRATION" | "OPERATION_NODE_SERVICE";
|
|
8
8
|
export type IConfig = {
|
|
9
9
|
SOURCE: AllowedSource;
|
|
10
10
|
INTERNAL_EVENT_HANDLER?: IInternalEvent;
|
package/dist/config/constants.js
CHANGED
|
@@ -9,8 +9,6 @@ exports.REQUIRED = {
|
|
|
9
9
|
"EVENT_BUS_NAME",
|
|
10
10
|
"REDIS_HOST",
|
|
11
11
|
"REDIS_PORT",
|
|
12
|
-
"POSTHOG_API_KEY",
|
|
13
|
-
"POSTHOG_HOST",
|
|
14
12
|
"DEVICE_SERVICE",
|
|
15
13
|
"DT_API_KEY",
|
|
16
14
|
"MONITORING_SERVICE_PYTHON",
|
|
@@ -101,4 +99,11 @@ exports.CONFIG_KEYS = {
|
|
|
101
99
|
pms: "PMS_DB_URI",
|
|
102
100
|
},
|
|
103
101
|
},
|
|
102
|
+
OPERATION_NODE: {
|
|
103
|
+
env: ["PMS_DB_URI"],
|
|
104
|
+
INTERNAL_EVENT_HANDLER: false,
|
|
105
|
+
db_keys: {
|
|
106
|
+
pms: "PMS_DB_URI",
|
|
107
|
+
},
|
|
108
|
+
},
|
|
104
109
|
};
|
|
@@ -6,6 +6,7 @@ export declare const CONNECTION_PROVIDERS: {
|
|
|
6
6
|
readonly YANOLJA: "Yanolja";
|
|
7
7
|
readonly SMOOBU: "Smoobu";
|
|
8
8
|
readonly WEBREZPRO: "Webrezpro";
|
|
9
|
+
readonly MEWS: "Mews";
|
|
9
10
|
readonly SENSIBO: "Sensibo";
|
|
10
11
|
readonly VERDANT: "Verdant";
|
|
11
12
|
readonly SALTOKS: "SaltoKS";
|
|
@@ -18,4 +19,5 @@ export declare const CONNECTION_PROVIDERS: {
|
|
|
18
19
|
readonly DORMAKABA: "Dormakaba";
|
|
19
20
|
readonly DUSAW: "Dusaw";
|
|
20
21
|
readonly LOCKLY: "Lockly";
|
|
22
|
+
readonly CHECKFRONT: "Checkfront";
|
|
21
23
|
};
|
|
@@ -10,6 +10,7 @@ exports.CONNECTION_PROVIDERS = {
|
|
|
10
10
|
YANOLJA: "Yanolja",
|
|
11
11
|
SMOOBU: "Smoobu",
|
|
12
12
|
WEBREZPRO: "Webrezpro",
|
|
13
|
+
MEWS: "Mews",
|
|
13
14
|
// THERMOSTATS
|
|
14
15
|
SENSIBO: "Sensibo",
|
|
15
16
|
VERDANT: "Verdant",
|
|
@@ -24,4 +25,5 @@ exports.CONNECTION_PROVIDERS = {
|
|
|
24
25
|
DORMAKABA: "Dormakaba",
|
|
25
26
|
DUSAW: "Dusaw",
|
|
26
27
|
LOCKLY: "Lockly",
|
|
28
|
+
CHECKFRONT: "Checkfront",
|
|
27
29
|
};
|
|
@@ -3,8 +3,9 @@ export declare class AdminRepository {
|
|
|
3
3
|
private readonly deviceRepository;
|
|
4
4
|
private readonly postgres;
|
|
5
5
|
private readonly localDeviceService;
|
|
6
|
+
private readonly redisUtils;
|
|
6
7
|
constructor();
|
|
7
|
-
getZonesByAccessGroupIds(accessGroupIds: string[]): Promise<any[]>;
|
|
8
|
+
getZonesByAccessGroupIds(accessGroupIds: string[], propertyId: string): Promise<any[]>;
|
|
8
9
|
getZonesByAccessGroups(accessGroupIds: string[]): Promise<any[]>;
|
|
9
10
|
getAccessGroup(accessGroupId: string, propertyId?: string): Promise<IAccessGroup | null>;
|
|
10
11
|
getZoneAccessGroupByZoneId(zoneId: string): Promise<IZoneAccessGroup[] | null>;
|
|
@@ -78,6 +78,7 @@ const Device_repository_1 = require("../device/local/repository/Device.repositor
|
|
|
78
78
|
const db_1 = require("../../db/db");
|
|
79
79
|
const interfaces_1 = require("../device/cloud/interfaces");
|
|
80
80
|
const services_1 = require("../device/local/services");
|
|
81
|
+
const config_1 = require("../../config/config");
|
|
81
82
|
let AdminRepository = (() => {
|
|
82
83
|
let _classDecorators = [(0, typedi_1.Service)()];
|
|
83
84
|
let _classDescriptor;
|
|
@@ -88,25 +89,9 @@ let AdminRepository = (() => {
|
|
|
88
89
|
this.deviceRepository = typedi_1.default.get(Device_repository_1.DeviceRepository);
|
|
89
90
|
this.postgres = (0, db_1.getPostgresClient)();
|
|
90
91
|
this.localDeviceService = typedi_1.default.get(services_1.LocalDeviceService);
|
|
92
|
+
this.redisUtils = typedi_1.default.get(utils_1.RedisUtils);
|
|
91
93
|
}
|
|
92
|
-
async getZonesByAccessGroupIds(accessGroupIds) {
|
|
93
|
-
// // Get propertyId from any of the accessGroupIds
|
|
94
|
-
// const accessGroupIdsResult = await this.postgres.query(
|
|
95
|
-
// `SELECT "propertyId" FROM dt_collections WHERE "id" = ANY($1) LIMIT 1`,
|
|
96
|
-
// [accessGroupIds]
|
|
97
|
-
// );
|
|
98
|
-
// const propertyId = accessGroupIdsResult.rows[0].propertyId;
|
|
99
|
-
// const sortedAccessGroupIds = [...accessGroupIds].sort((a, b) =>
|
|
100
|
-
// a.localeCompare(b)
|
|
101
|
-
// );
|
|
102
|
-
// // Check if the result is already cached
|
|
103
|
-
// const redisKey = `${propertyId}:zonesAndDevicesByAccessGroupIds:${sortedAccessGroupIds.join(
|
|
104
|
-
// ","
|
|
105
|
-
// )}`;
|
|
106
|
-
// const cachedResult = await this.redisUtils.get(redisKey);
|
|
107
|
-
// if (cachedResult) {
|
|
108
|
-
// return JSON.parse(cachedResult);
|
|
109
|
-
// }
|
|
94
|
+
async getZonesByAccessGroupIds(accessGroupIds, propertyId) {
|
|
110
95
|
// If not cached, get the result from the database
|
|
111
96
|
const result = await this.postgres.query(`SELECT
|
|
112
97
|
"zc"."id" AS "zoneCollectionMapId",
|
|
@@ -140,7 +125,18 @@ let AdminRepository = (() => {
|
|
|
140
125
|
const collectionZone = [];
|
|
141
126
|
for (let zone of response) {
|
|
142
127
|
let zoneIds = [];
|
|
143
|
-
|
|
128
|
+
let zones = null;
|
|
129
|
+
const redisKey = `${propertyId}:childZones:${zone.zoneId}`;
|
|
130
|
+
const zonesCache = await this.redisUtils.get(redisKey);
|
|
131
|
+
if (zonesCache !== null && zonesCache !== undefined) {
|
|
132
|
+
(0, config_1.getLogger)().info(`Got child zones from redis`);
|
|
133
|
+
zones = JSON.parse(zonesCache);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
const response = await (0, utils_1.getAdminServiceAxiosInstance)().get(`/zones/child?zoneId=${zone.zoneId}`);
|
|
137
|
+
zones = response?.data?.data;
|
|
138
|
+
await this.redisUtils.set(redisKey, JSON.stringify(zones), 86400);
|
|
139
|
+
}
|
|
144
140
|
zoneIds.push(zone.zoneId);
|
|
145
141
|
if (zones.childZones?.length > 0) {
|
|
146
142
|
const nestedZoneIds = new Set(_zones(zones.childZones));
|
|
@@ -3,7 +3,7 @@ export declare class AdminService {
|
|
|
3
3
|
private readonly adminRepository;
|
|
4
4
|
private readonly redisUtils;
|
|
5
5
|
constructor();
|
|
6
|
-
getZonesByAccessGroupIds(accessGroupIds: string[]): Promise<any[] | undefined>;
|
|
6
|
+
getZonesByAccessGroupIds(accessGroupIds: string[], propertyId: string): Promise<any[] | undefined>;
|
|
7
7
|
getZonesByAccessGroups(accessGroupIds: string[]): Promise<any[] | undefined>;
|
|
8
8
|
getAccessGroup(accessGroupId: string, propertyId?: string): Promise<IAccessGroup | null>;
|
|
9
9
|
getAccessGroupByZoneId(zoneId: string): Promise<IAccessGroup[] | []>;
|
|
@@ -85,9 +85,9 @@ let AdminService = (() => {
|
|
|
85
85
|
this.adminRepository = typedi_1.default.get(Admin_repository_1.AdminRepository);
|
|
86
86
|
this.redisUtils = typedi_1.default.get(redis_utils_1.RedisUtils);
|
|
87
87
|
}
|
|
88
|
-
async getZonesByAccessGroupIds(accessGroupIds) {
|
|
88
|
+
async getZonesByAccessGroupIds(accessGroupIds, propertyId) {
|
|
89
89
|
try {
|
|
90
|
-
return await this.adminRepository.getZonesByAccessGroupIds(accessGroupIds);
|
|
90
|
+
return await this.adminRepository.getZonesByAccessGroupIds(accessGroupIds, propertyId);
|
|
91
91
|
}
|
|
92
92
|
catch (error) {
|
|
93
93
|
console.log(error);
|
|
@@ -4,6 +4,5 @@ export declare class ConnectionRepository {
|
|
|
4
4
|
constructor();
|
|
5
5
|
createConnection(data: Partial<IConnection>): Promise<IConnection>;
|
|
6
6
|
getConnectionById(connectionId: string): Promise<IConnection>;
|
|
7
|
-
queryConnections(query: Partial<IConnection>): Promise<IConnection[]>;
|
|
8
7
|
updateConnection(connectionId: string, data: Partial<IConnection>): Promise<any>;
|
|
9
8
|
}
|
|
@@ -69,28 +69,6 @@ let ConnectionRepository = (() => {
|
|
|
69
69
|
const result = await this.pool.query("SELECT * FROM dt_connections WHERE id = $1", [connectionId]);
|
|
70
70
|
return result.rows[0];
|
|
71
71
|
}
|
|
72
|
-
async queryConnections(query) {
|
|
73
|
-
// Filter out undefined/null values and build WHERE clause
|
|
74
|
-
const conditions = [];
|
|
75
|
-
const values = [];
|
|
76
|
-
let paramIndex = 1;
|
|
77
|
-
// Build conditions dynamically based on provided query parameters
|
|
78
|
-
Object.keys(query).forEach((key) => {
|
|
79
|
-
const value = query[key];
|
|
80
|
-
if (value !== undefined && value !== null) {
|
|
81
|
-
conditions.push(`"${key}" = $${paramIndex}`);
|
|
82
|
-
values.push(value);
|
|
83
|
-
paramIndex++;
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
// Build the SQL query
|
|
87
|
-
let sql = "SELECT * FROM dt_connections";
|
|
88
|
-
if (conditions.length > 0) {
|
|
89
|
-
sql += ` WHERE ${conditions.join(" AND ")}`;
|
|
90
|
-
}
|
|
91
|
-
const result = await this.pool.query(sql, values);
|
|
92
|
-
return result.rows;
|
|
93
|
-
}
|
|
94
72
|
async updateConnection(connectionId, data) {
|
|
95
73
|
// Build dynamic SET clause with quoted column names
|
|
96
74
|
const setClause = Object.keys(data)
|
|
@@ -4,6 +4,5 @@ export declare class LocalConnectionService {
|
|
|
4
4
|
constructor();
|
|
5
5
|
createConnection(data: Partial<IConnection>): Promise<IConnection>;
|
|
6
6
|
getConnection(connectionId: string): Promise<IConnection>;
|
|
7
|
-
queryConnections(query: Partial<IConnection>): Promise<IConnection[]>;
|
|
8
7
|
updateConnection(connectionId: string, data: Partial<IConnection>): Promise<IConnection>;
|
|
9
8
|
}
|
|
@@ -22,9 +22,6 @@ class LocalConnectionService {
|
|
|
22
22
|
}
|
|
23
23
|
return await this.connectionRepository.getConnectionById(connectionId);
|
|
24
24
|
}
|
|
25
|
-
async queryConnections(query) {
|
|
26
|
-
return await this.connectionRepository.queryConnections(query);
|
|
27
|
-
}
|
|
28
25
|
async updateConnection(connectionId, data) {
|
|
29
26
|
if (!connectionId) {
|
|
30
27
|
throw new Error("Connection ID is required");
|
|
@@ -239,7 +239,7 @@ let IssueService = (() => {
|
|
|
239
239
|
title: device.deviceType.type.toLowerCase() === "hub"
|
|
240
240
|
? "Hub Offline"
|
|
241
241
|
: "Device Offline",
|
|
242
|
-
description: `${device.name} has gone offline ${reason ? `Reason: ${reason}
|
|
242
|
+
description: `${device.name} has gone offline. ${reason ? `Reason: ${reason}.` : ""}`,
|
|
243
243
|
createdBy: source,
|
|
244
244
|
category: issue_types_1.IssuesCategory.OPERATIONS,
|
|
245
245
|
priority: issue_types_1.IssuePriority.CRITICAL,
|
|
@@ -43,6 +43,7 @@ var EntitySubType;
|
|
|
43
43
|
EntitySubType["YANOLJA"] = "YANOLJA";
|
|
44
44
|
EntitySubType["SKYTOUCH"] = "SKYTOUCH";
|
|
45
45
|
EntitySubType["SMOOBU"] = "SMOOBU";
|
|
46
|
+
EntitySubType["MEWS"] = "MEWS";
|
|
46
47
|
EntitySubType["WEBREZPRO"] = "WEBREZPRO";
|
|
47
48
|
// DEVICE PROVIDERS
|
|
48
49
|
EntitySubType["SMARTTHINGS"] = "SMARTTHINGS";
|
|
@@ -123,6 +123,18 @@ class RateLimitUtils {
|
|
|
123
123
|
provider: constants_1.CONNECTION_PROVIDERS.WEBREZPRO,
|
|
124
124
|
maxTimeoutWindowMs: 120000,
|
|
125
125
|
});
|
|
126
|
+
configs.set(constants_1.CONNECTION_PROVIDERS.CHECKFRONT, {
|
|
127
|
+
maxRequests: 10,
|
|
128
|
+
windowMs: 60000,
|
|
129
|
+
provider: constants_1.CONNECTION_PROVIDERS.CHECKFRONT,
|
|
130
|
+
maxTimeoutWindowMs: 120000,
|
|
131
|
+
});
|
|
132
|
+
configs.set(constants_1.CONNECTION_PROVIDERS.MEWS, {
|
|
133
|
+
maxRequests: 200,
|
|
134
|
+
windowMs: 30000, // 30 seconds - 200 requests per AccessToken within 30 seconds
|
|
135
|
+
provider: constants_1.CONNECTION_PROVIDERS.MEWS,
|
|
136
|
+
maxTimeoutWindowMs: 120000,
|
|
137
|
+
});
|
|
126
138
|
return configs;
|
|
127
139
|
}
|
|
128
140
|
static async isRateLimitAllowed(connectionId, provider, rateLimitConfigs) {
|