botium-core 1.13.18 → 1.14.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.
Files changed (60) hide show
  1. package/dist/botium-cjs.js +326 -387
  2. package/dist/botium-cjs.js.map +1 -1
  3. package/dist/botium-es.js +326 -385
  4. package/dist/botium-es.js.map +1 -1
  5. package/package.json +21 -25
  6. package/samples/extensions/asserterHooks/botium.json +1 -0
  7. package/samples/extensions/logichooks/botium.json +1 -0
  8. package/samples/extensions/logichooks/custom/MyAsserter.js +3 -3
  9. package/src/Capabilities.js +2 -1
  10. package/src/containers/PluginConnectorContainer.js +8 -0
  11. package/src/containers/plugins/SimpleRestContainer.js +17 -9
  12. package/src/containers/plugins/index.js +29 -41
  13. package/src/helpers/HookUtils.js +32 -68
  14. package/src/scripting/Convo.js +17 -5
  15. package/src/scripting/ScriptingMemory.js +0 -24
  16. package/src/scripting/logichook/LogicHookConsts.js +5 -1
  17. package/src/scripting/logichook/LogicHookUtils.js +27 -47
  18. package/src/scripting/logichook/asserter/ButtonsAsserter.js +5 -5
  19. package/src/scripting/logichook/logichooks/ConditionalBusinessHoursLogicHook.js +56 -0
  20. package/src/scripting/logichook/logichooks/ConditionalCapabilityValueBasedLogicHook.js +37 -0
  21. package/src/scripting/logichook/logichooks/ConditionalJsonPathBasedLogicHook.js +31 -0
  22. package/src/scripting/logichook/logichooks/ConditionalTimeBasedLogicHook.js +46 -0
  23. package/test/compiler/precompilerscript.spec.js +24 -26
  24. package/test/connectors/pluginconnectorcontainer.spec.js +60 -0
  25. package/test/connectors/simplerest.spec.js +24 -27
  26. package/test/convo/fillAndApplyScriptingMemory.spec.js +1 -47
  27. package/test/hooks/customhooks.spec.js +3 -25
  28. package/test/logichooks/hookfromsrc.spec.js +13 -3
  29. package/test/plugins/plugins.spec.js +29 -2
  30. package/test/scripting/logichooks/CustomConditionalLogicHook.js +21 -0
  31. package/test/scripting/logichooks/conditionalStepBusinessHoursLogicHook.spec.js +130 -0
  32. package/test/scripting/logichooks/conditionalStepCapabilityValueBasedLogicHook.spec.js +35 -0
  33. package/test/scripting/logichooks/conditionalStepJsonPathBasedLogicHook.spec.js +35 -0
  34. package/test/scripting/logichooks/conditionalStepTimeBasedLogicHook.spec.js +91 -0
  35. package/test/scripting/logichooks/convos/conditional_steps.convo.txt +12 -0
  36. package/test/scripting/logichooks/convos/conditional_steps_business_hours.convo.txt +16 -0
  37. package/test/scripting/logichooks/convos/conditional_steps_cap_value_based.convo.txt +12 -0
  38. package/test/scripting/logichooks/convos/conditional_steps_followed_by_bot_msg.convo.txt +15 -0
  39. package/test/scripting/logichooks/convos/conditional_steps_followed_by_me.convo.txt +18 -0
  40. package/test/scripting/logichooks/convos/conditional_steps_json_path_based.convo.txt.convo.txt +12 -0
  41. package/test/scripting/logichooks/convos/conditional_steps_multiple_condition_groups.convo.txt +20 -0
  42. package/test/scripting/logichooks/convos/conditional_steps_multiple_condition_groups_no_assertion.convo.txt +20 -0
  43. package/test/scripting/logichooks/convos/conditional_steps_time_based.convo.txt +12 -0
  44. package/test/scripting/logichooks/customConditionalStepLogicHook.spec.js +105 -0
  45. package/test/scripting/scriptingProvider.spec.js +1 -1
  46. package/test/security/allowUnsafe.spec.js +20 -129
  47. package/LICENSES-3RDPARTY.txt +0 -6450
  48. package/test/scripting/asserters/convos/customembeddedasserterwithhugo.convo.txt +0 -7
  49. package/test/scripting/asserters/convos/customembeddedasserterwithouthugo.convo.txt +0 -7
  50. package/test/scripting/asserters/customEmbeddedAsserter.json +0 -14
  51. package/test/scripting/asserters/customEmbeddedAsserter.spec.js +0 -55
  52. package/test/scripting/logichooks/convos/custom_embedded.convo.txt +0 -8
  53. package/test/scripting/logichooks/convos/custom_embedded_skip.convo.txt +0 -11
  54. package/test/scripting/logichooks/convos/custom_embedded_skip_followed_by_me.convo.txt +0 -11
  55. package/test/scripting/logichooks/convos/custom_embedded_skip_followed_by_nothing.convo.txt +0 -8
  56. package/test/scripting/logichooks/customEmbedded.json +0 -14
  57. package/test/scripting/logichooks/customEmbedded.spec.js +0 -44
  58. package/test/scripting/logichooks/customEmbeddedSkip.json +0 -14
  59. package/test/scripting/logichooks/customEmbeddedSkip.spec.js +0 -58
  60. package/test/security/convos/withscriptingmemoryfunction.convo.txt +0 -5
@@ -15,7 +15,6 @@ var lodash = require('lodash');
15
15
  var boolean$1 = require('boolean');
16
16
  var events = require('events');
17
17
  var debug$n = require('debug');
18
- var vm2 = require('vm2');
19
18
  var isClass = require('is-class');
20
19
  var crypto = require('crypto');
21
20
  var globby = require('globby');
@@ -25,7 +24,6 @@ var uuid = require('uuid');
25
24
  var jsonpath = require('jsonpath');
26
25
  var isJson$1 = require('is-json');
27
26
  var wordErrorRate = require('word-error-rate');
28
- var esprima = require('esprima');
29
27
  var markdownIt = require('markdown-it');
30
28
  var xlsx = require('xlsx');
31
29
  var sync = require('csv-parse/sync');
@@ -55,7 +53,6 @@ var lodash__default = /*#__PURE__*/_interopDefaultLegacy(lodash);
55
53
  var boolean__default = /*#__PURE__*/_interopDefaultLegacy(boolean$1);
56
54
  var events__default = /*#__PURE__*/_interopDefaultLegacy(events);
57
55
  var debug__default = /*#__PURE__*/_interopDefaultLegacy(debug$n);
58
- var vm2__default = /*#__PURE__*/_interopDefaultLegacy(vm2);
59
56
  var isClass__default = /*#__PURE__*/_interopDefaultLegacy(isClass);
60
57
  var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto);
61
58
  var globby__default = /*#__PURE__*/_interopDefaultLegacy(globby);
@@ -65,7 +62,6 @@ var uuid__default = /*#__PURE__*/_interopDefaultLegacy(uuid);
65
62
  var jsonpath__default = /*#__PURE__*/_interopDefaultLegacy(jsonpath);
66
63
  var isJson__default = /*#__PURE__*/_interopDefaultLegacy(isJson$1);
67
64
  var wordErrorRate__default = /*#__PURE__*/_interopDefaultLegacy(wordErrorRate);
68
- var esprima__default = /*#__PURE__*/_interopDefaultLegacy(esprima);
69
65
  var markdownIt__default = /*#__PURE__*/_interopDefaultLegacy(markdownIt);
70
66
  var xlsx__default = /*#__PURE__*/_interopDefaultLegacy(xlsx);
71
67
  var sync__default = /*#__PURE__*/_interopDefaultLegacy(sync);
@@ -81,7 +77,7 @@ var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
81
77
  var bodyParser__default = /*#__PURE__*/_interopDefaultLegacy(bodyParser);
82
78
 
83
79
  var name = "botium-core";
84
- var version$1 = "1.13.18";
80
+ var version$1 = "1.14.0";
85
81
  var description = "The Selenium for Chatbots";
86
82
  var main = "index.js";
87
83
  var module$1 = "dist/botium-es.js";
@@ -99,7 +95,6 @@ var scripts = {
99
95
  link: "npm link botium-connector-dialogflow botium-connector-webdriverio botium-connector-directline3 botium-connector-watson botium-connector-alexa-smapi botium-connector-echo",
100
96
  test: "cross-env NODE_PATH=\"./test/plugins/plugindir/fromfolder:./test/plugins/plugindir/fromfile:./test/security/resources\" mocha \"./test/**/*.spec.js\"",
101
97
  "coverage:report": "nyc report --reporter=lcov npm test",
102
- "license-checker": "license-checker > LICENSES-3RDPARTY.txt",
103
98
  "update-dependencies": "npm-check-updates --reject globby,rollup -u --timeout 120000"
104
99
  };
