@sedni/cloud_common 1.2.0 → 2.1.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.
package/package.json CHANGED
@@ -1,15 +1,26 @@
1
1
  {
2
2
  "name": "@sedni/cloud_common",
3
- "version": "1.2.0",
3
+ "version": "2.1.0",
4
4
  "description": "Common package for all types, resources and tools of Diamar Cloud",
5
- "main": "index.js",
5
+ "type": "module",
6
+ "main": "./dist/node-entry.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
6
9
  "scripts": {
10
+ "build": "tsup app/index.ts app/node-entry.cjs --format esm,cjs --dts --out-dir dist",
7
11
  "test": "cross-env NODE_ENV=internal_test mocha --recursive --exit app/test/*",
8
12
  "coverage": "nyc --include 'app/**/*controller.js' mocha",
9
13
  "lint": "eslint app/*",
10
14
  "lint:fix": "eslint --fix app/*",
11
15
  "playground": "node playground.js"
12
16
  },
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.js",
21
+ "require": "./dist/node-entry.cjs"
22
+ }
23
+ },
13
24
  "author": "Jose Luis Silvestre García",
14
25
  "license": "ISC",
15
26
  "dependencies": {
@@ -20,6 +31,7 @@
20
31
  },
21
32
  "devDependencies": {
22
33
  "@eslint/js": "^9.32.0",
34
+ "@types/node": "^24.10.1",
23
35
  "chai": "^5.2.1",
24
36
  "eslint": "^9.32.0",
25
37
  "eslint-plugin-n": "^17.21.0",
@@ -28,6 +40,8 @@
28
40
  "nyc": "^17.1.0",
29
41
  "proxyquire": "^2.1.3",
30
42
  "sinon": "^21.0.0",
31
- "supertest": "^7.1.4"
43
+ "supertest": "^7.1.4",
44
+ "tsup": "^8.5.0",
45
+ "typescript": "^5.9.3"
32
46
  }
