@saasquatch/program-boilerplate 3.6.0-0 → 3.6.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.
@@ -5,7 +5,7 @@
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.meetEventTriggerRules = exports.meetCustomFieldRules = exports.meetEdgeTriggerConditions = void 0;
7
7
  const assert = require("assert");
8
- const jsonata = require("jsonata");
8
+ const jsonata_1 = require("./jsonata");
9
9
  //functions
10
10
  /**
11
11
  * Turns a string scalar into a Number, Boolean or String
@@ -40,11 +40,20 @@ function meetEdgeTriggerConditions(fields, activeTrigger) {
40
40
  }
41
41
  for (const field of fields) {
42
42
  if (!field.startsWith("user.")) {
43
- // TODO: what to do here? this is probably some kind of error case
44
- continue;
43
+ // we consider a malformed edge field to be "not passing"
44
+ return false;
45
+ }
46
+ // a simple query to retrieve the value of a field from the user should
47
+ // not take more than a few milliseconds. if it takes longer than 500ms
48
+ // something is definitely wrong with the query
49
+ const jsonataTimeoutMs = 500;
50
+ const { success: prevSuccess, result: previousValue } = jsonata_1.timeboxedJsonata(field.replace("user.", "previous."), activeTrigger, jsonataTimeoutMs);
51
+ const { success: currentSuccess, result: currentValue } = jsonata_1.timeboxedJsonata(field, activeTrigger, jsonataTimeoutMs);
52
+ // one of the JSONata expressions failed to evaluate -- edge field is considered
53
+ // "not passing"
54
+ if (!prevSuccess || !currentSuccess) {
55
+ return false;
45
56
  }
46
- const previousValue = jsonata(field.replace("user.", "previous.")).evaluate(activeTrigger);
47
- const currentValue = jsonata(field).evaluate(activeTrigger);
48
57
  try {
49
58
  assert.deepStrictEqual(currentValue, previousValue);
50
59
  // assertion passed -- field did not change
package/dist/index.d.ts CHANGED
@@ -6,11 +6,11 @@ import { triggerProgram } from "./trigger";
6
6
  import { getLogger, setLogLevel } from "./logger";
7
7
  import * as types from "./types";
8
8
  import { Program, ProgramRequirement, RequirementValidationResult, ValidationProgramField, ProgramTriggerBody } from "./types/rpc";
9
- import { timeboxExpression, safeJsonata } from "./jsonata";
9
+ import { timeboxExpression, timeboxedJsonata, safeJsonata } from "./jsonata";
10
10
  import { ProgramType } from "./types/saasquatch";
11
11
  import { inferType, getGoalAnalyticTimestamp, setRewardSchedule, numToEquality, getTriggerSchema, getUserCustomFieldsFromJsonata } from "./utils";
12
12
  export { types };
13
- export { Transaction, ProgramTriggerBody, Program, ProgramType, RequirementValidationResult, ProgramRequirement, ValidationProgramField, meetEventTriggerRules, meetCustomFieldRules, meetEdgeTriggerConditions, rewardEmailQuery, setRewardSchedule, getGoalAnalyticTimestamp, triggerProgram, inferType, numToEquality, getTriggerSchema, getUserCustomFieldsFromJsonata, timeboxExpression, safeJsonata, getLogger, setLogLevel, };
13
+ export { Transaction, ProgramTriggerBody, Program, ProgramType, RequirementValidationResult, ProgramRequirement, ValidationProgramField, meetEventTriggerRules, meetCustomFieldRules, meetEdgeTriggerConditions, rewardEmailQuery, setRewardSchedule, getGoalAnalyticTimestamp, triggerProgram, inferType, numToEquality, getTriggerSchema, getUserCustomFieldsFromJsonata, timeboxExpression, timeboxedJsonata, safeJsonata, getLogger, setLogLevel, };
14
14
  /**
15
15
  * Returns an express server that serves the provided handlers
16
16
  * as a program
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.webtask = exports.setLogLevel = exports.getLogger = exports.safeJsonata = exports.timeboxExpression = exports.getUserCustomFieldsFromJsonata = exports.getTriggerSchema = exports.numToEquality = exports.inferType = exports.triggerProgram = exports.getGoalAnalyticTimestamp = exports.setRewardSchedule = exports.rewardEmailQuery = exports.meetEdgeTriggerConditions = exports.meetCustomFieldRules = exports.meetEventTriggerRules = exports.Transaction = exports.types = void 0;
3
+ exports.webtask = exports.setLogLevel = exports.getLogger = exports.safeJsonata = exports.timeboxedJsonata = exports.timeboxExpression = exports.getUserCustomFieldsFromJsonata = exports.getTriggerSchema = exports.numToEquality = exports.inferType = exports.triggerProgram = exports.getGoalAnalyticTimestamp = exports.setRewardSchedule = exports.rewardEmailQuery = exports.meetEdgeTriggerConditions = exports.meetCustomFieldRules = exports.meetEventTriggerRules = exports.Transaction = exports.types = void 0;
4
4
  const express = require("express");
5
5
  const conversion_1 = require("./conversion");
6
6
  Object.defineProperty(exports, "meetCustomFieldRules", { enumerable: true, get: function () { return conversion_1.meetCustomFieldRules; } });
@@ -19,6 +19,7 @@ const types = require("./types");
19
19
  exports.types = types;
20
20
  const jsonata_1 = require("./jsonata");
21
21
  Object.defineProperty(exports, "timeboxExpression", { enumerable: true, get: function () { return jsonata_1.timeboxExpression; } });
22
+ Object.defineProperty(exports, "timeboxedJsonata", { enumerable: true, get: function () { return jsonata_1.timeboxedJsonata; } });
22
23
  Object.defineProperty(exports, "safeJsonata", { enumerable: true, get: function () { return jsonata_1.safeJsonata; } });
23
24
  const utils_1 = require("./utils");
24
25
  Object.defineProperty(exports, "inferType", { enumerable: true, get: function () { return utils_1.inferType; } });
package/dist/jsonata.d.ts CHANGED
@@ -7,5 +7,12 @@ import * as jsonata from "jsonata";
7
7
  * @param {Number} timeout - max time in ms
8
8
  * @param {Number} maxDepth - max stack depth
9
9
  */