105
100
  var repository = {
@@ -113,14 +108,13 @@ var bugs = {
113
108
  };
114
109
  var homepage = "https://www.botium.ai";
115
110
  var dependencies = {
116
- "@babel/runtime": "^7.21.5",
111
+ "@babel/runtime": "^7.22.15",
117
112
  async: "^3.2.4",
118
113
  "body-parser": "^1.20.2",
119
114
  boolean: "^3.2.0",
120
115
  bottleneck: "^2.19.5",
121
- "csv-parse": "^5.3.10",
116
+ "csv-parse": "^5.5.0",
122
117
  debug: "^4.3.4",
123
- esprima: "^4.0.1",
124
118
  express: "^4.18.2",
125
119
  globby: "11.0.4",
126
120
  ioredis: "^5.3.2",
@@ -132,47 +126,45 @@ var dependencies = {
132
126
  "mime-types": "^2.1.35",
133
127
  mkdirp: "^3.0.1",
134
128
  moment: "^2.29.4",
129
+ "moment-timezone": "^0.5.43",
135
130
  mustache: "^4.2.0",
136
131
  "promise-retry": "^2.0.1",
137
- "promise.allsettled": "^1.0.6",
132
+ "promise.allsettled": "^1.0.7",
138
133
  randomatic: "^3.1.1",
139
134
  request: "^2.88.2",
140
- rimraf: "^5.0.0",
135
+ rimraf: "^5.0.1",
141
136
  "sanitize-filename": "^1.6.3",
142
137
  slugify: "^1.6.6",
143
- "socket.io": "^4.6.1",
144
- "socket.io-client": "^4.6.1",
138
+ "socket.io": "^4.7.2",
139
+ "socket.io-client": "^4.7.2",
145
140
  "socketio-auth": "^0.1.1",
146
141
  "swagger-jsdoc": "^6.2.8",
147
- "swagger-ui-express": "^4.6.3",
142
+ "swagger-ui-express": "^5.0.0",
148
143
  uuid: "^9.0.0",
149
- vm2: "^3.9.17",
150
144
  "word-error-rate": "0.0.7",
151
145
  "write-yaml": "^1.0.0",
152
146
  xlsx: "^0.18.5",
153
147
  xregexp: "^5.1.1",
154
- yaml: "^2.2.2"
148
+ yaml: "^2.3.2"
155
149
  };
156
150
  var devDependencies = {
157
- "@babel/core": "^7.21.8",
158
- "@babel/node": "^7.20.7",
159
- "@babel/plugin-transform-runtime": "^7.21.4",
160
- "@babel/preset-env": "^7.21.5",
161
- chai: "^4.3.7",
151
+ "@babel/core": "^7.22.17",
152
+ "@babel/node": "^7.22.15",
153
+ "@babel/plugin-transform-runtime": "^7.22.15",
154
+ "@babel/preset-env": "^7.22.15",
155
+ chai: "^4.3.8",
162
156
  "chai-as-promised": "^7.1.1",
163
157
  "cross-env": "^7.0.3",
164
- eslint: "^8.40.0",
165
- "eslint-config-standard": "^17.0.0",
166
- "eslint-plugin-import": "^2.27.5",
158
+ eslint: "^8.49.0",
159
+ "eslint-config-standard": "^17.1.0",
160
+ "eslint-plugin-import": "^2.28.1",
167
161
  "eslint-plugin-mocha": "^10.1.0",
168
- "eslint-plugin-n": "^15.7.0",
162
+ "eslint-plugin-n": "^16.1.0",
169
163
  "eslint-plugin-promise": "^6.1.1",
170
164
  "eslint-plugin-standard": "^4.1.0",
171
- "license-checker": "^25.0.1",
172
- "license-compatibility-checker": "^0.3.5",
173
165
  mocha: "^10.2.0",
174
- nock: "^13.3.1",
175
- "npm-check-updates": "^16.10.12",
166
+ nock: "^13.3.3",
167
+ "npm-check-updates": "^16.13.3",
176
168
  nyc: "^15.1.0",
177
169
  rollup: "2.79.1",
178
170
  "rollup-plugin-babel": "^4.4.0",
@@ -221,6 +213,7 @@ var Capabilities = {
221
213
  TESTSESSIONNAME: 'TESTSESSIONNAME',
222
214
  TESTCASENAME: 'TESTCASENAME',
223
215
  TEMPDIR: 'TEMPDIR',
216
+ SAFEDIR: 'SAFEDIR',
224
217
  CLEANUPTEMPDIR: 'CLEANUPTEMPDIR',
225
218
  WAITFORBOTTIMEOUT: 'WAITFORBOTTIMEOUT',
226
219
  CONTAINERMODE: 'CONTAINERMODE',
@@ -230,7 +223,7 @@ var Capabilities = {
230
223
  BOTIUMGRIDURL: 'BOTIUMGRIDURL',
231
224
  BOTIUMAPITOKEN: 'BOTIUMAPITOKEN',
232
225
  BOTIUMGRIDSLOT: 'BOTIUMGRIDSLOT',
233
- // Simple Reset Bot Settings
226
+ // Simple Rest Bot Settings
234
227
  SIMPLEREST_PING_URL: 'SIMPLEREST_PING_URL',
235
228
  SIMPLEREST_PING_VERB: 'SIMPLEREST_PING_VERB',
236
229
  SIMPLEREST_PING_BODY: 'SIMPLEREST_PING_BODY',
@@ -395,6 +388,7 @@ Capabilities.PROJECTNAME;
395
388
  Capabilities.TESTSESSIONNAME;
396
389
  Capabilities.TESTCASENAME;
397
390
  Capabilities.TEMPDIR;
391
+ Capabilities.SAFEDIR;
398
392
  Capabilities.CLEANUPTEMPDIR;
399
393
  Capabilities.WAITFORBOTTIMEOUT;
400
394
  Capabilities.CONTAINERMODE;
@@ -913,140 +907,6 @@ function getCjsExportFromNamespace (n) {
913
907
  return n && n['default'] || n;
914
908
  }
915
909
 
916
- const BotiumError$7 = class BotiumError extends Error {
917
- /**
918
- *
919
- * @param message
920
- * @param context A JSON with struct
921
- * {
922
- * type: 'some free text to identity the exception type',
923
- * source: 'source of the event',
924
- * ...
925
- */
926
- constructor(message, context, supressChildCheck) {
927
- super(message.message || message);
928
- if (!supressChildCheck && _getChildErrorsFromContext(context)) {
929
- throw Error('Create BotiumError with child errors using the fromList() method!');
930
- }
931
- // Saving class name in the property of our custom error as a shortcut.
932
- this.name = this.constructor.name;
933
-
934
- // Capturing stack trace, excluding constructor call from it.
935
- Error.captureStackTrace(this, this.constructor);
936
- this.context = context || {};
937
- this.context.message = message.message || message;
938
- }
939
- isAsserterError() {
940
- if (this.context) {
941
- const errArr = lodash__default["default"].isArray(this.context) ? this.context : [this.context];
942
- const hasNotAsserterError = errArr.findIndex(errDetail => {
943
- if (errDetail.type === 'list') {
944
- if (errDetail.errors) {
945
- return errDetail.errors.findIndex(e => e.type !== 'asserter') >= 0;
946
- } else {
947
- return true;
948
- }
949
- } else {
950
- return errDetail.type !== 'asserter';
951
- }
952
- }) >= 0;
953
- if (hasNotAsserterError) return false;
954
- return true;
955
- } else {
956
- return false;
957
- }
958
- }
959
- prettify(includeJson) {
960
- const lines = [];
961
- if (this.context) {
962
- const errArr = lodash__default["default"].isArray(this.context) ? this.context : [this.context];
963
- errArr.forEach(errDetail => {
964
- lines.push('########################################');
965
- if (errDetail.type === 'asserter') {
966
- const segments = [];
967
- segments.push(`ASSERTION FAILED in ${errDetail.source}${errDetail.subtype ? ` (${errDetail.subtype})` : ''}`);
968
- errDetail.cause && errDetail.cause.expected && !errDetail.cause.not && segments.push(` - Expected: ${JSON.stringify(errDetail.cause.expected)} `);
969
- errDetail.cause && errDetail.cause.expected && errDetail.cause.not && segments.push(` - NOT Expected: ${JSON.stringify(errDetail.cause.expected)} `);
970
- errDetail.cause && errDetail.cause.actual && segments.push(` - Actual: ${JSON.stringify(errDetail.cause.actual)}`);
971
- errDetail.cause && !errDetail.cause.actual && segments.push(' - Actual: empty');
972
- lines.push(segments.join(''));
973
- errDetail.input && errDetail.input.messageText && lines.push(`INPUT: ${errDetail.input.messageText}`);
974
- } else if (errDetail.message) {
975
- lines.push(`${errDetail.message}`);
976
- }
977
- if (errDetail.transcript && errDetail.transcript.length > 0) {
978
- lines.push('------------ TRANSCRIPT ----------------------------');
979
- errDetail.transcript.forEach(transcriptStep => {
980
- if (transcriptStep.actual) {
981
- lines.push(transcriptStep.actual.prettify());
982
- }
983
- });
984
- }
985
- if (includeJson) {
986
- lines.push('------------ JSON CONTENT ----------------------------');
987
- try {
988
- const jsonOutput = JSON.stringify(errDetail);
989
- lines.push(jsonOutput);
990
- } catch (jsonErr) {
991
- lines.push(`JSON Output not possible: ${jsonErr.message}`);
992
- }
993
- }
994
- });
995
- }
996
- if (lines.length > 0) {
997
- return lines.join('\r\n');
998
- } else {
999
- return null;
1000
- }
1001
- }
1002
- };
1003
- const _getChildErrorsFromContext = context => {
1004
- if (context && context.errors && lodash__default["default"].isArray(context.errors)) {
1005
- return context.errors;
1006
- }
1007
- return false;
1008
- };
1009
- const botiumErrorFromErr$2 = (message, err) => {
1010
- if (err instanceof BotiumError$7) {
1011
- return new BotiumError$7(message, err.context, true);
1012
- } else {
1013
- return new BotiumError$7(message, {
1014
- err
1015
- }, true);
1016
- }
1017
- };
1018
- const botiumErrorFromList$2 = (errors, {
1019
- type = 'list',
1020
- source = 'BotiumError',
1021
- flat = true
1022
- }) => {
1023
- const message = errors.map(err => err.message || err.toString()).join(',\n');
1024
- let children = [];
1025
- for (const error of errors) {
1026
- if (error instanceof BotiumError$7) {
1027
- const childErrors = flat && _getChildErrorsFromContext(error.context);
1028
- if (childErrors && childErrors.length) {
1029
- children = children.concat(childErrors);
1030
- } else if (error.context) {
1031
- children.push(error.context);
1032
- }
1033
- } else {
1034
- children.push(error);
1035
- }
1036
- }
1037
- const result = new BotiumError$7(message, {
1038
- errors: children,
1039
- type,
1040
- source
1041
- }, true);
1042
- return result;
1043
- };
1044
- var BotiumError_1 = {
1045
- BotiumError: BotiumError$7,
1046
- botiumErrorFromErr: botiumErrorFromErr$2,
1047
- botiumErrorFromList: botiumErrorFromList$2
1048
- };
1049
-
1050
910
  const LOGIC_HOOK_INCLUDE$1 = 'INCLUDE';
1051
911
  var LogicHookConsts = {
1052
912
  LOGIC_HOOK_INCLUDE: LOGIC_HOOK_INCLUDE$1,
@@ -1204,6 +1064,18 @@ var LogicHookConsts = {
1204
1064
  }, {
1205
1065
  name: LOGIC_HOOK_INCLUDE$1,
1206
1066
  className: 'IncludeLogicHook'
1067
+ }, {
1068
+ name: 'CONDITIONAL_STEP_TIME_BASED',
1069
+ className: 'ConditionalTimeBasedLogicHook'
1070
+ }, {
1071
+ name: 'CONDITIONAL_STEP_BUSINESS_HOURS',
1072
+ className: 'ConditionalBusinessHoursLogicHook'
1073
+ }, {
1074
+ name: 'CONDITIONAL_STEP_CAPABILITY_VALUE_BASED',
1075
+ className: 'ConditionalCapabilityValueBasedLogicHook'
1076
+ }, {
1077
+ name: 'CONDITIONAL_STEP_JSON_PATH_BASED',
1078
+ className: 'ConditionalJsonPathBasedLogicHook.js'
1207
1079
  }],
1208
1080
  DEFAULT_USER_INPUTS: [{
1209
1081
  name: 'BUTTON',
@@ -1221,13 +1093,7 @@ LogicHookConsts.DEFAULT_ASSERTERS;
1221
1093
  LogicHookConsts.DEFAULT_LOGIC_HOOKS;
1222
1094
  LogicHookConsts.DEFAULT_USER_INPUTS;
1223
1095
 
1224
- const {
1225
- NodeVM: NodeVM$2
1226
- } = vm2__default["default"];
1227
1096
  const debug$m = debug__default["default"]('botium-core-asserterUtils');
1228
- const {
1229
- BotiumError: BotiumError$6
1230
- } = BotiumError_1;
1231
1097
  const {
1232
1098
  DEFAULT_ASSERTERS,
1233
1099
  DEFAULT_LOGIC_HOOKS,
@@ -1349,21 +1215,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1349
1215
  }, this.caps, args);
1350
1216
  }
1351
1217
  }
1352
- const _checkUnsafe = () => {
1353
- if (!this.caps[Capabilities.SECURITY_ALLOW_UNSAFE]) {
1354
- throw new BotiumError$6('Security Error. Using unsafe component is not allowed', {
1355
- type: 'security',
1356
- subtype: 'allow unsafe',
1357
- source: path__default["default"].basename(__filename),
1358
- cause: {
1359
- src: !!src,
1360
- ref,
1361
- args,
1362
- hookType
1363
- }
1364
- });
1365
- }
1366
- };
1218
+ const allowUnsafe = !!this.caps[Capabilities.SECURITY_ALLOW_UNSAFE];
1367
1219
  if (!src) {
1368
1220
  const packageName = `botium-${hookType}-${ref}`;
1369
1221
  try {
@@ -1384,10 +1236,10 @@ var LogicHookUtils_1 = class LogicHookUtils {
1384
1236
  ...this.buildScriptContext
1385
1237
  }, this.caps, args);
1386
1238
  } else {
1387
- throw new Error(`${packageName} class or function or PluginClass field expected`);
1239
+ throw new Error('Either class or function or PluginClass field expected');
1388
1240
  }
1389
1241
  } catch (err) {
1390
- throw new Error(`Failed to fetch hook ${ref} ${hookType} from guessed package ${packageName} - ${err.message}`);
1242
+ throw new Error(`Logic Hook specification ${ref} ${hookType} (${packageName}) invalid: ${err.message}`);
1391
1243
  }
1392
1244
  }
1393
1245
  if (isClass__default["default"](src)) {
@@ -1398,7 +1250,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1398
1250
  ...this.buildScriptContext
1399
1251
  }, this.caps, args);
1400
1252
  } catch (err) {
1401
- throw new Error(`Failed to load package ${ref} from provided class - ${err.message}`);
1253
+ throw new Error(`Logic Hook specification ${ref} from class invalid: ${err.message}`);
1402
1254
  }
