@justair/justair-library 4.7.21 → 4.7.22

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