10
- export declare function timeboxExpression(expr: jsonata.Expression): void;
10
+ export declare function timeboxExpression(expr: jsonata.Expression, timeout?: number, maxDepth?: number): void;
11
+ /**
12
+ * @deprecated Use timeboxedJsonata instead
13
+ */
11
14
  export declare function safeJsonata(expression: string, inputData: any): any;
15
+ export declare function timeboxedJsonata(expression: string, inputData: any, timeout?: number, maxDepth?: number): {
16
+ success: boolean;
17
+ result: any;
18
+ };
package/dist/jsonata.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.safeJsonata = exports.timeboxExpression = void 0;
3
+ exports.timeboxedJsonata = exports.safeJsonata = exports.timeboxExpression = void 0;
4
4
  const jsonata = require("jsonata");
5
5
  const logger_1 = require("./logger");
6
6
  const TIMEOUT = 5000;
@@ -14,19 +14,21 @@ const logger = logger_1.getLogger(process.env.PROGRAM_LOG_LEVEL || "debug");
14
14
  * @param {Number} timeout - max time in ms
15
15
  * @param {Number} maxDepth - max stack depth
16
16
  */
17
- function timeboxExpression(expr) {
18
- let depth = 0;
19
- const time = Date.now();
20
- let checkRunnaway = function () {
21
- if (depth > MAXDEPTH) {
17
+ function timeboxExpression(expr, timeout, maxDepth) {
18
+ const startTime = Date.now();
19
+ const actualTimeout = timeout !== null && timeout !== void 0 ? timeout : TIMEOUT;
20
+ const actualMaxDepth = maxDepth !== null && maxDepth !== void 0 ? maxDepth : MAXDEPTH;
21
+ let currentDepth = 0;
22
+ const checkRunnaway = function () {
23
+ if (currentDepth > actualMaxDepth) {
22
24
  // stack too deep
23
25
  throw {
24
26
  code: "U1001",
25
- message: "Stack overflow error: Check for non-terminating recursive function. Consider rewriting as tail-recursive.",
27
+ message: "Stack overflow error: Check for non-terminating recursive function. Consider rewriting as tail-recursive.",
26
28
  stack: new Error().stack,
27
29
  };
28
30
  }
29
- if (Date.now() - time > TIMEOUT) {
31
+ if (Date.now() - startTime > actualTimeout) {
30
32
  // expression has run for too long
31
33
  throw {
32
34
  code: "U1002",
@@ -36,16 +38,19 @@ function timeboxExpression(expr) {
36
38
  }
37
39
  };
38
40
  // register callbacks
39
- expr.assign("__evaluate_entry", function (expr, input, environment) {
40
- depth++;
41
+ expr.assign("__evaluate_entry", () => {
42
+ currentDepth++;
41
43
  checkRunnaway();
42
44
  });
43
- expr.assign("__evaluate_exit", function (expr, input, environment, result) {
44
- depth--;
45
+ expr.assign("__evaluate_exit", () => {
46
+ currentDepth--;
45
47
  checkRunnaway();
46
48
  });
47
49
  }
48
50
  exports.timeboxExpression = timeboxExpression;
51
+ /**
52
+ * @deprecated Use timeboxedJsonata instead
53
+ */
49
54
  function safeJsonata(expression, inputData) {
50
55
  try {
51
56
  const jsonataQuery = jsonata(expression);
@@ -57,3 +62,18 @@ function safeJsonata(expression, inputData) {
57
62
  }
58
63
  }
59
64
  exports.safeJsonata = safeJsonata;
65
+ function timeboxedJsonata(expression, inputData, timeout, maxDepth) {
66
+ try {
67
+ const jsonataQuery = jsonata(expression);
68
+ timeboxExpression(jsonataQuery, timeout, maxDepth);
69
+ const result = jsonataQuery.evaluate(inputData);
70
+ return { success: true, result };
71
+ }
72
+ catch (e) {
73
+ if (e instanceof Error) {
74
+ logger.warn(`Failed to evaluate JSONata expression: ${e.message}`);
75
+ }
76
+ return { success: false, result: undefined };
77
+ }
78
+ }
79
+ exports.timeboxedJsonata = timeboxedJsonata;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saasquatch/program-boilerplate",
3
- "version": "3.6.0-0",
3
+ "version": "3.6.0",
4
4
  "description": "Boilerplate for writing programs",
5
5
  "main": "dist/index.js",
6
6
  "files": [
@@ -32,7 +32,7 @@
32
32
  "typescript": "^3.9.9"
33
33
  },
34
34
  "dependencies": {
35
- "@saasquatch/jsonata-paths-extractor": "^1.0.0-0",
35
+ "@saasquatch/jsonata-paths-extractor": "^1.0.1",
36
36
  "bson-objectid": "^1.3.1",
37
37
  "compression": "^1.7.4",
38
38
  "express": "^4.17.1",