1403
1255
  }
1404
1256
  if (lodash__default["default"].isFunction(src)) {
@@ -1408,7 +1260,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1408
1260
  ...this.buildScriptContext
1409
1261
  }, this.caps, args);
1410
1262
  } catch (err) {
1411
- throw new Error(`Failed to load package ${ref} from provided function - ${err.message}`);
1263
+ throw new Error(`Logic Hook specification ${ref} from function invalid: ${err.message}`);
1412
1264
  }
1413
1265
  }
1414
1266
  if (lodash__default["default"].isObject(src) && !lodash__default["default"].isString(src)) {
@@ -1418,26 +1270,15 @@ var LogicHookUtils_1 = class LogicHookUtils {
1418
1270
  const script = src[key];
1419
1271
  if (lodash__default["default"].isFunction(script)) {
1420
1272
  return script(args);
1421
- } else if (lodash__default["default"].isString(script)) {
1422
- try {
1423
- const vm = new NodeVM$2({
1424
- eval: false,
1425
- require: false,
1426
- sandbox: args
1427
- });
1428
- return vm.run(script);
1429
- } catch (err) {
1430
- throw new Error(`Script ${key} is not valid - ${err.message || err}`);
1431
- }
1432
1273
  } else {
1433
- throw new Error(`Script "${key}" is not valid - only functions and javascript code accepted`);
1274
+ throw new Error(`Script ${key} is not valid - only functions accepted`);
1434
1275
  }
1435
1276
  };
1436
1277
  return result;
1437
1278
  }, {});
1438
1279
  return hookObject;
1439
1280
  } catch (err) {
1440
- throw new Error(`Failed to load package ${ref} ${hookType} from provided src function - ${err.message}`);
1281
+ throw new Error(`Logic Hook specification ${ref} ${hookType} from provided src (${util__default["default"].inspect(src)}) invalid: ${err.message}`);
1441
1282
  }
1442
1283
  }
1443
1284
  if (lodash__default["default"].isString(src)) {
@@ -1448,8 +1289,8 @@ var LogicHookUtils_1 = class LogicHookUtils {
1448
1289
  }];
