@justair/justair-library 5.0.0-alpha.e9d14dc → 5.0.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/README.md +13 -2
- package/dist/constants/pollutants.d.ts +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/models/measurements.d.ts.map +1 -1
- package/dist/models/monitors.d.ts.map +1 -1
- package/dist/models/sampleSites.d.ts +0 -3
- package/dist/models/sampleSites.d.ts.map +1 -1
- package/dist/models/samples.d.ts.map +1 -1
- package/dist/models/sites.d.ts +3 -0
- package/dist/models/sites.d.ts.map +1 -0
- package/dist/models/tests/enums.test.d.ts +2 -0
- package/dist/models/tests/enums.test.d.ts.map +1 -0
- package/dist/models/tests/sampleSites.test.d.ts +2 -0
- package/dist/models/tests/sampleSites.test.d.ts.map +1 -0
- package/dist/models/tests/sites.test.d.ts +2 -0
- package/dist/models/tests/sites.test.d.ts.map +1 -0
- package/package.json +17 -4
- package/src/constants/pollutants.js +2 -3
- package/src/constants/tests/pollutants.test.js +12 -0
- package/src/index.js +6 -0
- package/src/models/measurements.js +0 -6
- package/src/models/monitors.js +5 -7
- package/src/models/sampleSites.js +5 -13
- package/src/models/samples.js +0 -7
- package/src/models/sites.js +55 -0
package/README.md
CHANGED
|
@@ -64,6 +64,17 @@ Use the constants-only entry point — no Mongoose dependency:
|
|
|
64
64
|
import { PARAMETERS, HEAVY_METALS } from '@justair/justair-library/constants';
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
### New sample parameters in 5.0.0
|
|
68
|
+
|
|
69
|
+
The following parameters were added to `HEAVY_METALS` and are now included in `sampleParametersEnum`. Consuming services that display or filter sample parameters (UI dropdowns, notification thresholds, reporting) should be updated to handle these values:
|
|
70
|
+
|
|
71
|
+
| id | Name |
|
|
72
|
+
|---|---|
|
|
73
|
+
| `BE` | Beryllium |
|
|
74
|
+
| `CO` | Cobalt |
|
|
75
|
+
| `MN` | Manganese |
|
|
76
|
+
| `SE` | Selenium |
|
|
77
|
+
|
|
67
78
|
### Object shape
|
|
68
79
|
|
|
69
80
|
Each constant is an object with the following fields:
|
|
@@ -92,12 +103,12 @@ For rapid local development without waiting for CI:
|
|
|
92
103
|
npm pack
|
|
93
104
|
```
|
|
94
105
|
|
|
95
|
-
This creates a `.tgz` file (e.g., `justair-justair-library-
|
|
106
|
+
This creates a `.tgz` file (e.g., `justair-justair-library-5.0.0.tgz`).
|
|
96
107
|
|
|
97
108
|
2. **Install in a consuming service:**
|
|
98
109
|
|
|
99
110
|
```bash
|
|
100
|
-
npm install /path/to/justair-library/justair-justair-library-
|
|
111
|
+
npm install /path/to/justair-library/justair-justair-library-5.0.0.tgz
|
|
101
112
|
```
|
|
102
113
|
|
|
103
114
|
Or use `npm link` for live development:
|
package/dist/index.d.ts
CHANGED
|
@@ -56,6 +56,8 @@ import { networkMetricsSchema } from "./models/networkMetrics.js";
|
|
|
56
56
|
import { NetworkMetrics } from "./models/networkMetrics.js";
|
|
57
57
|
import { rateOfChangeSchema } from "./models/rateOfChange.js";
|
|
58
58
|
import { RateOfChange } from "./models/rateOfChange.js";
|
|
59
|
+
import { sitesSchema } from "./models/sites.js";
|
|
60
|
+
import { Sites } from "./models/sites.js";
|
|
59
61
|
import { sampleSitesSchema } from "./models/sampleSites.js";
|
|
60
62
|
import { SampleSites } from "./models/sampleSites.js";
|
|
61
63
|
import { sampleSiteAuditSchema } from "./models/sampleSites.js";
|
|
@@ -68,5 +70,5 @@ import { SamplesAudit } from "./models/samples.js";
|
|
|
68
70
|
import { sampleParameterReferenceConcentrations } from "./models/samples.js";
|
|
69
71
|
import { PARAMETERS } from "./constants/pollutants.js";
|
|
70
72
|
import { HEAVY_METALS } from "./constants/pollutants.js";
|
|
71
|
-
export { Database, adminSchema, Admin, configurationsSchema, Configurations, measurementsSchema, Measurements, monitorRequestsSchema, MonitorRequests, monitorsSchema, Monitors, organizationsSchema, Organizations, usersSchema, Users, eventsSchema, Events, lightMonitorSchema, LightMonitors, monitorSuppliersSchema, MonitorSuppliers, contextsSchema, Contexts, parametersSchema, Parameters, announcementSchema, Announcements, jobsSchema, Jobs, apiKeySchema, ApiKey, UsageMetrics, usageMetricsSchema, Audit, auditSchema, EventsAudit, eventsAuditSchema, MonitorAudit, monitorAuditSchema, parametersEnum, deploymentTypesEnum, AlertsAudit, Alerts, alertsSchema, alertsAuditSchema, Features, featuresSchema, dataCompletenessSchema, DataCompleteness, networkMetricsSchema, NetworkMetrics, rateOfChangeSchema, RateOfChange, sampleSitesSchema, SampleSites, sampleSiteAuditSchema, SampleSiteAudit, sampleParametersEnum, samplesSchema, Samples, samplesAuditSchema, SamplesAudit, sampleParameterReferenceConcentrations, PARAMETERS, HEAVY_METALS };
|
|
73
|
+
export { Database, adminSchema, Admin, configurationsSchema, Configurations, measurementsSchema, Measurements, monitorRequestsSchema, MonitorRequests, monitorsSchema, Monitors, organizationsSchema, Organizations, usersSchema, Users, eventsSchema, Events, lightMonitorSchema, LightMonitors, monitorSuppliersSchema, MonitorSuppliers, contextsSchema, Contexts, parametersSchema, Parameters, announcementSchema, Announcements, jobsSchema, Jobs, apiKeySchema, ApiKey, UsageMetrics, usageMetricsSchema, Audit, auditSchema, EventsAudit, eventsAuditSchema, MonitorAudit, monitorAuditSchema, parametersEnum, deploymentTypesEnum, AlertsAudit, Alerts, alertsSchema, alertsAuditSchema, Features, featuresSchema, dataCompletenessSchema, DataCompleteness, networkMetricsSchema, NetworkMetrics, rateOfChangeSchema, RateOfChange, sitesSchema, Sites, sampleSitesSchema, SampleSites, sampleSiteAuditSchema, SampleSiteAudit, sampleParametersEnum, samplesSchema, Samples, samplesAuditSchema, SamplesAudit, sampleParameterReferenceConcentrations, PARAMETERS, HEAVY_METALS };
|
|
72
74
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"AAgFA;;;iBAEC;yBA1BwB,oBAAoB;qBADxB,gBAAgB;4BAvDF,mBAAmB;sBAAnB,mBAAmB;qCAI/C,4BAA4B;+BAA5B,4BAA4B;mCAM5B,0BAA0B;6BAA1B,0BAA0B;sCAI1B,6BAA6B;gCAA7B,6BAA6B;+BAQ7B,sBAAsB;yBAAtB,sBAAsB;oCACsB,2BAA2B;8BAA3B,2BAA2B;4BAQ3C,mBAAmB;sBAAnB,mBAAmB;6BAM/C,oBAAoB;uBAApB,oBAAoB;mCAbuB,2BAA2B;8BAA3B,2BAA2B;uCAItE,8BAA8B;iCAA9B,8BAA8B;+BACI,sBAAsB;yBAAtB,sBAAsB;iCAClB,wBAAwB;2BAAxB,wBAAwB;mCAQnB,2BAA2B;8BAA3B,2BAA2B;2BAC5C,kBAAkB;qBAAlB,kBAAkB;6BACd,oBAAoB;uBAApB,oBAAoB;6BACR,0BAA0B;mCAA1B,0BAA0B;sBA/BpE,0BAA0B;4BAA1B,0BAA0B;4BA2B1B,oBAAoB;kCAApB,oBAAoB;6BAfpB,sBAAsB;mCAAtB,sBAAsB;+BAAtB,sBAAsB;oCAAtB,sBAAsB;4BAyBtB,oBAAoB;uBAApB,oBAAoB;6BAApB,oBAAoB;kCAApB,oBAAoB;yBACc,sBAAsB;+BAAtB,sBAAsB;uCAIxD,8BAA8B;iCAA9B,8BAA8B;qCACgB,4BAA4B;+BAA5B,4BAA4B;mCAChC,0BAA0B;6BAA1B,0BAA0B;4BAMxC,mBAAmB;sBAAnB,mBAAmB;kCAS/C,yBAAyB;4BAAzB,yBAAyB;sCAAzB,yBAAyB;gCAAzB,yBAAyB;qCAAzB,yBAAyB;8BASzB,qBAAqB;wBAArB,qBAAqB;mCAArB,qBAAqB;6BAArB,qBAAqB;uDAArB,qBAAqB;2BArBa,2BAA2B;6BAA3B,2BAA2B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"measurements.d.ts","sourceRoot":"","sources":["../../src/models/measurements.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"measurements.d.ts","sourceRoot":"","sources":["../../src/models/measurements.js"],"names":[],"mappings":"AA8FA,qCA0BE;AA2IF,+BAAwE;AAxKxE,wBAAmD;AAzBnD,8BAuBE;AAjEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCE;qBA5DmB,UAAU"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitors.d.ts","sourceRoot":"","sources":["../../src/models/monitors.js"],"names":[],"mappings":"AA6JA,
|
|
1
|
+
{"version":3,"file":"monitors.d.ts","sourceRoot":"","sources":["../../src/models/monitors.js"],"names":[],"mappings":"AA6JA,iCA8HE;AAuIF,2BAA4D;AAvS5D,qCA4BE;AAGF,+BAAwE;AAvJxE,sCAAoD"}
|
|
@@ -3,7 +3,4 @@ export const SampleSites: any;
|
|
|
3
3
|
export const sampleSiteAuditSchema: any;
|
|
4
4
|
export const SampleSiteAudit: any;
|
|
5
5
|
export const sampleParametersEnum: string[];
|
|
6
|
-
export const sampleParameterReferenceConcentrations: {
|
|
7
|
-
[k: string]: any;
|
|
8
|
-
};
|
|
9
6
|
//# sourceMappingURL=sampleSites.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sampleSites.d.ts","sourceRoot":"","sources":["../../src/models/sampleSites.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sampleSites.d.ts","sourceRoot":"","sources":["../../src/models/sampleSites.js"],"names":[],"mappings":"AAsDA,oCAuDE;AAqJF,8BAAqE;AAlOrE,wCAgBE;AAGF,kCAAiF;AA7CjF,4CAAuD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"samples.d.ts","sourceRoot":"","sources":["../../src/models/samples.js"],"names":[],"mappings":"AAoCA,gCAkBE;
|
|
1
|
+
{"version":3,"file":"samples.d.ts","sourceRoot":"","sources":["../../src/models/samples.js"],"names":[],"mappings":"AAoCA,gCAkBE;AA6HF,0BAAyD;AAlJzD,+BAAwE;AAvBxE,qCAoBE;AAzBF;;EAEE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sites.d.ts","sourceRoot":"","sources":["../../src/models/sites.js"],"names":[],"mappings":"AAGA,8BAoCE;AAaF,wBAAmD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enums.test.d.ts","sourceRoot":"","sources":["../../../src/models/tests/enums.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sampleSites.test.d.ts","sourceRoot":"","sources":["../../../src/models/tests/sampleSites.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sites.test.d.ts","sourceRoot":"","sources":["../../../src/models/tests/sites.test.js"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@justair/justair-library",
|
|
3
|
-
"version": "5.0.0
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "JustAir Internal Library",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
|
-
".":
|
|
10
|
-
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./src/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./constants": {
|
|
14
|
+
"types": "./dist/constants/pollutants.d.ts",
|
|
15
|
+
"default": "./src/constants/pollutants.js"
|
|
16
|
+
}
|
|
11
17
|
},
|
|
12
18
|
"scripts": {
|
|
13
|
-
"test": "
|
|
19
|
+
"test": "node --experimental-vm-modules node_modules/.bin/jest",
|
|
14
20
|
"build": "tsc",
|
|
15
21
|
"prepublish": "npm run build"
|
|
16
22
|
},
|
|
@@ -24,8 +30,15 @@
|
|
|
24
30
|
"nanoid": "^5.1.6",
|
|
25
31
|
"winston": "^3.10.0"
|
|
26
32
|
},
|
|
33
|
+
"jest": {
|
|
34
|
+
"testEnvironment": "node",
|
|
35
|
+
"transform": {}
|
|
36
|
+
},
|
|
27
37
|
"devDependencies": {
|
|
38
|
+
"@jest/globals": "^29",
|
|
28
39
|
"@types/node": "^16.0.0",
|
|
40
|
+
"jest": "^29",
|
|
41
|
+
"jest-environment-node": "^29",
|
|
29
42
|
"ts-node": "^10.0.0",
|
|
30
43
|
"typescript": "^5.3.2"
|
|
31
44
|
}
|
|
@@ -41,8 +41,8 @@ export const PARAMETERS = {
|
|
|
41
41
|
origin: null,
|
|
42
42
|
impacts: null,
|
|
43
43
|
},
|
|
44
|
-
|
|
45
|
-
id: "
|
|
44
|
+
BRC: {
|
|
45
|
+
id: "BRC",
|
|
46
46
|
label: "Brown Carbon",
|
|
47
47
|
name: "Total Brown Carbon (BrC)",
|
|
48
48
|
unit: "ng/m³",
|
|
@@ -205,7 +205,6 @@ export const PARAMETERS = {
|
|
|
205
205
|
|
|
206
206
|
// Parameters analyzed from physical air samples in a laboratory.
|
|
207
207
|
// These correspond to SampleSites.parameters and are not measured by real-time sensors.
|
|
208
|
-
// Note: CO here is Cobalt, not Carbon Monoxide — see PARAMETERS.CO for Carbon Monoxide.
|
|
209
208
|
export const HEAVY_METALS = {
|
|
210
209
|
C6H6: {
|
|
211
210
|
id: "C6H6",
|
|
@@ -57,6 +57,14 @@ function sharedAssertions(constants) {
|
|
|
57
57
|
test.each(entries)("%s: rfc is a number or null", (key, pollutant) => {
|
|
58
58
|
expect(pollutant.rfc === null || typeof pollutant.rfc === "number").toBe(true);
|
|
59
59
|
});
|
|
60
|
+
|
|
61
|
+
test.each(entries)("%s: origin is a string or null", (key, pollutant) => {
|
|
62
|
+
expect(pollutant.origin === null || typeof pollutant.origin === "string").toBe(true);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test.each(entries)("%s: impacts is a string or null", (key, pollutant) => {
|
|
66
|
+
expect(pollutant.impacts === null || typeof pollutant.impacts === "string").toBe(true);
|
|
67
|
+
});
|
|
60
68
|
}
|
|
61
69
|
|
|
62
70
|
describe("PARAMETERS", () => {
|
|
@@ -65,4 +73,8 @@ describe("PARAMETERS", () => {
|
|
|
65
73
|
|
|
66
74
|
describe("HEAVY_METALS", () => {
|
|
67
75
|
sharedAssertions(HEAVY_METALS);
|
|
76
|
+
|
|
77
|
+
test("PB.rfc is exactly 0, not null", () => {
|
|
78
|
+
expect(HEAVY_METALS.PB.rfc).toBe(0);
|
|
79
|
+
});
|
|
68
80
|
});
|
package/src/index.js
CHANGED
|
@@ -57,6 +57,9 @@ import Database from "./config/db.js"; // Import the new Database class
|
|
|
57
57
|
import CustomLogger from "./config/logger.js";
|
|
58
58
|
import { PARAMETERS, HEAVY_METALS } from "./constants/pollutants.js";
|
|
59
59
|
|
|
60
|
+
// Sites related imports
|
|
61
|
+
import { sitesSchema, Sites } from "./models/sites.js";
|
|
62
|
+
|
|
60
63
|
// SampleSites related imports
|
|
61
64
|
import {
|
|
62
65
|
sampleSitesSchema,
|
|
@@ -133,6 +136,9 @@ export {
|
|
|
133
136
|
NetworkMetrics,
|
|
134
137
|
rateOfChangeSchema,
|
|
135
138
|
RateOfChange,
|
|
139
|
+
// Sites related exports
|
|
140
|
+
sitesSchema,
|
|
141
|
+
Sites,
|
|
136
142
|
// SampleSites related exports
|
|
137
143
|
sampleSitesSchema,
|
|
138
144
|
SampleSites,
|
|
@@ -83,7 +83,6 @@ const auditSchema = mongoose.Schema(
|
|
|
83
83
|
},
|
|
84
84
|
annotations: [annotationSchema], // Include annotations in audit trail
|
|
85
85
|
isCorrected: { type: Boolean },
|
|
86
|
-
isFog: { type: Boolean },
|
|
87
86
|
},
|
|
88
87
|
{
|
|
89
88
|
timestamps: true,
|
|
@@ -139,7 +138,6 @@ measurementsSchema.index({ "annotations.userId": 1 });
|
|
|
139
138
|
measurementsSchema.pre("findOneAndDelete", async function () {
|
|
140
139
|
const docToDelete = await this.model.findOne(this.getFilter());
|
|
141
140
|
if (docToDelete) {
|
|
142
|
-
console.log("Logging findOneAndDelete to audit", docToDelete);
|
|
143
141
|
const auditLog = new Audit({
|
|
144
142
|
monitorId: docToDelete.monitorId,
|
|
145
143
|
orgId: docToDelete.orgId,
|
|
@@ -190,11 +188,9 @@ measurementsSchema.pre("deleteMany", async function () {
|
|
|
190
188
|
|
|
191
189
|
// Pre-hook to log a single document deletion (for deleteOne)
|
|
192
190
|
measurementsSchema.pre("deleteOne", async function () {
|
|
193
|
-
console.log("deleteOne pre-hook triggered");
|
|
194
191
|
const docToDelete = await this.model.findOne(this.getFilter()).lean();
|
|
195
192
|
|
|
196
193
|
if (docToDelete) {
|
|
197
|
-
console.log("Logging deleteOne to audit", docToDelete);
|
|
198
194
|
const auditLog = new Audit({
|
|
199
195
|
monitorId: docToDelete.monitorId,
|
|
200
196
|
orgId: docToDelete.orgId,
|
|
@@ -218,7 +214,6 @@ measurementsSchema.pre("deleteOne", async function () {
|
|
|
218
214
|
measurementsSchema.pre("findOneAndUpdate", async function () {
|
|
219
215
|
const docToUpdate = await this.model.findOne(this.getFilter()).lean();
|
|
220
216
|
if (docToUpdate) {
|
|
221
|
-
console.log("Logging findOneAndUpdate to audit", docToUpdate);
|
|
222
217
|
const auditLog = new Audit({
|
|
223
218
|
monitorId: docToUpdate.monitorId,
|
|
224
219
|
orgId: docToUpdate.orgId,
|
|
@@ -242,7 +237,6 @@ measurementsSchema.pre("findOneAndUpdate", async function () {
|
|
|
242
237
|
measurementsSchema.pre("updateMany", async function () {
|
|
243
238
|
const docsToUpdate = await this.model.find(this.getFilter()).lean();
|
|
244
239
|
if (docsToUpdate.length) {
|
|
245
|
-
console.log(`Logging ${docsToUpdate.length} documents to audit`);
|
|
246
240
|
const auditLogs = docsToUpdate.map((doc) => ({
|
|
247
241
|
monitorId: doc.monitorId,
|
|
248
242
|
orgId: doc.orgId,
|
package/src/models/monitors.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import mongoose from "mongoose";
|
|
2
2
|
import { PARAMETERS } from "../constants/pollutants.js";
|
|
3
3
|
|
|
4
|
-
const parametersEnum = Object.keys(PARAMETERS);
|
|
4
|
+
const parametersEnum = [...Object.keys(PARAMETERS)];
|
|
5
5
|
|
|
6
6
|
const deploymentTypesEnum = {
|
|
7
7
|
STATIONARY: "stationary",
|
|
@@ -269,6 +269,10 @@ const monitorsSchema = mongoose.Schema(
|
|
|
269
269
|
enum: Object.values(deploymentTypesEnum),
|
|
270
270
|
default: deploymentTypesEnum.STATIONARY,
|
|
271
271
|
},
|
|
272
|
+
siteId: {
|
|
273
|
+
type: mongoose.Types.ObjectId,
|
|
274
|
+
ref: "Sites",
|
|
275
|
+
},
|
|
272
276
|
// Optional Clarity node ID (1:1 relationship with Node-S sensor)
|
|
273
277
|
nodeId: { type: String },
|
|
274
278
|
// Active alarms from Clarity node (keyed by alarmType)
|
|
@@ -305,7 +309,6 @@ monitorsSchema.index({ deploymentType: 1 });
|
|
|
305
309
|
monitorsSchema.pre("findOneAndDelete", async function () {
|
|
306
310
|
const docToDelete = await this.model.findOne(this.getFilter()).lean();
|
|
307
311
|
if (docToDelete) {
|
|
308
|
-
console.log("Logging findOneAndDelete to monitor audit", docToDelete);
|
|
309
312
|
const auditLog = new MonitorAudit({
|
|
310
313
|
monitorId: docToDelete._id,
|
|
311
314
|
orgId: docToDelete.sponsor,
|
|
@@ -332,11 +335,9 @@ monitorsSchema.pre("findOneAndDelete", async function () {
|
|
|
332
335
|
|
|
333
336
|
// Pre-hook to log multiple document deletions
|
|
334
337
|
monitorsSchema.pre("deleteMany", async function () {
|
|
335
|
-
console.log("deleteMany pre-hook triggered for monitors");
|
|
336
338
|
const docsToDelete = await this.model.find(this.getFilter()).lean();
|
|
337
339
|
|
|
338
340
|
if (docsToDelete.length) {
|
|
339
|
-
console.log(`Logging ${docsToDelete.length} monitor documents to audit`);
|
|
340
341
|
const auditLogs = docsToDelete.map((doc) => ({
|
|
341
342
|
monitorId: doc._id,
|
|
342
343
|
orgId: doc.sponsor,
|
|
@@ -361,11 +362,9 @@ monitorsSchema.pre("deleteMany", async function () {
|
|
|
361
362
|
|
|
362
363
|
// Pre-hook to log a single document deletion (for deleteOne)
|
|
363
364
|
monitorsSchema.pre("deleteOne", async function () {
|
|
364
|
-
console.log("deleteOne pre-hook triggered for monitors");
|
|
365
365
|
const docToDelete = await this.model.findOne(this.getFilter()).lean();
|
|
366
366
|
|
|
367
367
|
if (docToDelete) {
|
|
368
|
-
console.log("Logging deleteOne to monitor audit", docToDelete);
|
|
369
368
|
const auditLog = new MonitorAudit({
|
|
370
369
|
monitorId: docToDelete._id,
|
|
371
370
|
orgId: docToDelete.sponsor,
|
|
@@ -394,7 +393,6 @@ monitorsSchema.pre("deleteOne", async function () {
|
|
|
394
393
|
monitorsSchema.pre("updateMany", async function () {
|
|
395
394
|
const docsToUpdate = await this.model.find(this.getFilter()).lean();
|
|
396
395
|
if (docsToUpdate.length) {
|
|
397
|
-
console.log(`Logging ${docsToUpdate.length} monitor documents to audit`);
|
|
398
396
|
const auditLogs = docsToUpdate.map((doc) => ({
|
|
399
397
|
monitorId: doc._id,
|
|
400
398
|
orgId: doc.sponsor,
|
|
@@ -6,12 +6,6 @@ const generateSiteCode = customAlphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 8);
|
|
|
6
6
|
|
|
7
7
|
const sampleParametersEnum = Object.keys(HEAVY_METALS);
|
|
8
8
|
|
|
9
|
-
// EPA IRIS chronic inhalation reference concentrations (µg/m³)
|
|
10
|
-
// null = no established inhalation RfC
|
|
11
|
-
const sampleParameterReferenceConcentrations = Object.fromEntries(
|
|
12
|
-
Object.entries(HEAVY_METALS).map(([key, p]) => [key, p.rfc])
|
|
13
|
-
);
|
|
14
|
-
|
|
15
9
|
const noteSchema = mongoose.Schema({
|
|
16
10
|
note: {
|
|
17
11
|
type: String,
|
|
@@ -105,6 +99,10 @@ const sampleSitesSchema = mongoose.Schema(
|
|
|
105
99
|
],
|
|
106
100
|
notes: { type: [noteSchema] },
|
|
107
101
|
image: { type: String },
|
|
102
|
+
siteId: {
|
|
103
|
+
type: mongoose.Types.ObjectId,
|
|
104
|
+
ref: "Sites",
|
|
105
|
+
},
|
|
108
106
|
},
|
|
109
107
|
{
|
|
110
108
|
timestamps: true,
|
|
@@ -139,7 +137,6 @@ sampleSitesSchema.index({ parameters: 1 });
|
|
|
139
137
|
sampleSitesSchema.pre("findOneAndDelete", async function () {
|
|
140
138
|
const docToDelete = await this.model.findOne(this.getFilter()).lean();
|
|
141
139
|
if (docToDelete) {
|
|
142
|
-
console.log("Logging findOneAndDelete to sample site audit", docToDelete);
|
|
143
140
|
let coordinates = null;
|
|
144
141
|
if (docToDelete.location && docToDelete.location.gps && Array.isArray(docToDelete.location.gps.coordinates)) {
|
|
145
142
|
coordinates = docToDelete.location.gps.coordinates;
|
|
@@ -165,11 +162,9 @@ sampleSitesSchema.pre("findOneAndDelete", async function () {
|
|
|
165
162
|
|
|
166
163
|
// Pre-hook to log multiple document deletions
|
|
167
164
|
sampleSitesSchema.pre("deleteMany", async function () {
|
|
168
|
-
console.log("deleteMany pre-hook triggered for sample sites");
|
|
169
165
|
const docsToDelete = await this.model.find(this.getFilter()).lean();
|
|
170
166
|
|
|
171
167
|
if (docsToDelete.length) {
|
|
172
|
-
console.log(`Logging ${docsToDelete.length} sample site documents to audit`);
|
|
173
168
|
const auditLogs = docsToDelete.map((doc) => {
|
|
174
169
|
let coordinates = null;
|
|
175
170
|
if (doc.location && doc.location.gps && Array.isArray(doc.location.gps.coordinates)) {
|
|
@@ -201,11 +196,9 @@ sampleSitesSchema.pre("deleteMany", async function () {
|
|
|
201
196
|
|
|
202
197
|
// Pre-hook to log a single document deletion (for deleteOne)
|
|
203
198
|
sampleSitesSchema.pre("deleteOne", async function () {
|
|
204
|
-
console.log("deleteOne pre-hook triggered for sample sites");
|
|
205
199
|
const docToDelete = await this.model.findOne(this.getFilter()).lean();
|
|
206
200
|
|
|
207
201
|
if (docToDelete) {
|
|
208
|
-
console.log("Logging deleteOne to sample site audit", docToDelete);
|
|
209
202
|
let coordinates = null;
|
|
210
203
|
if (docToDelete.location && docToDelete.location.gps && Array.isArray(docToDelete.location.gps.coordinates)) {
|
|
211
204
|
coordinates = docToDelete.location.gps.coordinates;
|
|
@@ -233,7 +226,6 @@ sampleSitesSchema.pre("deleteOne", async function () {
|
|
|
233
226
|
sampleSitesSchema.pre("updateMany", async function () {
|
|
234
227
|
const docsToUpdate = await this.model.find(this.getFilter()).lean();
|
|
235
228
|
if (docsToUpdate.length) {
|
|
236
|
-
console.log(`Logging ${docsToUpdate.length} sample site documents to audit`);
|
|
237
229
|
const auditLogs = docsToUpdate.map((doc) => {
|
|
238
230
|
let coordinates = null;
|
|
239
231
|
if (doc.location && doc.location.gps && Array.isArray(doc.location.gps.coordinates)) {
|
|
@@ -266,4 +258,4 @@ sampleSitesSchema.pre("updateMany", async function () {
|
|
|
266
258
|
// Create the SampleSites model
|
|
267
259
|
const SampleSites = mongoose.model("SampleSites", sampleSitesSchema);
|
|
268
260
|
|
|
269
|
-
export { sampleSitesSchema, SampleSites, sampleSiteAuditSchema, SampleSiteAudit, sampleParametersEnum
|
|
261
|
+
export { sampleSitesSchema, SampleSites, sampleSiteAuditSchema, SampleSiteAudit, sampleParametersEnum };
|
package/src/models/samples.js
CHANGED
|
@@ -65,7 +65,6 @@ samplesSchema.index({ siteId: 1, uploadDate: -1 });
|
|
|
65
65
|
samplesSchema.pre("findOneAndDelete", async function () {
|
|
66
66
|
const docToDelete = await this.model.findOne(this.getFilter()).lean();
|
|
67
67
|
if (docToDelete) {
|
|
68
|
-
console.log("Logging findOneAndDelete to audit", docToDelete);
|
|
69
68
|
const auditLog = new SamplesAudit({
|
|
70
69
|
siteId: docToDelete.siteId,
|
|
71
70
|
orgId: docToDelete.orgId,
|
|
@@ -87,10 +86,8 @@ samplesSchema.pre("findOneAndDelete", async function () {
|
|
|
87
86
|
|
|
88
87
|
// Pre-hook to log multiple document deletions
|
|
89
88
|
samplesSchema.pre("deleteMany", async function () {
|
|
90
|
-
console.log("deleteMany pre-hook triggered");
|
|
91
89
|
const docsToDelete = await this.model.find(this.getFilter()).lean();
|
|
92
90
|
if (docsToDelete.length) {
|
|
93
|
-
console.log(`Logging ${docsToDelete.length} documents to audit`);
|
|
94
91
|
const auditLogs = docsToDelete.map((doc) => ({
|
|
95
92
|
siteId: doc.siteId,
|
|
96
93
|
orgId: doc.orgId,
|
|
@@ -112,10 +109,8 @@ samplesSchema.pre("deleteMany", async function () {
|
|
|
112
109
|
|
|
113
110
|
// Pre-hook to log a single document deletion (for deleteOne)
|
|
114
111
|
samplesSchema.pre("deleteOne", async function () {
|
|
115
|
-
console.log("deleteOne pre-hook triggered");
|
|
116
112
|
const docToDelete = await this.model.findOne(this.getFilter()).lean();
|
|
117
113
|
if (docToDelete) {
|
|
118
|
-
console.log("Logging deleteOne to audit", docToDelete);
|
|
119
114
|
const auditLog = new SamplesAudit({
|
|
120
115
|
siteId: docToDelete.siteId,
|
|
121
116
|
orgId: docToDelete.orgId,
|
|
@@ -139,7 +134,6 @@ samplesSchema.pre("deleteOne", async function () {
|
|
|
139
134
|
samplesSchema.pre("findOneAndUpdate", async function () {
|
|
140
135
|
const docToUpdate = await this.model.findOne(this.getFilter()).lean();
|
|
141
136
|
if (docToUpdate) {
|
|
142
|
-
console.log("Logging findOneAndUpdate to audit", docToUpdate);
|
|
143
137
|
const auditLog = new SamplesAudit({
|
|
144
138
|
siteId: docToUpdate.siteId,
|
|
145
139
|
orgId: docToUpdate.orgId,
|
|
@@ -163,7 +157,6 @@ samplesSchema.pre("findOneAndUpdate", async function () {
|
|
|
163
157
|
samplesSchema.pre("updateMany", async function () {
|
|
164
158
|
const docsToUpdate = await this.model.find(this.getFilter()).lean();
|
|
165
159
|
if (docsToUpdate.length) {
|
|
166
|
-
console.log(`Logging ${docsToUpdate.length} documents to audit`);
|
|
167
160
|
const auditLogs = docsToUpdate.map((doc) => ({
|
|
168
161
|
siteId: doc.siteId,
|
|
169
162
|
orgId: doc.orgId,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
|
|
3
|
+
// Sites Schema
|
|
4
|
+
const sitesSchema = mongoose.Schema(
|
|
5
|
+
{
|
|
6
|
+
name: { type: String },
|
|
7
|
+
sampleSiteId: {
|
|
8
|
+
type: mongoose.Types.ObjectId,
|
|
9
|
+
ref: "SampleSites",
|
|
10
|
+
},
|
|
11
|
+
monitorIds: {
|
|
12
|
+
type: [{ type: mongoose.Types.ObjectId, ref: "Monitors" }],
|
|
13
|
+
default: undefined,
|
|
14
|
+
},
|
|
15
|
+
sponsor: { type: mongoose.Types.ObjectId, ref: "Organizations" },
|
|
16
|
+
location: {
|
|
17
|
+
city: { type: String },
|
|
18
|
+
state: { type: String },
|
|
19
|
+
county: { type: String },
|
|
20
|
+
street: { type: String },
|
|
21
|
+
zip_code: { type: String },
|
|
22
|
+
neighborhood: { type: String },
|
|
23
|
+
gps: {
|
|
24
|
+
type: {
|
|
25
|
+
type: String,
|
|
26
|
+
enum: ["Point"],
|
|
27
|
+
required: true,
|
|
28
|
+
},
|
|
29
|
+
coordinates: {
|
|
30
|
+
type: [Number],
|
|
31
|
+
required: true,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
isActive: { type: Boolean, default: true },
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
timestamps: true,
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// Geographic queries
|
|
43
|
+
sitesSchema.index({ "location.gps": "2dsphere" });
|
|
44
|
+
|
|
45
|
+
// Sponsor-based queries
|
|
46
|
+
sitesSchema.index({ sponsor: 1, isActive: 1 });
|
|
47
|
+
|
|
48
|
+
// Back-reference lookups
|
|
49
|
+
sitesSchema.index({ sampleSiteId: 1 });
|
|
50
|
+
sitesSchema.index({ monitorIds: 1 });
|
|
51
|
+
|
|
52
|
+
// Create the Sites model
|
|
53
|
+
const Sites = mongoose.model("Sites", sitesSchema);
|
|
54
|
+
|
|
55
|
+
export { sitesSchema, Sites };
|