33
47
  }
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "allowJs": true,
7
+ "checkJs": false,
8
+ "declaration": true,
9
+ "outDir": "./dist",
10
+ "rootDir": "app",
11
+ "strict": true,
12
+ "resolveJsonModule": true,
13
+ "esModuleInterop": true,
14
+ "forceConsistentCasingInFileNames": true,
15
+ "skipLibCheck": true
16
+ },
17
+ "include": [
18
+ "app/**/*"
19
+ ]
20
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "module": "CommonJS",
5
+ "outDir": "./dist",
6
+ "declaration": false
7
+ },
8
+ "include": [
9
+ "app/node-entry.ts",
10
+ "app/models/**/*.js"
11
+ ]
12
+ }
@@ -1,73 +0,0 @@
1
- const mongoose = require("mongoose");
2
- const mongooseAutopopulate = require("mongoose-autopopulate");
3
- const mongoosePaginate = require("mongoose-paginate-v2");
4
- const mongooseAggregatePaginate = require("mongoose-aggregate-paginate-v2");
5
-
6
- const channelSchema = new mongoose.Schema({
7
- channel_tag: {
8
- type: String,
9
- required: true,
10
- },
11
- channel_description: {
12
- type: String,
13
- required: true,
14
- },
15
- channel_unit_id: {
16
- type: mongoose.Schema.Types.ObjectId,
17
- ref: "Unit",
18
- required: true,
19
- autopopulate: true,
20
- },
21
- channel_parsed : {
22
- type: Object,
23
- required: true,
24
- },
25
- channel_last_bucket_sync: {
26
- type: Date,
27
- required: false,
28
- },
29
- }, {
30
- timestamps: {
31
- createdAt: true,
32
- updatedAt: true
33
- },
34
- collection: "channels",
35
- toJSON: {
36
- transform: function (doc, ret)
37
- {
38
- ret.id = ret._id;
39
- ret.channel_unit = ret.channel_unit_id;
40
- ret.channel_unit_id = ret.channel_unit_id.unit_id;
41
- delete ret._id;
42
- delete ret.__v;
43
- },
44
- },
45
- });
46
-
47
- /**
48
- * ///////////////////////////////////////////////
49
- * ///////////// INDEXES /////////////////
50
- * ///////////////////////////////////////////////
51
- */
52
-
53
- /**
54
- * Index used primarily for filtering by channel_tag
55
- */
56
- channelSchema.index({ "channel_tag" : 1 }, { unique: true });
57
-
58
- /**
59
- * Index used primarily for filtering by channel_description
60
- */
61
- channelSchema.index({ "channel_description" : 1 });
62
-
63
-
64
- /**
65
- * ///////////////////////////////////////////////
66
- * ///////////// PLUGINS /////////////////
67
- * ///////////////////////////////////////////////
68
- */
69
- channelSchema.plugin(mongoosePaginate);
70
- channelSchema.plugin(mongooseAggregatePaginate);
71
- channelSchema.plugin(mongooseAutopopulate);
72
-
73
- module.exports = channelSchema;
@@ -1,314 +0,0 @@
1
- const mongoose = require("mongoose");
2
- const mongooseAutopopulate = require("mongoose-autopopulate");
3
- const mongoosePaginate = require("mongoose-paginate-v2");
4
- const mongooseAggregatePaginate = require("mongoose-aggregate-paginate-v2");
5
-
6
- const dataPointSchema = new mongoose.Schema({
7
- timestamp: {
8
- type: Number,
9
- required: true,
10
- },
11
- value: {
12
- type: Number,
13
- required: true,
14
- }
15
- }, {
16
- _id: false,
17
- });
18
-
19
- const channeldataBucketSchema = new mongoose.Schema({
20
- start_date: {
21
- type: Date,
22
- required: true,
23
- default: Date.now,
24
- },
25
- end_date: {
26
- type: Date,
27
- required: true,
28
- default: function()
29
- {
30
- return new Date(Date.now() + 1000 * 60 * 60); // 1 hour from now
31
- }
32
- },
33
- data : {
34
- type: [dataPointSchema],
35
- required: true,
36
- default: [],
37
- },
38
- size : {
39
- type: Number,
40
- required: true,
41
- default: 0,
42
- },
43
- synced : {
44
- type: Number,
45
- required: true,
46
- default: 0,
47
- },
48
- sum : {
49
- type: Number,
50
- required: true,
51
- default: 0,
52
- },
53
- }, {
54
- toJSON: {
55
- transform: function (doc, ret)
56
- {
57
- ret.id = ret._id;
58
- delete ret._id;
59
- delete ret.__v;
60
- ret.start_date = ret.start_date.getTime();
61
- ret.end_date = ret.end_date.getTime();
62
- ret.avg = ret.sum / ret.size;
63
- },
64
- },
65
- versionKey: false,
66
- });
67
-
68
- /**
69
- * ///////////////////////////////////////////////
70
- * ///////////// INDEXES /////////////////
71
- * ///////////////////////////////////////////////
72
- */
73
-
74
- /**
75
- * Index the start_date and end_date fields for faster queries.
76
- * The compound index will be used to query the buckets by date range.
77
- */
78
- channeldataBucketSchema.index({ start_date: 1, end_date: 1 }, { background: true });
79
-
80
- /**
81
- * Index used to delete old buckets automatically.
82
- */
83
- channeldataBucketSchema.index({ start_date: 1 }, { expireAfterSeconds: 60 * 60 * 24 * 365, background: true }); // 1 year
84
-
85
- /**
86
- * ///////////////////////////////////////////////
87
- * ///////////// PLUGINS /////////////////
88
- * ///////////////////////////////////////////////
89
- */
90
- channeldataBucketSchema.plugin(mongoosePaginate);
91
- channeldataBucketSchema.plugin(mongooseAggregatePaginate);
92
- channeldataBucketSchema.plugin(mongooseAutopopulate);
93
-
94
-
95
- /**
96
- * ///////////////////////////////////////////////
97
- * //////////// FUNCTIONS ////////////////
98
- * ///////////////////////////////////////////////
99
- */
100
- /**
101
- * Insert a data point into a specific bucket.
102
- *
103
- * The data point will be inserted into the bucket and the size and sum will be updated.
104
- * @param {Number} timestamp The timestamp of the data point
105
- * @param {Number} value The value of the data point
106
- */
107
- channeldataBucketSchema.methods.insertDataPoint = async function(timestamp, value)
108
- {
109
- this.data.push({ timestamp: timestamp, value: value });
110
- this.size++;
111
- this.sum += value;
112
- await this.save();
113
- };
114
-
115
- /**
116
- * Remove data points outside the specified date range within the bucket.
117
- *
118
- * IT WILL NOT SAVE THE BUCKET, YOU NEED TO CALL save() AFTER THIS FUNCTION TO SAVE THE BUCKET
119
- * @param {Number | Date} start_date The start date of the date range
120
- * @param {Number | Date} end_date The end date of the date range
121
- */
122
- channeldataBucketSchema.methods.removeDataPointsOutsideDateRange = function(start_date, end_date)
123
- {
124
- start_date = start_date instanceof Date ? start_date.getTime() : start_date;
125
- end_date = end_date instanceof Date ? end_date.getTime() : end_date;
126
-
127
- this.data = this.data.filter(data_point => data_point.timestamp >= start_date && data_point.timestamp < end_date);
128
- this.size = this.data.length;
129
- this.sum = this.data.reduce((sum, data_point) => sum + data_point.value, 0);
130
- };
131
-
132
- /**
133
- * Check if the bucket is closed, meaning that it is no longer accepting data points.
134
- * @param {Number} timestamp The timestamp to check if the bucket is closed
135
- * @returns {Boolean} True if the bucket is closed, false otherwise
136
- */
137
- channeldataBucketSchema.methods.isBucketClosed = function(timestamp = Date.now())
138
- {
139
- return timestamp >= this.end_date.getTime();
140
- };
141
-
142
- /**
143
- * Insert a data point into the corresponding bucket.
144
- *
145
- * If no bucket exists for the timestamp, it will be created.
146
- * If a bucket exists for the timestamp, the data point will be inserted into the bucket and the size and sum will be updated.
147
- * @param {Number} timestamp The timestamp of the data point
148
- * @param {Number} value The value of the data point
149
- * @returns {Object} The bucket that the data point was inserted into
150
- */
151
- channeldataBucketSchema.statics.insertDataPoint = async function(timestamp, value)
152
- {
153
- // Truncate the timestamp to the nearest hour
154
- const date = new Date(timestamp);
155
- date.setMinutes(0);
156
- date.setSeconds(0);
157
- date.setMilliseconds(0);
158
-
159
- // Upsert the data point
160
- const bucket = await this.findOneAndUpdate(
161
- {
162
- start_date: date
163
- },
164
- {
165
- $push:
166
- {
167
- data:
168
- {
169
- timestamp: timestamp,
170
- value: value
171
- }
172
- },
173
-
174
- $inc:
175
- {
176
- size: 1,
177
- sum: value
178
- },
179
-
180
- $set:
181
- {
182
- end_date: new Date(date.getTime() + 1000 * 60 * 60),
183
- }
184
- },
185
- {
186
- upsert: true,
187
- new: true
188
- }
189
- );
190
-
191
- return bucket;
192
- };
193
-
194
- /**
195
- * Get the last time the data was synced
196
- * @param {Object} options The options to get the last time the data was synced
197
- * @param {String} options.channel_tag The channel tag to get the data from
198
- * @param {Object} options.db The database to get the channel document from
199
- * @returns {Number} The last time the data was synced
200
- */
201
- channeldataBucketSchema.statics.lastTimeSynced = async function(options)
202
- {
203
- let last_sync = 0;
204
- if(options?.channel_tag && options?.db)
205
- {
206
- // Get the last time the data was synced
207
- const channel = await options.db.collection("channels").findOne({
208
- channel_tag : options.channel_tag
209
- });
210
-
211
- last_sync = channel.channel_last_bucket_sync.getTime();
212
- }
213
- return last_sync;
214
- };
215
-
216
- /**
217
- * Get the data that has not been uploaded to the cloud yet
218
- * @param {Object} options The options to get the data
219
- * @param {Date | Number} options.last_sync The last time the data was synced, if not provided it will be fetched from the channel document
220
- * @param {String} options.channel_tag The channel tag to get the data from, only used if last_sync is not provided
221
- * @param {Object} options.db The database to get the channel document from, only used if last_sync is not provided
222
- * @returns {Array} The data that has not been uploaded to the cloud yet
223
- */
224
- channeldataBucketSchema.statics.getNotUploadedData = async function(options)
225
- {
226
- // Get the last time the data was synced
227
- const last_sync = options?.last_sync ?? await this.lastTimeSynced(options);
228
-
229
- // Get all the buckets that synced is lt size and end_date is gt last_sync
230
- const buckets = await this.find({
231
- end_date: {
232
- $gt: new Date(last_sync)
233
- }
234
- });
235
-
236
- return buckets;
237
- };
238
-
239
- /**
240
- * Get the data in the specified date range
241
- * @param {Date | Number} start_date The start date of the date range
242
- * @param {Date | Number} end_date The end date of the date range
243
- * @param {Boolean} plain If true, the data will be returned as an array of data points, otherwise it will be returned as an array of buckets
244
- * @returns {Array} The data in the specified date range. It will be an array of data points if plain is true, otherwise it will be an array of buckets
245
- */
246
- channeldataBucketSchema.statics.getData = async function(start_date, end_date, plain = false)
247
- {
248
- // Truncate the timestamp to the nearest hour
249
- const date = new Date(start_date);
250
- date.setMinutes(0);
251
- date.setSeconds(0);
252
- date.setMilliseconds(0);
253
-
254
- // Get the data in the specified date range
255
- const data = await this.find({
256
- start_date: {
257
- $gte: date,
258
- $lt: new Date(end_date)
259
- }
260
- });
261
-
262
- if(!data || data.length === 0)
263
- {
264
- return [];
265
- }
266
-
267
- // Remove the data inside the bucket that is not in the specified date range
268
- data[0].removeDataPointsOutsideDateRange(start_date, end_date);
269
-
270
- if(data.length > 1)
271
- {
272
- data[1].removeDataPointsOutsideDateRange(start_date, end_date);
273
- }
274
-
275
- return plain ? data.flatMap(bucket => {
276
- return bucket.data.map(data_point => {
277
- return {
278
- timestamp: data_point.timestamp,
279
- value: data_point.value
280
- };
281
- });
282
- }) : data;
283
- };
284
-
285
-
286
- channeldataBucketSchema.statics.upsertBucket = async function(bucket)
287
- {
288
- const date = new Date(bucket.start_date);
289
- date.setMinutes(0);
290
- date.setSeconds(0);
291
- date.setMilliseconds(0);
292
-
293
- const result = await this.updateOne(
294
- {
295
- start_date: date
296
- },
297
- {
298
- $set:
299
- {
300
- data: bucket.data,
301
- size: bucket.size,
302
- sum: bucket.sum,
303
- end_date: new Date(date.getTime() + 1000 * 60 * 60),
304
- }
305
- },
306
- {
307
- upsert: true
308
- }
309
- );
310
-
311
- return result;
312
- };
313
-
314
- module.exports = channeldataBucketSchema;
@@ -1,95 +0,0 @@
1
- const mongoose = require("mongoose");
2
- const mongooseAutopopulate = require("mongoose-autopopulate");
3
- const mongoosePaginate = require("mongoose-paginate-v2");
4
- const mongooseAggregatePaginate = require("mongoose-aggregate-paginate-v2");
5
- const { EventCategories, EventCriticality } = require("../types/event.types");
6
-
7
- const eventSchema = new mongoose.Schema({
8
- event_message: {
9
- type: String,
10
- required: true
11
- },
12
- event_source: {
13
- type: String,
14
- required: true
15
- },
16
- event_user: {
17
- type: String,
18
- required: false
19
- },
20
- event_category: {
21
- type: String,
22
- required: true,
23
- enum: Object.values(EventCategories)
24
- },
25
- event_criticality: {
26
- type: String,
27
- required: true,
28
- enum: Object.values(EventCriticality)
29
- },
30
- event_type: {
31
- type: String,
32
- required: true
33
- },
34
- event_timestamp: {
35
- type: Date,
36
- default: Date.now,
37
- },
38
- event_data: {
39
- type: Object
40
- }
41
- }, {
42
- timestamps: {
43
- createdAt: true,
44
- updatedAt: false
45
- },
46
- versionKey: false,
47
- toJSON: {
48
- transform: function (doc, ret)
49
- {
50
- ret.id = ret._id;
51
- delete ret._id;
52
- delete ret.createdAt;
53
- ret.event_timestamp = ret.event_timestamp.getTime();
54
- }
55
- }
56
- });
57
-
58
- /**
59
- * ///////////////////////////////////////////////
60
- * ///////////// INDEXES /////////////////
61
- * ///////////////////////////////////////////////
62
- */
63
-
64
- /**
65
- * Index used primarily for filtering by event_type
66
- */
67
- eventSchema.index({ "event_type" : 1 });
68
-
69
- /**
70
- * Index used primarily for filtering by event_category
71
- */
72
- eventSchema.index({ "event_category" : 1 });
73
-
74
- /**
75
- * Index used to delete old events automatically.
76
- * This function will need to be called to create the TTL index.
77
- * The index will expire documents after the specified time in seconds.
78
- * The default is set to one year, but it can be changed by passing the expirationTimeInSeconds parameter.
79
- */
80
- const oneYear = 60 * 60 * 24 * 365; // One year in seconds
81
- eventSchema.addTTLIndex = function(ttlField, expirationTimeInSeconds = oneYear)
82
- {
83
- this.index({ [ttlField]: 1 }, { expireAfterSeconds: expirationTimeInSeconds });
84
- }
85
-
86
- /**
87
- * ///////////////////////////////////////////////
88
- * ///////////// PLUGINS /////////////////
89
- * ///////////////////////////////////////////////
90
- */
91
- eventSchema.plugin(mongoosePaginate);
92
- eventSchema.plugin(mongooseAggregatePaginate);
93
- eventSchema.plugin(mongooseAutopopulate);
94
-
95
- module.exports = eventSchema;
@@ -1,106 +0,0 @@
1
- const mongoose = require("mongoose");
2
- const mongooseAutopopulate = require("mongoose-autopopulate");
3
- const mongoosePaginate = require("mongoose-paginate-v2");
4
- const mongooseAggregatePaginate = require("mongoose-aggregate-paginate-v2");
5
- const { AlarmTypes, AlarmPriorities, CloudAlarmStates, DiamarAlarmStates } = require("../types/alarm.types");
6
-
7
- const historySchema = new mongoose.Schema({
8
- channel_tag: {
9
- type: String,
10
- required: true,
11
- },
12
- alarm_timestamp: {
13
- type: Date,
14
- required: true,
15
- default: Date.now,
16
- },
17
- alarm_priority: {
18
- type: String,
19
- required: true,
20
- enum: Object.values(AlarmPriorities),
21
- },
22
- alarm_original_state: {
23
- type: String,
24
- required: true,
25
- enum: Object.values(DiamarAlarmStates),
26
- },
27
- alarm_state: {
28
- type: String,
29
- required: true,
30
- enum: Object.values(CloudAlarmStates),
31
- },
32
- alarm_type: {
33
- type: String,
34
- required: true,
35
- enum: Object.values(AlarmTypes),
36
- },
37
- alarm_value: {
38
- type: Number,
39
- required: false,
40
- },
41
- alarm_message: {
42
- type: String,
43
- required: false,
44
- },
45
- alarm_data: {
46
- type: Object,
47
- required: false,
48
- },
49
- }, {
50
- timestamps: {
51
- createdAt: false,
52
- updatedAt: false
53
- },
54
- versionKey: false,
55
- collection: "history",
56
- toJSON: {
57
- transform: function (doc, ret)
58
- {
59
- ret.id = ret._id;
60
- delete ret._id;
61
- delete ret.__v;
62
- ret.alarm_timestamp = new Date(ret.alarm_timestamp).getTime();
63
- ret.alarm = {
64
- alarm_priority: ret.alarm_priority,
65
- alarm_state: ret.alarm_original_state ?? "Inactive",
66
- alarm_type: ret.alarm_type,
67
- alarm_value: ret.alarm_value === null ? "inf" : `${ret.alarm_value}`,
68
- alarm_timestamp: new Date(ret.alarm_timestamp).getTime()
69
- };
70
- },
71
- },
72
- });
73
-
74
- /**
75
- * ///////////////////////////////////////////////
76
- * ///////////// INDEXES /////////////////
77
- * ///////////////////////////////////////////////
78
- */
79
-
80
- /**
81
- * Index used primarily for filtering by channel_tag
82
- */
83
- historySchema.index({ "channel_tag" : 1 });
84
-
85
- /**
86
- * Index used to delete old alarms automatically.
87
- * This function will need to be called to create the TTL index.
88
- * The index will expire documents after the specified time in seconds.
89
- * The default is set to one year, but it can be changed by passing the expirationTimeInSeconds parameter.
90
- */
91
- const oneYear = 60 * 60 * 24 * 365; // One year in seconds
92
- historySchema.addTTLIndex = function(ttlField, expirationTimeInSeconds = oneYear)
93
- {
94
- this.index({ [ttlField]: 1 }, { expireAfterSeconds: expirationTimeInSeconds });
95
- }
96
-
97
- /**
98
- * ///////////////////////////////////////////////
99
- * ///////////// PLUGINS /////////////////
100
- * ///////////////////////////////////////////////
101
- */
102
- historySchema.plugin(mongoosePaginate);
103
- historySchema.plugin(mongooseAggregatePaginate);
104
- historySchema.plugin(mongooseAutopopulate);
105
-
106
- module.exports = historySchema;