1449
1290
  if (src.indexOf('/') >= 0) {
1450
1291
  tryLoads.push({
1451
- tryLoadPackageName: src.substr(0, src.lastIndexOf('/')),
1452
- tryLoadAsserterByName: src.substr(src.lastIndexOf('/') + 1)
1292
+ tryLoadPackageName: src.substring(0, src.lastIndexOf('/')),
1293
+ tryLoadAsserterByName: src.substring(src.lastIndexOf('/') + 1)
1453
1294
  });
1454
1295
  }
1455
1296
  const tryLoadFromSource = (tryRequire, tryAsserterName) => {
@@ -1487,28 +1328,33 @@ var LogicHookUtils_1 = class LogicHookUtils {
1487
1328
  ...this.buildScriptContext
1488
1329
  }, this.caps, args);
1489
1330
  } else {
1490
- throw new Error(`${src} class or function expected`);
1331
+ throw new Error('Expected class or function');
1491
1332
  }
1492
1333
  };
1493
1334
  for (const tryLoad of tryLoads) {
1494
- const tryLoadFile = path__default["default"].resolve(process.cwd(), tryLoad.tryLoadPackageName);
1495
- if (fs__default["default"].existsSync(tryLoadFile)) {
1496
- _checkUnsafe();
1335
+ if (this.caps.SAFEDIR) {
1336
+ const tryLoadFile = path__default["default"].resolve(this.caps.SAFEDIR, tryLoad.tryLoadPackageName);
1337
+ if (tryLoadFile.startsWith(path__default["default"].resolve(this.caps.SAFEDIR))) {
1338
+ if (fs__default["default"].existsSync(tryLoadFile)) {
1339
+ try {
1340
+ return tryLoadFromSource(tryLoadFile, tryLoad.tryLoadAsserterByName);
1341
+ } catch (err) {
1342
+ loadErr.push(`Logic Hook specification ${ref} ${hookType} from "${src}" invalid: ${err.message} `);
1343
+ }
1344
+ }
1345
+ }
1346
+ }
1347
+ if (allowUnsafe || tryLoad.tryLoadPackageName.startsWith('botium-')) {
1497
1348
  try {
1498
- return tryLoadFromSource(tryLoadFile, tryLoad.tryLoadAsserterByName);
1349
+ return tryLoadFromSource(tryLoad.tryLoadPackageName, tryLoad.tryLoadAsserterByName);
1499
1350
  } catch (err) {
1500
- loadErr.push(`Failed to fetch ${ref} ${hookType} from ${src} - ${err.message} `);
1351
+ loadErr.push(`Logic Hook specification ${ref} ${hookType} from "${src}" invalid: ${err.message} `);
1501
1352
  }
1502
1353
  }
1503
- try {
1504
- return tryLoadFromSource(tryLoad.tryLoadPackageName, tryLoad.tryLoadAsserterByName);
1505
- } catch (err) {
1506
- loadErr.push(`Failed to fetch ${ref} ${hookType} from ${src} - ${err.message} `);
1507
- }
1508
1354
  }
1509
1355
  loadErr.forEach(debug$m);
1510
1356
  }
1511
- throw new Error(`Failed to fetch ${ref} ${hookType}, no idea how to load ...`);
1357
+ throw new Error(`Logic Hook specification ${ref} ${hookType} from "${util__default["default"].inspect(src)}" invalid : no loader available`);
1512
1358
  }
1513
1359
  };
1514
1360
 
@@ -2315,19 +2161,150 @@ var helper = {
2315
2161
  toPercent: toPercent$1
2316
2162
  };
2317
2163
 
2164
+ const BotiumError$4 = class BotiumError extends Error {
2165
+ /**
2166
+ *
2167
+ * @param message
2168
+ * @param context A JSON with struct
2169
+ * {
2170
+ * type: 'some free text to identity the exception type',
2171
+ * source: 'source of the event',
2172
+ * ...
2173
+ */
2174
+ constructor(message, context, supressChildCheck) {
2175
+ super(message.message || message);
2176
+ if (!supressChildCheck && _getChildErrorsFromContext(context)) {
2177
+ throw Error('Create BotiumError with child errors using the fromList() method!');
2178
+ }
2179
+ // Saving class name in the property of our custom error as a shortcut.
2180
+ this.name = this.constructor.name;
2181
+
2182
+ // Capturing stack trace, excluding constructor call from it.
2183
+ Error.captureStackTrace(this, this.constructor);
2184
+ this.context = context || {};
2185
+ this.context.message = message.message || message;
2186
+ }
2187
+ isAsserterError() {
2188
+ if (this.context) {
2189
+ const errArr = lodash__default["default"].isArray(this.context) ? this.context : [this.context];
2190
+ const hasNotAsserterError = errArr.findIndex(errDetail => {
2191
+ if (errDetail.type === 'list') {
2192
+ if (errDetail.errors) {
2193
+ return errDetail.errors.findIndex(e => e.type !== 'asserter') >= 0;
2194
+ } else {
2195
+ return true;
2196
+ }
2197
+ } else {
2198
+ return errDetail.type !== 'asserter';
2199
+ }
2200
+ }) >= 0;
2201
+ if (hasNotAsserterError) return false;
2202
+ return true;
2203
+ } else {
2204
+ return false;
2205
+ }
2206
+ }
2207
+ prettify(includeJson) {
2208
+ const lines = [];
2209
+ if (this.context) {
2210
+ const errArr = lodash__default["default"].isArray(this.context) ? this.context : [this.context];
2211
+ errArr.forEach(errDetail => {
2212
+ lines.push('########################################');
2213
+ if (errDetail.type === 'asserter') {
2214
+ const segments = [];
2215
+ segments.push(`ASSERTION FAILED in ${errDetail.source}${errDetail.subtype ? ` (${errDetail.subtype})` : ''}`);
2216
+ errDetail.cause && errDetail.cause.expected && !errDetail.cause.not && segments.push(` - Expected: ${JSON.stringify(errDetail.cause.expected)} `);
2217
+ errDetail.cause && errDetail.cause.expected && errDetail.cause.not && segments.push(` - NOT Expected: ${JSON.stringify(errDetail.cause.expected)} `);
2218
+ errDetail.cause && errDetail.cause.actual && segments.push(` - Actual: ${JSON.stringify(errDetail.cause.actual)}`);
2219
+ errDetail.cause && !errDetail.cause.actual && segments.push(' - Actual: empty');
2220
+ lines.push(segments.join(''));
2221
+ errDetail.input && errDetail.input.messageText && lines.push(`INPUT: ${errDetail.input.messageText}`);
2222
+ } else if (errDetail.message) {
2223
+ lines.push(`${errDetail.message}`);
2224
+ }
2225
+ if (errDetail.transcript && errDetail.transcript.length > 0) {
2226
+ lines.push('------------ TRANSCRIPT ----------------------------');
2227
+ errDetail.transcript.forEach(transcriptStep => {
2228
+ if (transcriptStep.actual) {
2229
+ lines.push(transcriptStep.actual.prettify());
2230
+ }
2231
+ });
2232
+ }
2233
+ if (includeJson) {
2234
+ lines.push('------------ JSON CONTENT ----------------------------');
2235
+ try {
2236
+ const jsonOutput = JSON.stringify(errDetail);
2237
+ lines.push(jsonOutput);
2238
+ } catch (jsonErr) {
2239
+ lines.push(`JSON Output not possible: ${jsonErr.message}`);
2240
+ }
2241
+ }
2242
+ });
2243
+ }
2244
+ if (lines.length > 0) {
2245
+ return lines.join('\r\n');
2246
+ } else {
2247
+ return null;
2248
+ }
2249
+ }
2250
+ };
2251
+ const _getChildErrorsFromContext = context => {
2252
+ if (context && context.errors && lodash__default["default"].isArray(context.errors)) {
2253
+ return context.errors;
2254
+ }
2255
+ return false;
2256
+ };
2257
+ const botiumErrorFromErr$2 = (message, err) => {
2258
+ if (err instanceof BotiumError$4) {
2259
+ return new BotiumError$4(message, err.context, true);
2260
+ } else {
2261
+ return new BotiumError$4(message, {
2262
+ err
2263
+ }, true);
2264
+ }
2265
+ };
2266
+ const botiumErrorFromList$2 = (errors, {
2267
+ type = 'list',
2268
+ source = 'BotiumError',
2269
+ flat = true
2270
+ }) => {
2271
+ const message = errors.map(err => err.message || err.toString()).join(',\n');
2272
+ let children = [];
2273
+ for (const error of errors) {
2274
+ if (error instanceof BotiumError$4) {
2275
+ const childErrors = flat && _getChildErrorsFromContext(error.context);
2276
+ if (childErrors && childErrors.length) {
2277
+ children = children.concat(childErrors);
2278
+ } else if (error.context) {
2279
+ children.push(error.context);
2280
+ }
2281
+ } else {
2282
+ children.push(error);
2283
+ }
2284
+ }
2285
+ const result = new BotiumError$4(message, {
2286
+ errors: children,
2287
+ type,
2288
+ source
2289
+ }, true);
2290
+ return result;
2291
+ };
2292
+ var BotiumError_1 = {
2293
+ BotiumError: BotiumError$4,
2294
+ botiumErrorFromErr: botiumErrorFromErr$2,
2295
+ botiumErrorFromList: botiumErrorFromList$2
2296
+ };
2297
+
2318
2298
  const debug$k = debug__default["default"]('botium-core-ScriptingMemory');
