@justair/justair-library 4.7.1 → 4.7.2

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.
@@ -1,251 +1,251 @@
1
- import mongoose from "mongoose";
2
-
3
- const correctionSnapshotSchema = new mongoose.Schema(
4
- {
5
- equationType: String,
6
- dateCreated: Date,
7
- },
8
- { _id: false } // Not generating separate _id for each correction
9
- );
10
-
11
- // Annotation Schema
12
- const annotationSchema = new mongoose.Schema(
13
- {
14
- measurementIdentifier: {
15
- type: String,
16
- required: true,
17
- trim: true,
18
- // Examples: "PM2_5", "PM10", "NO2", "O3", etc.
19
- },
20
- comment: {
21
- type: String,
22
- required: true,
23
- trim: true,
24
- },
25
- adminId: {
26
- type: mongoose.Types.ObjectId,
27
- ref: "Admin",
28
- required: true,
29
- },
30
- timestamp: {
31
- type: Date,
32
- default: Date.now,
33
- required: true,
34
- },
35
- },
36
- {
37
- _id: true,
38
- timestamps: false,
39
- }
40
- );
41
-
42
- // Add index for efficient querying
43
- annotationSchema.index({ measurementIdentifier: 1, timestamp: -1 });
44
-
45
- // Audit Schema
46
- const auditSchema = mongoose.Schema(
47
- {
48
- monitorId: { type: mongoose.Types.ObjectId, ref: "Monitors" },
49
- orgId: { type: mongoose.Types.ObjectId, ref: "Organizations" },
50
- timeUpdated: Date,
51
- deletedAt: { type: Date, default: Date.now },
52
- measurements: Object,
53
- monitorState: String,
54
- monitorSupplier: String,
55
- normalizedMeasurements: Object,
56
- flags: Object,
57
- appliedCorrections: {
58
- type: Map,
59
- of: correctionSnapshotSchema,
60
- default: {},
61
- },
62
- correctedNormalizedMeasurements: Object,
63
- annotations: [annotationSchema], // Include annotations in audit trail
64
- },
65
- {
66
- timestamps: true,
67
- }
68
- );
69
-
70
- const Audit = mongoose.model("Audit", auditSchema);
71
-
72
- // Measurements Schema
73
- const measurementsSchema = mongoose.Schema(
74
- {
75
- monitorId: { type: mongoose.Types.ObjectId, ref: "Monitors" },
76
- orgId: { type: mongoose.Types.ObjectId, ref: "Organizations" },
77
- timeUpdated: Date,
78
- measurements: Object,
79
- monitorState: String,
80
- monitorSupplier: String,
81
- normalizedMeasurements: Object,
82
- flags: Object,
83
- appliedCorrections: {
84
- type: Map,
85
- of: correctionSnapshotSchema,
86
- default: {},
87
- },
88
- correctedNormalizedMeasurements: Object,
89
- annotations: {
90
- type: [annotationSchema],
91
- default: [],
92
- },
93
- },
94
- {
95
- timestamps: true,
96
- }
97
- );
98
-
99
- // CRITICAL: Add compound indexes for monitorId + timeUpdated
100
- // Primary query pattern index (descending timeUpdated for latest data first)
101
- measurementsSchema.index({ monitorId: 1, timeUpdated: -1 });
102
- // Date range query index (ascending timeUpdated for range queries)
103
- measurementsSchema.index({ monitorId: 1, timeUpdated: 1 });
104
-
105
- // Flag-based query index for filtering by monitor and flags
106
- measurementsSchema.index({ monitorId: 1, flags: 1 });
107
-
108
- // Keep the individual indexes as they may still be useful for other queries
109
- measurementsSchema.index({ monitorId: 1 });
110
- measurementsSchema.index({ timeUpdated: 1 });
111
-
112
- // Annotation-related indexes
113
- measurementsSchema.index({
114
- "annotations.measurementIdentifier": 1,
115
- "annotations.timestamp": -1,
116
- });
117
- measurementsSchema.index({ "annotations.userId": 1 });
118
-
119
- // Pre-hook to log single document deletions
120
- measurementsSchema.pre("findOneAndDelete", async function () {
121
- const docToDelete = await this.model.findOne(this.getFilter());
122
- if (docToDelete) {
123
- console.log("Logging findOneAndDelete to audit", docToDelete);
124
- const auditLog = new Audit({
125
- monitorId: docToDelete.monitorId,
126
- orgId: docToDelete.orgId,
127
- timeUpdated: docToDelete.timeUpdated,
128
- measurements: docToDelete.measurements,
129
- monitorState: docToDelete.monitorState,
130
- monitorSupplier: docToDelete.monitorSupplier,
131
- normalizedMeasurements: docToDelete.normalizedMeasurements,
132
- flags: docToDelete.flags,
133
- appliedCorrections: docToDelete.appliedCorrections,
134
- correctedNormalizedMeasurements:
135
- docToDelete.correctedNormalizedMeasurements,
136
- annotations: docToDelete.annotations, // Include annotations in audit
137
- deletedAt: new Date(),
138
- });
139
- await auditLog.save();
140
- }
141
- });
142
-
143
- // Pre-hook to log multiple document deletions
144
- measurementsSchema.pre("deleteMany", async function () {
145
- console.log("deleteMany pre-hook triggered");
146
- const docsToDelete = await this.model.find(this.getFilter()).lean();
147
-
148
- if (docsToDelete.length) {
149
- console.log(`Logging ${docsToDelete.length} documents to audit`);
150
- const auditLogs = docsToDelete.map((doc) => ({
151
- monitorId: doc.monitorId,
152
- orgId: doc.orgId,
153
- timeUpdated: doc.timeUpdated,
154
- measurements: doc.measurements,
155
- monitorState: doc.monitorState,
156
- monitorSupplier: doc.monitorSupplier,
157
- normalizedMeasurements: doc.normalizedMeasurements,
158
- flags: doc.flags,
159
- appliedCorrections: doc.appliedCorrections,
160
- correctedNormalizedMeasurements: doc.correctedNormalizedMeasurements,
161
- annotations: doc.annotations, // Include annotations in audit
162
- deletedAt: new Date(),
163
- }));
164
-
165
- await Audit.insertMany(auditLogs);
166
- }
167
- });
168
-
169
- // Pre-hook to log a single document deletion (for deleteOne)
170
- measurementsSchema.pre("deleteOne", async function () {
171
- console.log("deleteOne pre-hook triggered");
172
- const docToDelete = await this.model.findOne(this.getFilter()).lean();
173
-
174
- if (docToDelete) {
175
- console.log("Logging deleteOne to audit", docToDelete);
176
- const auditLog = new Audit({
177
- monitorId: docToDelete.monitorId,
178
- orgId: docToDelete.orgId,
179
- timeUpdated: docToDelete.timeUpdated,
180
- measurements: docToDelete.measurements,
181
- monitorState: docToDelete.monitorState,
182
- monitorSupplier: docToDelete.monitorSupplier,
183
- normalizedMeasurements: docToDelete.normalizedMeasurements,
184
- flags: docToDelete.flags,
185
- appliedCorrections: docToDelete.appliedCorrections,
186
- correctedNormalizedMeasurements:
187
- docToDelete.correctedNormalizedMeasurements,
188
- annotations: docToDelete.annotations, // Include annotations in audit
189
- deletedAt: new Date(),
190
- });
191
- await auditLog.save();
192
- }
193
- });
194
-
195
- // Pre-hook to log single document updates
196
- measurementsSchema.pre("findOneAndUpdate", async function () {
197
- const docToUpdate = await this.model.findOne(this.getFilter()).lean();
198
- if (docToUpdate) {
199
- console.log("Logging findOneAndUpdate to audit", docToUpdate);
200
- const auditLog = new Audit({
201
- monitorId: docToUpdate.monitorId,
202
- orgId: docToUpdate.orgId,
203
- timeUpdated: docToUpdate.timeUpdated,
204
- measurements: docToUpdate.measurements,
205
- monitorState: docToUpdate.monitorState,
206
- monitorSupplier: docToUpdate.monitorSupplier,
207
- normalizedMeasurements: docToUpdate.normalizedMeasurements,
208
- flags: docToUpdate.flags,
209
- appliedCorrections: docToUpdate.appliedCorrections,
210
- correctedNormalizedMeasurements:
211
- docToUpdate.correctedNormalizedMeasurements,
212
- annotations: docToUpdate.annotations, // Include annotations in audit
213
- deletedAt: null, // No deletion happening, so set it to null or undefined
214
- });
215
- await auditLog.save();
216
- }
217
- });
218
-
219
- // Pre-hook to log multiple document updates
220
- measurementsSchema.pre("updateMany", async function () {
221
- const docsToUpdate = await this.model.find(this.getFilter()).lean();
222
- if (docsToUpdate.length) {
223
- console.log(`Logging ${docsToUpdate.length} documents to audit`);
224
- const auditLogs = docsToUpdate.map((doc) => ({
225
- monitorId: doc.monitorId,
226
- orgId: doc.orgId,
227
- timeUpdated: doc.timeUpdated,
228
- measurements: doc.measurements,
229
- monitorState: doc.monitorState,
230
- monitorSupplier: doc.monitorSupplier,
231
- normalizedMeasurements: doc.normalizedMeasurements,
232
- flags: doc.flags,
233
- appliedCorrections: doc.appliedCorrections,
234
- correctedNormalizedMeasurements: doc.correctedNormalizedMeasurements,
235
- annotations: doc.annotations, // Include annotations in audit
236
- deletedAt: null, // No deletion happening
237
- }));
238
-
239
- await Audit.insertMany(auditLogs);
240
- }
241
- });
242
-
243
- const Measurements = mongoose.model("Measurements", measurementsSchema);
244
-
245
- export {
246
- measurementsSchema,
247
- Measurements,
248
- Audit,
249
- auditSchema,
250
- annotationSchema,
251
- };
1
+ import mongoose from "mongoose";
2
+
3
+ const correctionSnapshotSchema = new mongoose.Schema(
4
+ {
5
+ equationType: String,
6
+ dateCreated: Date,
7
+ },
8
+ { _id: false } // Not generating separate _id for each correction
9
+ );
10
+
11
+ // Annotation Schema
12
+ const annotationSchema = new mongoose.Schema(
13
+ {
14
+ measurementIdentifier: {
15
+ type: String,
16
+ required: true,
17
+ trim: true,
18
+ // Examples: "PM2_5", "PM10", "NO2", "O3", etc.
19
+ },
20
+ comment: {
21
+ type: String,
22
+ required: true,
23
+ trim: true,
24
+ },
25
+ adminId: {
26
+ type: mongoose.Types.ObjectId,
27
+ ref: "Admin",
28
+ required: true,
29
+ },
30
+ timestamp: {
31
+ type: Date,
32
+ default: Date.now,
33
+ required: true,
34
+ },
35
+ },
36
+ {
37
+ _id: true,
38
+ timestamps: false,
39
+ }
40
+ );
41
+
42
+ // Add index for efficient querying
43
+ annotationSchema.index({ measurementIdentifier: 1, timestamp: -1 });
44
+
45
+ // Audit Schema
46
+ const auditSchema = mongoose.Schema(
47
+ {
48
+ monitorId: { type: mongoose.Types.ObjectId, ref: "Monitors" },
49
+ orgId: { type: mongoose.Types.ObjectId, ref: "Organizations" },
50
+ timeUpdated: Date,
51
+ deletedAt: { type: Date, default: Date.now },
52
+ measurements: Object,
53
+ monitorState: String,
54
+ monitorSupplier: String,
55
+ normalizedMeasurements: Object,
56
+ flags: Object,
57
+ appliedCorrections: {
58
+ type: Map,
59
+ of: correctionSnapshotSchema,
60
+ default: {},
61
+ },
62
+ correctedNormalizedMeasurements: Object,
63
+ annotations: [annotationSchema], // Include annotations in audit trail
64
+ },
65
+ {
66
+ timestamps: true,
67
+ }
68
+ );
69
+
70
+ const Audit = mongoose.model("Audit", auditSchema);
71
+
72
+ // Measurements Schema
73
+ const measurementsSchema = mongoose.Schema(
74
+ {
75
+ monitorId: { type: mongoose.Types.ObjectId, ref: "Monitors" },
76
+ orgId: { type: mongoose.Types.ObjectId, ref: "Organizations" },
77
+ timeUpdated: Date,
78
+ measurements: Object,
79
+ monitorState: String,
80
+ monitorSupplier: String,
81
+ normalizedMeasurements: Object,
82
+ flags: Object,
83
+ appliedCorrections: {
84
+ type: Map,
85
+ of: correctionSnapshotSchema,
86
+ default: {},
87
+ },
88
+ correctedNormalizedMeasurements: Object,
89
+ annotations: {
90
+ type: [annotationSchema],
91
+ default: [],
92
+ },
93
+ },
94
+ {
95
+ timestamps: true,
96
+ }
97
+ );
98
+
99
+ // CRITICAL: Add compound indexes for monitorId + timeUpdated
100
+ // Primary query pattern index (descending timeUpdated for latest data first)
101
+ measurementsSchema.index({ monitorId: 1, timeUpdated: -1 });
102
+ // Date range query index (ascending timeUpdated for range queries)
103
+ measurementsSchema.index({ monitorId: 1, timeUpdated: 1 });
104
+
105
+ // Flag-based query index for filtering by monitor and flags
106
+ measurementsSchema.index({ monitorId: 1, flags: 1 });
107
+
108
+ // Keep the individual indexes as they may still be useful for other queries
109
+ measurementsSchema.index({ monitorId: 1 });
110
+ measurementsSchema.index({ timeUpdated: 1 });
111
+
112
+ // Annotation-related indexes
113
+ measurementsSchema.index({
114
+ "annotations.measurementIdentifier": 1,
115
+ "annotations.timestamp": -1,
116
+ });
117
+ measurementsSchema.index({ "annotations.userId": 1 });
118
+
119
+ // Pre-hook to log single document deletions
120
+ measurementsSchema.pre("findOneAndDelete", async function () {
121
+ const docToDelete = await this.model.findOne(this.getFilter());
122
+ if (docToDelete) {
123
+ console.log("Logging findOneAndDelete to audit", docToDelete);
124
+ const auditLog = new Audit({
125
+ monitorId: docToDelete.monitorId,
126
+ orgId: docToDelete.orgId,
127
+ timeUpdated: docToDelete.timeUpdated,
128
+ measurements: docToDelete.measurements,
129
+ monitorState: docToDelete.monitorState,
130
+ monitorSupplier: docToDelete.monitorSupplier,
131
+ normalizedMeasurements: docToDelete.normalizedMeasurements,
132
+ flags: docToDelete.flags,
133
+ appliedCorrections: docToDelete.appliedCorrections,
134
+ correctedNormalizedMeasurements:
135
+ docToDelete.correctedNormalizedMeasurements,
136
+ annotations: docToDelete.annotations, // Include annotations in audit
137
+ deletedAt: new Date(),
138
+ });
139
+ await auditLog.save();
140
+ }
141
+ });
142
+
143
+ // Pre-hook to log multiple document deletions
144
+ measurementsSchema.pre("deleteMany", async function () {
145
+ console.log("deleteMany pre-hook triggered");
146
+ const docsToDelete = await this.model.find(this.getFilter()).lean();
147
+
148
+ if (docsToDelete.length) {
149
+ console.log(`Logging ${docsToDelete.length} documents to audit`);
150
+ const auditLogs = docsToDelete.map((doc) => ({
151
+ monitorId: doc.monitorId,
152
+ orgId: doc.orgId,
153
+ timeUpdated: doc.timeUpdated,
154
+ measurements: doc.measurements,
155
+ monitorState: doc.monitorState,
156
+ monitorSupplier: doc.monitorSupplier,
157
+ normalizedMeasurements: doc.normalizedMeasurements,
158
+ flags: doc.flags,
159
+ appliedCorrections: doc.appliedCorrections,
160
+ correctedNormalizedMeasurements: doc.correctedNormalizedMeasurements,
161
+ annotations: doc.annotations, // Include annotations in audit
162
+ deletedAt: new Date(),
163
+ }));
164
+
165
+ await Audit.insertMany(auditLogs);
166
+ }
167
+ });
168
+
169
+ // Pre-hook to log a single document deletion (for deleteOne)
170
+ measurementsSchema.pre("deleteOne", async function () {
171
+ console.log("deleteOne pre-hook triggered");
172
+ const docToDelete = await this.model.findOne(this.getFilter()).lean();
173
+
174
+ if (docToDelete) {
175
+ console.log("Logging deleteOne to audit", docToDelete);
176
+ const auditLog = new Audit({
177
+ monitorId: docToDelete.monitorId,
178
+ orgId: docToDelete.orgId,
179
+ timeUpdated: docToDelete.timeUpdated,
180
+ measurements: docToDelete.measurements,
181
+ monitorState: docToDelete.monitorState,
182
+ monitorSupplier: docToDelete.monitorSupplier,
183
+ normalizedMeasurements: docToDelete.normalizedMeasurements,
184
+ flags: docToDelete.flags,
185
+ appliedCorrections: docToDelete.appliedCorrections,
186
+ correctedNormalizedMeasurements:
187
+ docToDelete.correctedNormalizedMeasurements,
188
+ annotations: docToDelete.annotations, // Include annotations in audit
189
+ deletedAt: new Date(),
190
+ });
191
+ await auditLog.save();
192
+ }
193
+ });
194
+
195
+ // Pre-hook to log single document updates
196
+ measurementsSchema.pre("findOneAndUpdate", async function () {
197
+ const docToUpdate = await this.model.findOne(this.getFilter()).lean();
198
+ if (docToUpdate) {
199
+ console.log("Logging findOneAndUpdate to audit", docToUpdate);
200
+ const auditLog = new Audit({
201
+ monitorId: docToUpdate.monitorId,
202
+ orgId: docToUpdate.orgId,
203
+ timeUpdated: docToUpdate.timeUpdated,
204
+ measurements: docToUpdate.measurements,
205
+ monitorState: docToUpdate.monitorState,
206
+ monitorSupplier: docToUpdate.monitorSupplier,
207
+ normalizedMeasurements: docToUpdate.normalizedMeasurements,
208
+ flags: docToUpdate.flags,
209
+ appliedCorrections: docToUpdate.appliedCorrections,
210
+ correctedNormalizedMeasurements:
211
+ docToUpdate.correctedNormalizedMeasurements,
212
+ annotations: docToUpdate.annotations, // Include annotations in audit
213
+ deletedAt: null, // No deletion happening, so set it to null or undefined
214
+ });
215
+ await auditLog.save();
216
+ }
217
+ });
218
+
219
+ // Pre-hook to log multiple document updates
220
+ measurementsSchema.pre("updateMany", async function () {
221
+ const docsToUpdate = await this.model.find(this.getFilter()).lean();
222
+ if (docsToUpdate.length) {
223
+ console.log(`Logging ${docsToUpdate.length} documents to audit`);
224
+ const auditLogs = docsToUpdate.map((doc) => ({
225
+ monitorId: doc.monitorId,
226
+ orgId: doc.orgId,
227
+ timeUpdated: doc.timeUpdated,
228
+ measurements: doc.measurements,
229
+ monitorState: doc.monitorState,
230
+ monitorSupplier: doc.monitorSupplier,
231
+ normalizedMeasurements: doc.normalizedMeasurements,
232
+ flags: doc.flags,
233
+ appliedCorrections: doc.appliedCorrections,
234
+ correctedNormalizedMeasurements: doc.correctedNormalizedMeasurements,
235
+ annotations: doc.annotations, // Include annotations in audit
236
+ deletedAt: null, // No deletion happening
237
+ }));
238
+
239
+ await Audit.insertMany(auditLogs);
240
+ }
241
+ });
242
+
243
+ const Measurements = mongoose.model("Measurements", measurementsSchema);
244
+
245
+ export {
246
+ measurementsSchema,
247
+ Measurements,
248
+ Audit,
249
+ auditSchema,
250
+ annotationSchema,
251
+ };
@@ -1,25 +1,25 @@
1
- import mongoose from "mongoose";
2
-
3
- const monitorRequestsSchema = mongoose.Schema(
4
- {
5
- monitorOwnerOrg: { type: mongoose.Types.ObjectId, ref: "Organizations" },
6
- monitorOwnerOrgName: String,
7
- monitorReceiverOrg: { type: mongoose.Types.ObjectId, ref: "Organizations" },
8
- monitorReceiverOrgName: String,
9
- monitorList: [{ type: mongoose.Types.ObjectId, ref: "Monitors" }],
10
- status: {
11
- type: String,
12
- enum: ["Requested", "Approved", "Denied", "Cancel", "Deleted"],
13
- },
14
- },
15
- {
16
- timestamps: true,
17
- }
18
- );
19
-
20
- const MonitorRequests = mongoose.model(
21
- "MonitorRequests",
22
- monitorRequestsSchema
23
- );
24
-
25
- export { monitorRequestsSchema, MonitorRequests };
1
+ import mongoose from "mongoose";
2
+
3
+ const monitorRequestsSchema = mongoose.Schema(
4
+ {
5
+ monitorOwnerOrg: { type: mongoose.Types.ObjectId, ref: "Organizations" },
6
+ monitorOwnerOrgName: String,
7
+ monitorReceiverOrg: { type: mongoose.Types.ObjectId, ref: "Organizations" },
8
+ monitorReceiverOrgName: String,
9
+ monitorList: [{ type: mongoose.Types.ObjectId, ref: "Monitors" }],
10
+ status: {
11
+ type: String,
12
+ enum: ["Requested", "Approved", "Denied", "Cancel", "Deleted"],
13
+ },
14
+ },
15
+ {
16
+ timestamps: true,
17
+ }
18
+ );
19
+
20
+ const MonitorRequests = mongoose.model(
21
+ "MonitorRequests",
22
+ monitorRequestsSchema
23
+ );
24
+
25
+ export { monitorRequestsSchema, MonitorRequests };
@@ -1,21 +1,21 @@
1
- import mongoose from "mongoose";
2
-
3
- const monitorSuppliersSchema = mongoose.Schema(
4
- {
5
- name: String,
6
- supplierTypes: [String],
7
- authenticationStructure: [String],
8
- defaultParameterThresholds: Object,
9
- defaultCompletenessThresholdCount: Number,
10
- },
11
- {
12
- timestamps: true,
13
- }
14
- );
15
-
16
- const MonitorSuppliers = mongoose.model(
17
- "MonitorSuppliers",
18
- monitorSuppliersSchema
19
- );
20
-
21
- export { monitorSuppliersSchema, MonitorSuppliers };
1
+ import mongoose from "mongoose";
2
+
3
+ const monitorSuppliersSchema = mongoose.Schema(
4
+ {
5
+ name: String,
6
+ supplierTypes: [String],
7
+ authenticationStructure: [String],
8
+ defaultParameterThresholds: Object,
9
+ defaultCompletenessThresholdCount: Number,
10
+ },
11
+ {
12
+ timestamps: true,
13
+ }
14
+ );
15
+
16
+ const MonitorSuppliers = mongoose.model(
17
+ "MonitorSuppliers",
18
+ monitorSuppliersSchema
19
+ );
20
+
21
+ export { monitorSuppliersSchema, MonitorSuppliers };
@@ -0,0 +1,40 @@
1
+ import mongoose from "mongoose";
2
+
3
+ const parametersEnum = [
4
+ "NO2",
5
+ "SO2",
6
+ "PM2.5",
7
+ "PM10",
8
+ "Temperature",
9
+ "Humidity",
10
+ "OZONE",
11
+ "VOC",
12
+ "CO",
13
+ "NO",
14
+ "PM1",
15
+ "WS And Direction",
16
+ ];
17
+
18
+ const monitorTypeSchema = mongoose.Schema(
19
+ {
20
+ model: {
21
+ type: String,
22
+ required: true,
23
+ },
24
+
25
+ supplier: {
26
+ type: mongoose.Types.ObjectId,
27
+ required: true,
28
+ ref: "MonitorSuppliers",
29
+ },
30
+
31
+ parameters: {
32
+ type: String,
33
+ enum: parametersEnum,
34
+ required: true,
35
+ },
36
+ },
37
+ { timestamps: true }
38
+ );
39
+
40
+ const monitorType = mongoose.model("MonitorType", monitorTypeSchema);