@openinc/parse-server-opendash 4.0.22 → 4.0.24

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.
@@ -43,6 +43,8 @@ const cron_1 = require("cron");
43
43
  const index_js_1 = require("../features/openware/index.js");
44
44
  const index_js_2 = require("../features/schema/index.js");
45
45
  const index_js_3 = require("../types/index.js");
46
+ // Tolerance for client/server clock skew when comparing `start` against `now`.
47
+ const CLOCK_SKEW_MS = 60_000;
46
48
  const excludeFields = [
47
49
  "ACL",
48
50
  "updatedAt",
@@ -80,8 +82,6 @@ async function init() {
80
82
  const { object, original, user } = request;
81
83
  if (!object.id)
82
84
  return;
83
- // Non-sync client & Server times. ALlow 1 minute difference
84
- const nowThresholded = Date.now() - 60_000;
85
85
  await (0, index_js_2.defaultHandler)(request);
86
86
  await (0, index_js_2.defaultAclHandler)(request, {
87
87
  allowCustomACL: true,
@@ -106,27 +106,28 @@ async function init() {
106
106
  : article?.get("targettime") || 0);
107
107
  }
108
108
  }
109
- // If the order is started and has a source, it is running
110
- if (object.get("start") &&
111
- object.get("start").getTime() < Date.now() + 60_000 &&
112
- object.get("source") &&
113
- !object.get("status")) {
114
- object.set("status", "running");
115
- }
116
- if (object.get("start") &&
117
- object.get("start").getTime() > Date.now() &&
118
- object.get("source") &&
119
- !object.get("status")) {
120
- object.set("status", "planned");
121
- }
122
- // If the order is started and has no source, it is unknown
123
- if (object.get("start") &&
124
- object.get("start").getTime() < nowThresholded &&
125
- !object.get("source")) {
126
- object.set("status", "unknown");
109
+ // Re-evaluate status. Terminal states (done/canceled) are preserved; any
110
+ // other status — including "unknown" — is recomputed so orders can heal
111
+ // when source/tag arrive on a later save. Clock skew is tolerated in both
112
+ // directions: starts up to CLOCK_SKEW_MS in the future count as "started",
113
+ // and a missing source only produces "unknown" once `start` has clearly
114
+ // passed.
115
+ const currentStatus = object.get("status");
116
+ const start = object.get("start");
117
+ const hasSource = !!object.get("source");
118
+ if (currentStatus !== "done" && currentStatus !== "canceled" && start) {
119
+ const startMs = start.getTime();
120
+ const nowMs = Date.now();
121
+ if (hasSource) {
122
+ object.set("status", startMs < nowMs + CLOCK_SKEW_MS ? "running" : "planned");
123
+ }
124
+ else if (startMs < nowMs - CLOCK_SKEW_MS) {
125
+ console.log("[MES] - beforeSaveHook: Setting status to unknown for order " + object.id + " due to missing source and order running for more than a minute.");
126
+ object.set("status", "unknown");
127
+ }
127
128
  }
128
129
  // If the order has been started and ended, it is done
129
- if (object.get("start") &&
130
+ if (start &&
130
131
  object.get("duration") &&
131
132
  (object.get("status") === "running" || object.get("status") === "planned")) {
132
133
  object.set("status", "done");
@@ -182,6 +183,7 @@ async function init() {
182
183
  runningData.name = "Order_Running";
183
184
  console.log("-".repeat(20));
184
185
  console.log("Publishing running order " + object.id);
186
+ console.log("Data:", runningData);
185
187
  console.log("-".repeat(20));
186
188
  await (0, index_js_1.publishDataItem)(runningData, user?.getEmail() || undefined, true);
187
189
  }
@@ -303,6 +305,7 @@ async function createValueArrayForObject(object, extraValues, fields) {
303
305
  }
304
306
  values.push(value);
305
307
  }
308
+ console.log("[MES] - createValueArrayForObject: Created values object for order " + object.id + ": ", values);
306
309
  return [{ date: object.get("start").getTime(), value: values }];
307
310
  }
308
311
  function scheduleOrderStartedStatusCheck(cronInterval) {
@@ -315,29 +318,26 @@ function scheduleOrderStartedStatusCheck(cronInterval) {
315
318
  query.find({ useMasterKey: true }).then((orders) => {
316
319
  orders.forEach((order) => {
317
320
  const status = order.get("status");
318
- if (!status) {
319
- if (order.get("tag")) {
320
- if (order.get("start").getTime() < Date.now()) {
321
- order.set("status", "running");
322
- order.save(null, { useMasterKey: true });
323
- }
324
- else {
325
- order.set("status", "planned");
326
- order.save(null, { useMasterKey: true });
327
- }
328
- }
329
- else {
330
- order.set("status", "unknown");
331
- order.save(null, { useMasterKey: true });
332
- }
321
+ if (status === "done" || status === "canceled")
322
+ return;
323
+ const startMs = order.get("start").getTime();
324
+ const nowMs = Date.now();
325
+ const hasStarted = startMs < nowMs + CLOCK_SKEW_MS;
326
+ const hasTag = !!order.get("tag");
327
+ let next;
328
+ if (hasTag) {
329
+ next = hasStarted ? "running" : "planned";
330
+ }
331
+ else if (startMs < nowMs - CLOCK_SKEW_MS) {
332
+ next = "unknown";
333
+ console.log("[MES] - orderStartedStatusCheck: Setting status to unknown for order " + order.id + " due to missing source and order running for more than a minute.");
334
+ }
335
+ else if (!status) {
336
+ next = "planned";
333
337
  }
334
- else {
335
- if (status === "unknown" || status === "planned") {
336
- if (order.get("start").getTime() < Date.now()) {
337
- order.set("status", "running");
338
- order.save(null, { useMasterKey: true });
339
- }
340
- }
338
+ if (next && next !== status) {
339
+ order.set("status", next);
340
+ order.save(null, { useMasterKey: true });
341
341
  }
342
342
  });
343
343
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openinc/parse-server-opendash",
3
- "version": "4.0.22",
3
+ "version": "4.0.24",
4
4
  "description": "Parse Server Cloud Code for open.INC Stack.",
5
5
  "packageManager": "pnpm@10.33.0",
6
6
  "keywords": [
@@ -41,7 +41,7 @@
41
41
  "path": "@semantic-release/git",
42
42
  "assets": [
43
43
  "package.json",
44
- "pnpm-lock.json",
44
+ "pnpm-lock.yaml",
45
45
  "CHANGELOG.md"
46
46
  ],
47
47
  "message": "chore(release): Release ${nextRelease.version} \n\n${nextRelease.notes}"
@@ -66,34 +66,26 @@
66
66
  "docker:rebuild": "cd ./docker-dev && powershell -NoProfile -ExecutionPolicy Bypass -File rebuild_and_restart.ps1"
67
67
  },
68
68
  "dependencies": {
69
- "@openinc/parse-server-schema": "^4.1.0",
69
+ "@openinc/parse-server-schema": "^4.1.1",
70
70
  "amqplib": "^0.10.9",
71
71
  "cron": "^4.4.0",
72
72
  "dayjs": "^1.11.20",
73
73
  "fast-equals": "^6.0.0",
74
- "i18next": "^26.0.5",
75
- "i18next-fs-backend": "^2.6.3",
74
+ "i18next": "^26.0.6",
75
+ "i18next-fs-backend": "^2.6.4",
76
76
  "jsonwebtoken": "^9.0.3",
77
77
  "jwks-rsa": "^4.0.1",
78
78
  "nodemailer": "^8.0.5",
79
79
  "nunjucks": "^3.2.4",
80
- "parse": "^8.5.0",
80
+ "parse": "^8.6.0",
81
81
  "parse-server": "9.8.0",
82
82
  "pdf-img-convert": "2.0.0",
83
83
  "rimraf": "^6.1.3",
84
- "semantic-release": "^25.0.3",
85
84
  "table": "^6.9.0",
86
85
  "web-push": "^3.6.7",
87
86
  "winston": "^3.19.0"
88
87
  },
89
88
  "devDependencies": {
90
- "@semantic-release/changelog": "^6.0.3",
91
- "@semantic-release/commit-analyzer": "^13.0.1",
92
- "@semantic-release/exec": "^7.1.0",
93
- "@semantic-release/git": "^10.0.1",
94
- "@semantic-release/github": "^12.0.6",
95
- "@semantic-release/npm": "^13.1.5",
96
- "@semantic-release/release-notes-generator": "^14.1.0",
97
89
  "@types/jsonwebtoken": "^9.0.10",
98
90
  "@types/node": "^25.6.0",
99
91
  "@types/nodemailer": "^7.0.11",
@@ -101,10 +93,16 @@
101
93
  "@types/safe-timers": "^1.1.2",
102
94
  "@types/web-push": "^3.6.4",
103
95
  "concurrently": "^9.2.1",
104
- "semantic-release-export-data": "^1.2.0",
105
96
  "ts-node": "^10.9.2",
106
97
  "typedoc": "^0.28.19",
107
98
  "typedoc-plugin-markdown": "^4.11.0",
108
99
  "typescript": "^5.9.3"
100
+ },
101
+ "pnpm": {
102
+ "auditConfig": {
103
+ "ignoreGhsas": [
104
+ "GHSA-w5hq-g745-h8pq"
105
+ ]
106
+ }
109
107
  }
110
108
  }