2319
2299
  const {
2320
2300
  v1: uuidv1
2321
2301
  } = uuid__default["default"];
2322
- const {
2323
- NodeVM: NodeVM$1
2324
- } = vm2__default["default"];
2325
2302
  const {
2326
2303
  quoteRegexpString: quoteRegexpString$1,
2327
2304
  toString: toString$2
2328
2305
  } = helper;
2329
2306
  const {
2330
- BotiumError: BotiumError$5
2307
+ BotiumError: BotiumError$3
2331
2308
  } = BotiumError_1;
2332
2309
 
2333
2310
  // If they got parameter, then it will be a string always.
@@ -2484,28 +2461,6 @@ const SCRIPTING_FUNCTIONS_RAW = {
2484
2461
  if (root && root.length > 0) return root[0];else return '';
2485
2462
  },
2486
2463
  numberOfArguments: 1
2487
- },
2488
- $func: {
2489
- handler: (caps, code) => {
2490
- if (code == null) {
2491
- throw Error('func function used without args!');
2492
- }
2493
- try {
2494
- const vm = new NodeVM$1({
2495
- eval: false,
2496
- require: false,
2497
- env: caps[Capabilities.SECURITY_ALLOW_UNSAFE] ? process.env : {},
2498
- sandbox: {
2499
- caps,
2500
- moment: moment__default["default"]
2501
- }
2502
- });
2503
- return vm.run(`module.exports = (${code})`);
2504
- } catch (err) {
2505
- throw Error(`func function execution failed - ${err}`);
2506
- }
2507
- },
2508
- numberOfArguments: 1
2509
2464
  }
2510
2465
  };
2511
2466
  const SCRIPTING_FUNCTIONS$1 = lodash__default["default"].mapValues(SCRIPTING_FUNCTIONS_RAW, (funcOrStruct, name) => {
@@ -2514,7 +2469,7 @@ const SCRIPTING_FUNCTIONS$1 = lodash__default["default"].mapValues(SCRIPTING_FUN
2514
2469
  return {
2515
2470
  handler: (caps, ...rest) => {
2516
2471
  if (!caps[Capabilities.SECURITY_ALLOW_UNSAFE] && funcOrStruct.unsafe) {
2517
- throw new BotiumError$5(`Security Error. Using unsafe scripting memory function ${name} is not allowed`, {
2472
+ throw new BotiumError$3(`Security Error. Using unsafe scripting memory function ${name} is not allowed`, {
2518
2473
  type: 'security',
2519
2474
  subtype: 'allow unsafe',
2520
2475
  source: path__default["default"].basename(__filename),
@@ -2654,7 +2609,7 @@ ScriptingMemory.SCRIPTING_FUNCTIONS;
2654
2609
 
2655
2610
  const debug$j = debug__default["default"]('botium-core-Convo');
2656
2611
  const {
2657
- BotiumError: BotiumError$4,
2612
+ BotiumError: BotiumError$2,
2658
2613
  botiumErrorFromErr: botiumErrorFromErr$1,
2659
2614
  botiumErrorFromList: botiumErrorFromList$1
2660
2615
  } = BotiumError_1;
@@ -3078,6 +3033,7 @@ class Convo$6 {
3078
3033
  throw failErr;
3079
3034
  }
3080
3035
  } else if (convoStep.sender === 'bot') {
3036
+ const previousWaitForBotSays = waitForBotSays;
3081
3037
  if (waitForBotSays) {
3082
3038
  botMsg = null;
3083
3039
  } else {
@@ -3133,16 +3089,25 @@ class Convo$6 {
3133
3089
  } catch (failErr) {}
3134
3090
  throw failErr;
3135
3091
  }
3136
- if (convoStep.skip === true) {
3137
- skipTranscriptStep = true;
3092
+ if (convoStep.conditional) {
3138
3093
  const nextConvoStep = this.conversation[i + 1];
3139
- if (nextConvoStep && nextConvoStep.sender === 'bot') {
3140
- waitForBotSays = false;
3094
+ if (!previousWaitForBotSays) {
3095
+ skipTranscriptStep = true;
3096
+ }
3097
+ waitForBotSays = false;
3098
+ if (!nextConvoStep || nextConvoStep.sender !== 'bot' || !nextConvoStep.logicHooks || !nextConvoStep.logicHooks.some(lh => lh.name.toUpperCase().startsWith('CONDITIONAL_STEP'))) {
3099
+ waitForBotSays = true;
3100
+ } else {
3101
+ const conditionalLogicHook = convoStep.logicHooks.find(lh => lh.name.startsWith('CONDITIONAL_STEP'));
3102
+ const nextConditionalLogicHook = nextConvoStep.logicHooks.find(lh => lh.name.startsWith('CONDITIONAL_STEP'));
3103
+ waitForBotSays = conditionalLogicHook.args[1] !== nextConditionalLogicHook.args[1];
3104
+ }
3105
+ if (convoStep.conditional.skip) {
3106
+ continue;
3141
3107
  }
3142
- continue;
3143
3108
  }
3144
3109
  if (!botMsg || !botMsg.messageText && !botMsg.media && !botMsg.buttons && !botMsg.cards && !botMsg.sourceData && !botMsg.nlp) {
3145
- const failErr = new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot says nothing`);
3110
+ const failErr = new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot says nothing`);
3146
3111
  debug$j(failErr);
3147
3112
  try {
3148
3113
  this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
@@ -3228,7 +3193,7 @@ class Convo$6 {
3228
3193
  try {
3229
3194
  this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
3230
3195
  } catch (failErr) {}
3231
- if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS] && err instanceof BotiumError$4) {
3196
+ if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS] && err instanceof BotiumError$2) {
3232
3197
  assertErrors.push(err);
3233
3198
  } else {
3234
3199
  throw failErr;
@@ -3244,7 +3209,7 @@ class Convo$6 {
3244
3209
  }
3245
3210
  }
3246
3211
  } else {
3247
- const failErr = new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: invalid sender - ${util__default["default"].inspect(convoStep.sender)}`);
3212
+ const failErr = new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: invalid sender - ${util__default["default"].inspect(convoStep.sender)}`);
3248
3213
  debug$j(failErr);
3249
3214
  try {
3250
3215
  this.scriptingEvents.fail && this.scriptingEvents.fail(failErr);
@@ -3253,7 +3218,7 @@ class Convo$6 {
3253
3218
  }
3254
3219
  } catch (err) {
3255
3220
  if (lastMeConvoStep) {
3256
- if (err instanceof BotiumError$4 && err.context) {
3221
+ if (err instanceof BotiumError$2 && err.context) {
3257
3222
  err.context.input = new ConvoStep$1(lastMeConvoStep);
3258
3223
  err.context.transcript = [...transcriptSteps, {
3259
3224
  ...transcriptStep
@@ -3266,7 +3231,7 @@ class Convo$6 {
3266
3231
  }
3267
3232
  }
3268
3233
  transcriptStep.err = err;
3269
- if (err instanceof BotiumError$4 && container.caps[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]) {
3234
+ if (err instanceof BotiumError$2 && container.caps[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]) {
3270
3235
  if (!err.isAsserterError()) {
3271
3236
  throw err;
3272
3237
  }
@@ -3299,10 +3264,10 @@ class Convo$6 {
3299
3264
  if (expected === null || expected === undefined) return;
3300
3265
  if (lodash__default["default"].isArray(expected)) {
3301
3266
  if (!lodash__default["default"].isArray(result)) {
3302
- throw new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot response expected array, got "${result}"`);
3267
+ throw new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot response expected array, got "${result}"`);
3303
3268
  }
3304
3269
  if (expected.length !== result.length) {
3305
- throw new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot response expected array length ${expected.length}, got ${result.length}`);
3270
+ throw new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot response expected array length ${expected.length}, got ${result.length}`);
3306
3271
  }
3307
3272
  for (let i = 0; i < expected.length; i++) {
3308
3273
  this._compareObject(container, scriptingMemory, convoStep, result[i], expected[i]);
@@ -3312,7 +3277,7 @@ class Convo$6 {
3312
3277
  if (Object.prototype.hasOwnProperty.call(result, key)) {
3313
3278
  this._compareObject(container, scriptingMemory, convoStep, result[key], expected[key]);
3314
3279
  } else {
3315
- throw new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot response "${result}" missing expected property: ${key}`);
3280
+ throw new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot response "${result}" missing expected property: ${key}`);
3316
3281
  }
3317
3282
  });
3318
3283
  } else {
@@ -3441,14 +3406,14 @@ class Convo$6 {
3441
3406
  includeLogicHooks.forEach(includeLogicHook => {
3442
3407
  const alreadyThereAt = parentPConvos.indexOf(includeLogicHook);
3443
3408
  if (alreadyThereAt >= 0) {
3444
- throw new BotiumError$4(`Partial convos are included circular. "${includeLogicHook}" is referenced by "/${parentPConvos.slice(0, alreadyThereAt).join('/')}" and by "/${parentPConvos.join('/')}" `);
3409
+ throw new BotiumError$2(`Partial convos are included circular. "${includeLogicHook}" is referenced by "/${parentPConvos.slice(0, alreadyThereAt).join('/')}" and by "/${parentPConvos.join('/')}" `);
3445
3410
  }
3446
3411
  if (!partialConvos || Object.keys(partialConvos).length === 0) {
3447
- throw new BotiumError$4(`Cant find partial convo with name ${includeLogicHook} (There are no partial convos)`);
3412
+ throw new BotiumError$2(`Cant find partial convo with name ${includeLogicHook} (There are no partial convos)`);
3448
3413
  }
3449
3414
  const partialConvo = partialConvos[includeLogicHook];
3450
3415
  if (!partialConvo) {
3451
- throw new BotiumError$4(`Cant find partial convo with name ${includeLogicHook} (available partial convos: ${Object.keys(partialConvos).join(',')})`);
3416
+ throw new BotiumError$2(`Cant find partial convo with name ${includeLogicHook} (available partial convos: ${Object.keys(partialConvos).join(',')})`);
3452
3417
  }
3453
3418
  _getEffectiveConversationRecursive(partialConvo.conversation, [...parentPConvos, includeLogicHook], result, true);
3454
3419
  debug$j(`Partial convo ${includeLogicHook} included`);
@@ -3783,44 +3748,21 @@ var JsonToJson = {
3783
3748
  precompile: precompile$2
3784
3749
  };
3785
3750
 
3786
- const {
3787
- NodeVM
3788
- } = vm2__default["default"];
3789
3751
  const debug$h = debug__default["default"]('botium-core-HookUtils');
3790
- const {
3791
- BotiumError: BotiumError$3
3792
- } = BotiumError_1;
3793
- const executeHook$2 = async (caps, hook, args) => {
3794
- return executeHookSync$1(caps, hook, args);
3752
+ const executeHook$2 = async (caps, hook, ...args) => {
3753
+ return executeHookSync$1(caps, hook, ...args);
3795
3754
  };
3796
- const executeHookSync$1 = (caps, hook, args) => {
3755
+ const executeHookSync$1 = (caps, hook, ...args) => {
3797
3756
  if (!hook) {
3798
3757
  return;
3799
3758
  }
3800
3759
  if (lodash__default["default"].isFunction(hook)) {
3801
3760
  try {
3802
- return hook(args);
3761
+ return hook(...args);
3803
3762
  } catch (err) {
3804
3763
  throw new Error(`Calling Hook function failed: ${err.message}`);
3805
3764
  }
3806
3765
  }
3807
- if (lodash__default["default"].isString(hook)) {
3808
- try {
3809
- const vm = new NodeVM({
3810
- eval: false,
3811
- require: false,
3812
- sandbox: args
3813
- });
3814
- const r = vm.run(hook);
3815
- if (lodash__default["default"].isFunction(r)) {
3816
- return r(args);
3817
- } else {
3818
- return r;
3819
- }
3820
- } catch (err) {
3821
- throw new Error(`Calling Hook Javascript code failed: ${err.message}`);
3822
- }
3823
- }
3824
3766
  throw new Error(`Unknown hook ${typeof hook}`);
3825
3767
  };
3826
3768
  const getHook$3 = (caps, data) => {
@@ -3833,46 +3775,40 @@ const getHook$3 = (caps, data) => {
3833
3775
  return data;
3834
3776
  }
3835
3777
  if (lodash__default["default"].isString(data)) {
3836
- let resultWithRequire;
3837
- let tryLoadFile = path__default["default"].resolve(process.cwd(), data);
3838
- if (fs__default["default"].existsSync(tryLoadFile)) {
3839
- try {
3840
- resultWithRequire = commonjsRequire(tryLoadFile);
3841
- } catch (err) {}
3842
- } else {
3843
- tryLoadFile = data;
3844
- try {
3845
- resultWithRequire = commonjsRequire(data);
3846
- } catch (err) {}
3847
- }
3848
- if (resultWithRequire) {
3849
- if (!allowUnsafe) {
3850
- throw new BotiumError$3('Security Error. Using unsafe custom hook with require is not allowed', {
3851
- type: 'security',
3852
- subtype: 'allow unsafe',
3853
- source: path__default["default"].basename(__filename),
3854
- cause: {
3855
- SECURITY_ALLOW_UNSAFE: caps[Capabilities.SECURITY_ALLOW_UNSAFE],
3856
- hookData: data
3778
+ if (caps.SAFEDIR) {
3779
+ const tryLoadFile = path__default["default"].resolve(caps.SAFEDIR, data);
3780
+ if (tryLoadFile.startsWith(path__default["default"].resolve(caps.SAFEDIR))) {
3781
+ if (fs__default["default"].existsSync(tryLoadFile)) {
3782
+ try {
3783
+ const resultWithRequire = commonjsRequire(tryLoadFile);
3784
+ if (lodash__default["default"].isFunction(resultWithRequire)) {
3785
+ debug$h(`found hook, type: safedir, in ${tryLoadFile}`);
3786
+ return resultWithRequire;
3787
+ } else {
3788
+ throw new Error(`Expected function from hook specification "${util__default["default"].inspect(data)}", got: "${util__default["default"].inspect(resultWithRequire)}"`);
3789
+ }
3790
+ } catch (err) {
3791
+ debug$h(`Failed loading hook, type: safedir, from ${tryLoadFile} failed: ${err.message || err}`);
3857
3792
  }
3858
- });
3859
- }
3860
- if (lodash__default["default"].isFunction(resultWithRequire)) {
3861
- debug$h(`found hook, type: require, in ${tryLoadFile}`);
3862
- return resultWithRequire;
3863
- } else {
3864
- throw new Error(`Cant load hook ${tryLoadFile} because it is not a function`);
3793
+ }
3865
3794
  }
3866
3795
  }
3867
- try {
3868
- esprima__default["default"].parseScript(data);
3869
- } catch (err) {
3870
- throw new Error(`Cant load hook, syntax is not valid - ${util__default["default"].inspect(err)}`);
3796
+ if (allowUnsafe || data.startsWith('botium-')) {
3797
+ const tryLoadFile = data;
3798
+ try {
3799
+ const resultWithRequire = commonjsRequire(tryLoadFile);
3800
+ if (lodash__default["default"].isFunction(resultWithRequire)) {
3801
+ debug$h(`found hook, type: require, in ${tryLoadFile}`);
3802
+ return resultWithRequire;
3803
+ } else {
3804
+ throw new Error(`Expected function from hook specification "${util__default["default"].inspect(data)}", got: "${util__default["default"].inspect(resultWithRequire)}"`);
3805
+ }
3806
+ } catch (err) {
3807
+ debug$h(`Failed loading hook, type: require, from ${tryLoadFile} failed: ${err.message || err}`);
3808
+ }
3871
3809
  }
3872
- debug$h('Found hook, type: JavaScript as String');
3873
- return data;
3874
3810
  }
3875
- throw new Error(`Not valid hook ${util__default["default"].inspect(data)}`);
3811
+ throw new Error(`Hook specification "${util__default["default"].inspect(data)}" invalid: no loader available`);
3876
3812
  };
3877
3813
  var HookUtils = {
3878
3814
  getHook: getHook$3,
@@ -5368,7 +5304,7 @@ const {
5368
5304
  ConvoStep
5369
5305
  } = Convo_1;
5370
5306
  const {
5371
- BotiumError: BotiumError$2,
5307
+ BotiumError: BotiumError$1,
5372
5308
  botiumErrorFromList,
5373
5309
  botiumErrorFromErr
5374
5310
  } = BotiumError_1;
@@ -5644,7 +5580,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5644
5580
  const werArgs = this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS];
5645
5581
  const threshold = [',', '.'].find(p => `${werArgs[0]}`.includes(p)) ? parseFloat(werArgs[0]) : parseInt(werArgs[0]) / 100;
5646
5582
  const message = `${stepTag}: Word Error Rate (${toPercent(wer)}) higher than accepted (${toPercent(threshold)})`;
5647
- throw new BotiumError$2(message, {
5583
+ throw new BotiumError$1(message, {
5648
5584
  type: 'asserter',
5649
5585
  source: asserterType,
5650
5586
  params: {
@@ -5666,7 +5602,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5666
5602
  message += ' expected to match ';
5667
5603
  message += tomatch && tomatch.length > 1 ? 'one of ' : '';
5668
5604
  message += `${tomatch.map(e => e ? '"' + e + '"' : '<any response>').join(', ')}`;
5669
- throw new BotiumError$2(message, {
5605
+ throw new BotiumError$1(message, {
5670
5606
  type: 'asserter',
5671
5607
  source: asserterType,
5672
5608
  params: {
@@ -5699,7 +5635,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5699
5635
  const werArgs = this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS];
5700
5636
  const threshold = [',', '.'].find(p => `${werArgs[0]}`.includes(p)) ? parseFloat(werArgs[0]) : parseInt(werArgs[0]) / 100;
5701
5637
  const message = `${stepTag}: Word Error Rate (${toPercent(wer)}) lower than accepted (${toPercent(threshold)})`;
5702
- throw new BotiumError$2(message, {
5638
+ throw new BotiumError$1(message, {
5703
5639
  type: 'asserter',
5704
5640
  source: asserterType,
5705
5641
  params: {
@@ -5721,7 +5657,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5721
5657
  message += ' expected NOT to match ';
5722
5658
  message += nottomatch && nottomatch.length > 1 ? 'one of ' : '';
5723
5659
  message += `${nottomatch.map(e => e ? '"' + e + '"' : '<any response>').join(', ')}`;
5724
- throw new BotiumError$2(message, {
5660
+ throw new BotiumError$1(message, {
5725
5661
  type: 'asserter',
5726
5662
  source: asserterType,
5727
5663
  params: {
@@ -5771,7 +5707,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5771
5707
  if (asserter[notAsserterType]) {
5772
5708
  return p(this.retryHelperAsserter, () => asserter[notAsserterType](params));
5773
5709
  } else {
5774
- return pnot(this.retryHelperAsserter, () => asserter[asserterType](params), new BotiumError$2(`${convoStep.stepTag}: Expected asserter ${asserter.name || asserterSpec.name} with args "${params.args}" to fail`, {
5710
+ return pnot(this.retryHelperAsserter, () => asserter[asserterType](params), new BotiumError$1(`${convoStep.stepTag}: Expected asserter ${asserter.name || asserterSpec.name} with args "${params.args}" to fail`, {
5775
5711
  type: 'asserter',
5776
5712
  source: asserter.name || asserterSpec.name,
5777
5713
  params: {
@@ -6166,7 +6102,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6166
6102
  return !entry.header.name;
6167
6103
  });
6168
6104
  if (aggregatedNoNames.length) {
6169
- throw new BotiumError$2('Scripting Memory Definition(s) without name', {
6105
+ throw new BotiumError$1('Scripting Memory Definition(s) without name', {
6170
6106
  type: 'Scripting Memory',
6171
6107
  subtype: 'Scripting Memory without name',
6172
6108
  source: 'ScriptingProvider',
@@ -6181,7 +6117,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6181
6117
  return !entry.values || !Object.keys(entry.values).length;
6182
6118
  });
6183
6119
  if (aggregatedNoVariables.length) {
6184
- throw new BotiumError$2(`Scripting Memory Definition(s) ${aggregatedNoVariables.map(e => e.header.name).join(', ')} without variable`, {
6120
+ throw new BotiumError$1(`Scripting Memory Definition(s) ${aggregatedNoVariables.map(e => e.header.name).join(', ')} without variable`, {
6185
6121
  type: 'Scripting Memory',
6186
6122
  subtype: 'Scripting Memory without variable',
6187
6123
  source: 'ScriptingProvider',
@@ -6196,7 +6132,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6196
6132
  return !lodash__default["default"].isUndefined(entry.values['']);
6197
6133
  });
6198
6134
  if (aggregatedNoVariableNames.length) {
6199
- throw new BotiumError$2(`Scripting Memory Definition(s) ${aggregatedNoVariableNames.map(e => e.header.name).join(', ')} without variable name`, {
6135
+ throw new BotiumError$1(`Scripting Memory Definition(s) ${aggregatedNoVariableNames.map(e => e.header.name).join(', ')} without variable name`, {
6200
6136
  type: 'Scripting Memory',
6201
6137
  subtype: 'Scripting Memory without variable name',
6202
6138
  source: 'ScriptingProvider',
@@ -6224,7 +6160,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6224
6160
  }
6225
6161
  }
6226
6162
  if (aggregatedDuplicates.length) {
6227
- throw new BotiumError$2(`Scripting Memory Definition name(s) "${lodash__default["default"].uniq(aggregatedDuplicates.map(d => d.scriptingMemory.header.name)).join(', ')}" are not unique`, {
6163
+ throw new BotiumError$1(`Scripting Memory Definition name(s) "${lodash__default["default"].uniq(aggregatedDuplicates.map(d => d.scriptingMemory.header.name)).join(', ')}" are not unique`, {
6228
6164
  type: 'Scripting Memory',
6229
6165
  subtype: 'Scripting Memory name collision',
6230
6166
  source: 'ScriptingProvider',
@@ -6255,7 +6191,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6255
6191
  }
6256
6192
  }
6257
6193
  if (aggregatedIntersections.length) {
6258
- throw new BotiumError$2(`Scripting Memory Definitions "${aggregatedIntersections.map(i => i.scriptingMemory.header.name).join(', ')}" are invalid because variable name collision"`, {
6194
+ throw new BotiumError$1(`Scripting Memory Definitions "${aggregatedIntersections.map(i => i.scriptingMemory.header.name).join(', ')}" are invalid because variable name collision"`, {
6259
6195
  type: 'Scripting Memory',
6260
6196
  subtype: 'Scripting Memory variable name collision',
6261
6197
  source: 'ScriptingProvider',
@@ -6818,7 +6754,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6818
6754
  }
6819
6755
  } else if (scriptingMemories) {
6820
6756
  if (!scriptingMemories.header || !scriptingMemories.header.name) {
6821
- throw new BotiumError$2('Scripting Memory Definition has no name', {
6757
+ throw new BotiumError$1('Scripting Memory Definition has no name', {
6822
6758
  type: 'Compiler',
6823
6759
  subtype: 'Scripting memory without name',
6824
6760
  source: 'ScriptingProvider',
@@ -6828,7 +6764,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6828
6764
  });
6829
6765
  }
6830
6766
  if (!scriptingMemories.values || !Object.keys(scriptingMemories.values).length) {
6831
- throw new BotiumError$2('Scripting Memory Definition has no variables', {
6767
+ throw new BotiumError$1('Scripting Memory Definition has no variables', {
6832
6768
  type: 'Compiler',
6833
6769
  subtype: 'Scripting memory without variable',
6834
6770
  source: 'ScriptingProvider',
@@ -6838,7 +6774,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6838
6774
  });
6839
6775
  }
6840
6776
  if (scriptingMemories.values && !lodash__default["default"].isUndefined(scriptingMemories.values[''])) {
6841
- throw new BotiumError$2('Scripting Memory Definition variable has no name', {
6777
+ throw new BotiumError$1('Scripting Memory Definition variable has no name', {
6842
6778
  type: 'Compiler',
6843
6779
  subtype: 'Scripting memory without variable name',
6844
6780
  source: 'ScriptingProvider',
@@ -7725,7 +7661,7 @@ const {
7725
7661
  escapeJSONString
7726
7662
  } = Utils;
7727
7663
  const {
7728
- BotiumError: BotiumError$1
7664
+ BotiumError
7729
7665
  } = BotiumError_1;
7730
7666
  mustache__default["default"].escape = s => s;
7731
7667
  var SimpleRestContainer_1 = class SimpleRestContainer {
@@ -8022,22 +7958,32 @@ var SimpleRestContainer_1 = class SimpleRestContainer {
8022
7958
  }
8023
7959
  const result = [];
8024
7960
  if (isFromUser) {
8025
- const _extractFrom = (root, jsonPaths) => {
8026
- const flattened = [];
7961
+ const _extractFrom = (root, jsonPaths, acceptFn = null) => {
7962
+ const result = [];
8027
7963
  for (const jsonPath of jsonPaths) {
7964
+ const jsonPathRes = [];
8028
7965
  const rb = jsonpath__default["default"].query(root, jsonPath);
8029
7966
  if (lodash__default["default"].isArray(rb)) {
8030
- lodash__default["default"].flattenDeep(rb).forEach(r => flattened.push(r));
8031
- } else if (rb) {
8032
- flattened.push(rb);
7967
+ lodash__default["default"].flattenDeep(rb).forEach(r => jsonPathRes.push(r));
7968
+ } else {
7969
+ jsonPathRes.push(rb);
7970
+ }
7971
+ if (acceptFn) {
7972
+ result.push(...jsonPathRes.filter(r => acceptFn(root, jsonPath, r)));
7973
+ } else {
7974
+ result.push(...jsonPathRes);
8033
7975
  }
8034
7976
  }
8035
- return flattened;
7977
+ return result;
8036
7978
  };
8037
7979
  const jsonPathRoots = [];
8038
7980
  const jsonPathsBody = getAllCapValues(Capabilities.SIMPLEREST_BODY_JSONPATH, this.caps);
8039
7981
  if (jsonPathsBody.length > 0) {
8040
- jsonPathRoots.push(..._extractFrom(body, jsonPathsBody));
7982
+ jsonPathRoots.push(..._extractFrom(body, jsonPathsBody, (root, jsonPath, r) => {
7983
+ if (r && lodash__default["default"].isObject(r)) return true;
7984
+ debug$4(`Ignoring result body from ${jsonPath} - not a querieable object (${util__default["default"].inspect(r)})`);
7985
+ return false;
7986
+ }));
8041
7987
  } else {
8042
7988
  jsonPathRoots.push(body);
8043
7989
  }
@@ -8196,7 +8142,7 @@ var SimpleRestContainer_1 = class SimpleRestContainer {
8196
8142
  const jsonBody = Utils.toJsonWeak(body);
8197
8143
  const errKey = Object.keys(jsonBody).find(k => k.startsWith('err') || k.startsWith('fail'));
8198
8144
  if (errKey) {
8199
- return reject(new BotiumError$1(`got error response: ${response.statusCode}/${response.statusMessage} - ${jsonBody[errKey]}`, {
8145
+ return reject(new BotiumError(`got error response: ${response.statusCode}/${response.statusMessage} - ${jsonBody[errKey]}`, {
8200
8146
  message: Utils.shortenJsonString(body)
8201
8147
  }));
8202
8148
  }
@@ -8651,9 +8597,6 @@ var SimpleRestContainer_1 = class SimpleRestContainer {
8651
8597
  };
8652
8598
 
8653
8599
  const debug$3 = debug__default["default"]('botium-connector-PluginConnectorContainer-helper');
8654
- const {
8655
- BotiumError
8656
- } = BotiumError_1;
8657
8600
  const pluginResolver = containermode => {
8658
8601
  if (containermode === 'simplerest') {
8659
8602
  return SimpleRestContainer_1;
@@ -8704,20 +8647,6 @@ const loadConnectorModule = (PluginClass, args) => {
8704
8647
  };
8705
8648
  const tryLoadPlugin$1 = (containermode, modulepath, args) => {
8706
8649
  const pluginLoaderSpec = modulepath || containermode;
8707
- const _checkUnsafe = (caps, mode, cause) => {
8708
- if (!caps[Capabilities.SECURITY_ALLOW_UNSAFE]) {
8709
- throw new BotiumError(`Security Error. Using unsafe connector mode "${mode}" is not allowed`, {
8710
- type: 'security',
8711
- subtype: 'allow unsafe',
8712
- source: 'src/containers/plugins/index.js',
8713
- cause: {
8714
- SECURITY_ALLOW_UNSAFE: caps[Capabilities.SECURITY_ALLOW_UNSAFE],
8715
- mode,
8716
- ...cause
8717
- }
8718
- });
8719
- }
8720
- };
8721
8650
  if (pluginResolver(pluginLoaderSpec)) {
8722
8651
  const pluginInstance = new (pluginResolver(pluginLoaderSpec))(args);
8723
8652
  debug$3('Botium plugin loaded from internal plugin resolver');
@@ -8729,44 +8658,47 @@ const tryLoadPlugin$1 = (containermode, modulepath, args) => {
8729
8658
  return pluginInstance;
8730
8659
  }
8731
8660
  const loadErr = [];
8661
+ const allowUnsafe = !!args.caps[Capabilities.SECURITY_ALLOW_UNSAFE];
8732
8662
  if (lodash__default["default"].isString(pluginLoaderSpec)) {
8733
- const tryLoadFile = path__default["default"].resolve(process.cwd(), pluginLoaderSpec);
8734
- if (fs__default["default"].existsSync(tryLoadFile)) {
8735
- _checkUnsafe(args.caps, 'Using work dir', {
8736
- modulepath,
8737
- containermode
8738
- });
8663
+ if (args.caps.SAFEDIR) {
8664
+ const tryLoadFile = path__default["default"].resolve(args.caps.SAFEDIR, pluginLoaderSpec);
8665
+ if (tryLoadFile.startsWith(path__default["default"].resolve(args.caps.SAFEDIR))) {
8666
+ if (fs__default["default"].existsSync(tryLoadFile)) {
8667
+ try {
8668
+ let plugin = commonjsRequire(tryLoadFile);
8669
+ if (plugin.default) {
8670
+ plugin = plugin.default;
8671
+ }
8672
+ if (!plugin.PluginVersion || !plugin.PluginClass) {
8673
+ loadErr.push(`Invalid Botium plugin loaded from ${tryLoadFile}, expected PluginVersion, PluginClass fields`);
8674
+ } else {
8675
+ const pluginInstance = loadConnectorModule(plugin.PluginClass, args);
8676
+ debug$3(`Botium plugin loaded from ${tryLoadFile}`);
8677
+ return pluginInstance;
8678
+ }
8679
+ } catch (err) {
8680
+ loadErr.push(`Loading Botium plugin from ${tryLoadFile} failed - ${err.message}`);
8681
+ }
8682
+ }
8683
+ }
8684
+ }
8685
+ if (allowUnsafe) {
8739
8686
  try {
8740
- let plugin = commonjsRequire(tryLoadFile);
8687
+ let plugin = commonjsRequire(pluginLoaderSpec);
8741
8688
  if (plugin.default) {
8742
8689
  plugin = plugin.default;
8743
8690
  }
8744
8691
  if (!plugin.PluginVersion || !plugin.PluginClass) {
8745
- loadErr.push(`Invalid Botium plugin loaded from ${tryLoadFile}, expected PluginVersion, PluginClass fields`);
8692
+ loadErr.push(`Invalid Botium plugin loaded from ${pluginLoaderSpec}, expected PluginVersion, PluginClass fields`);
8746
8693
  } else {
8747
8694
  const pluginInstance = loadConnectorModule(plugin.PluginClass, args);
8748
- debug$3(`Botium plugin loaded from ${tryLoadFile}`);
8695
+ debug$3(`Botium plugin loaded from ${pluginLoaderSpec}. Plugin version is ${getModuleVersionSafe(pluginLoaderSpec)}`);
8749
8696
  return pluginInstance;
8750
8697
  }
8751
8698
  } catch (err) {
8752
- loadErr.push(`Loading Botium plugin from ${tryLoadFile} failed - ${err.message}`);
8699
+ loadErr.push(`Loading Botium plugin from ${pluginLoaderSpec} failed - ${err.message}`);
8753
8700
  }
8754
8701
  }
8755
- try {
8756
- let plugin = commonjsRequire(pluginLoaderSpec);
8757
- if (plugin.default) {
8758
- plugin = plugin.default;
8759
- }
8760
- if (!plugin.PluginVersion || !plugin.PluginClass) {
8761
- loadErr.push(`Invalid Botium plugin loaded from ${pluginLoaderSpec}, expected PluginVersion, PluginClass fields`);
8762
- } else {
8763
- const pluginInstance = loadConnectorModule(plugin.PluginClass, args);
8764
- debug$3(`Botium plugin loaded from ${pluginLoaderSpec}. Plugin version is ${getModuleVersionSafe(pluginLoaderSpec)}`);
8765
- return pluginInstance;
8766
- }
8767
- } catch (err) {
8768
- loadErr.push(`Loading Botium plugin from ${pluginLoaderSpec} failed - ${err.message}`);
8769
- }
8770
8702
  const tryLoadPackage = `botium-connector-${pluginLoaderSpec}`;
8771
8703
  try {
8772
8704
  let plugin = commonjsRequire(tryLoadPackage);
@@ -8930,6 +8862,13 @@ var PluginConnectorContainer_1 = class PluginConnectorContainer extends BaseCont
8930
8862
  return Promise.reject(new Error(`Clean - Botium plugin failed: ${util__default["default"].inspect(err)}`));
8931
8863
  }
8932
8864
  }
8865
+ GetMetaData() {
8866
+ try {
8867
+ return this.pluginInstance.GetMetaData ? this.pluginInstance.GetMetaData() || Promise.resolve() : Promise.resolve();
8868
+ } catch (err) {
8869
+ return Promise.reject(new Error(`GetMetaData - Botium plugin failed: ${util__default["default"].inspect(err)}`));
8870
+ }
8871
+ }
8933
8872
  };
8934
8873
 
8935
8874
  var require$$3 = getCjsExportFromNamespace(_package$1);