botium-core 1.13.19 → 1.14.1

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 (41) hide show
  1. package/dist/botium-cjs.js +328 -395
  2. package/dist/botium-cjs.js.map +1 -1
  3. package/dist/botium-es.js +328 -393
  4. package/dist/botium-es.js.map +1 -1
  5. package/package.json +24 -29
  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 +26 -9
  15. package/src/scripting/ScriptingMemory.js +0 -24
  16. package/src/scripting/logichook/LogicHookUtils.js +27 -47
  17. package/src/scripting/logichook/logichooks/ConditionalBusinessHoursLogicHook.js +1 -1
  18. package/src/scripting/logichook/logichooks/ConditionalCapabilityValueBasedLogicHook.js +1 -1
  19. package/src/scripting/logichook/logichooks/ConditionalJsonPathBasedLogicHook.js +1 -1
  20. package/src/scripting/logichook/logichooks/ConditionalTimeBasedLogicHook.js +1 -1
  21. package/test/compiler/precompilerscript.spec.js +24 -26
  22. package/test/connectors/pluginconnectorcontainer.spec.js +60 -0
  23. package/test/connectors/simplerest.spec.js +24 -27
  24. package/test/convo/fillAndApplyScriptingMemory.spec.js +1 -47
  25. package/test/hooks/customhooks.spec.js +3 -25
  26. package/test/logichooks/hookfromsrc.spec.js +13 -3
  27. package/test/plugins/plugins.spec.js +29 -2
  28. package/test/scripting/logichooks/convos/conditional_steps_multiple_condition_groups_no_assertion.convo.txt +6 -6
  29. package/test/scripting/logichooks/convos/conditional_steps_multiple_mandatory_condition_groups.convo.txt +20 -0
  30. package/test/scripting/logichooks/convos/conditional_steps_multiple_optional_condition_groups.convo.txt +20 -0
  31. package/test/scripting/logichooks/customConditionalStepLogicHook.spec.js +16 -0
  32. package/test/security/allowUnsafe.spec.js +20 -129
  33. package/LICENSES-3RDPARTY.txt +0 -6450
  34. package/test/scripting/asserters/convos/customembeddedasserterwithhugo.convo.txt +0 -7
  35. package/test/scripting/asserters/convos/customembeddedasserterwithouthugo.convo.txt +0 -7
  36. package/test/scripting/asserters/customEmbeddedAsserter.json +0 -14
  37. package/test/scripting/asserters/customEmbeddedAsserter.spec.js +0 -55
  38. package/test/scripting/logichooks/convos/custom_embedded.convo.txt +0 -8
  39. package/test/scripting/logichooks/customEmbedded.json +0 -14
  40. package/test/scripting/logichooks/customEmbedded.spec.js +0 -44
  41. package/test/security/convos/withscriptingmemoryfunction.convo.txt +0 -5
package/dist/botium-es.js CHANGED
@@ -11,7 +11,6 @@ import lodash from 'lodash';
11
11
  import boolean$1 from 'boolean';
12
12
  import events from 'events';
13
13
  import debug$n from 'debug';
14
- import vm2 from 'vm2';
15
14
  import isClass from 'is-class';
16
15
  import crypto from 'crypto';
17
16
  import globby from 'globby';
@@ -21,7 +20,6 @@ import uuid from 'uuid';
21
20
  import jsonpath from 'jsonpath';
22
21
  import isJson$1 from 'is-json';
23
22
  import wordErrorRate from 'word-error-rate';
24
- import esprima from 'esprima';
25
23
  import markdownIt from 'markdown-it';
26
24
  import xlsx from 'xlsx';
27
25
  import sync from 'csv-parse/sync';
@@ -37,7 +35,7 @@ import express from 'express';
37
35
  import bodyParser from 'body-parser';
38
36
 
39
37
  var name = "botium-core";
40
- var version$1 = "1.13.19";
38
+ var version$1 = "1.14.1";
41
39
  var description = "The Selenium for Chatbots";
42
40
  var main = "index.js";
43
41
  var module = "dist/botium-es.js";
@@ -55,7 +53,6 @@ var scripts = {
55
53
  link: "npm link botium-connector-dialogflow botium-connector-webdriverio botium-connector-directline3 botium-connector-watson botium-connector-alexa-smapi botium-connector-echo",
56
54
  test: "cross-env NODE_PATH=\"./test/plugins/plugindir/fromfolder:./test/plugins/plugindir/fromfile:./test/security/resources\" mocha \"./test/**/*.spec.js\"",
57
55
  "coverage:report": "nyc report --reporter=lcov npm test",
58
- "license-checker": "license-checker > LICENSES-3RDPARTY.txt",
59
56
  "update-dependencies": "npm-check-updates --reject globby,rollup -u --timeout 120000"
60
57
  };
61
58
  var repository = {
@@ -69,14 +66,13 @@ var bugs = {
69
66
  };
70
67
  var homepage = "https://www.botium.ai";
71
68
  var dependencies = {
72
- "@babel/runtime": "^7.21.5",
73
- async: "^3.2.4",
69
+ "@babel/runtime": "^7.23.2",
70
+ async: "^3.2.5",
74
71
  "body-parser": "^1.20.2",
75
72
  boolean: "^3.2.0",
76
73
  bottleneck: "^2.19.5",
77
- "csv-parse": "^5.3.10",
74
+ "csv-parse": "^5.5.2",
78
75
  debug: "^4.3.4",
79
- esprima: "^4.0.1",
80
76
  express: "^4.18.2",
81
77
  globby: "11.0.4",
82
78
  ioredis: "^5.3.2",
@@ -84,52 +80,49 @@ var dependencies = {
84
80
  "is-json": "^2.0.1",
85
81
  jsonpath: "^1.1.1",
86
82
  lodash: "^4.17.21",
87
- "markdown-it": "^13.0.1",
83
+ "markdown-it": "^13.0.2",
88
84
  "mime-types": "^2.1.35",
89
85
  mkdirp: "^3.0.1",
90
86
  moment: "^2.29.4",
91
87
  "moment-timezone": "^0.5.43",
92
88
  mustache: "^4.2.0",
93
89
  "promise-retry": "^2.0.1",
94
- "promise.allsettled": "^1.0.6",
90
+ "promise.allsettled": "^1.0.7",
95
91
  randomatic: "^3.1.1",
96
92
  request: "^2.88.2",
97
- rimraf: "^5.0.0",
93
+ rimraf: "^5.0.5",
98
94
  "sanitize-filename": "^1.6.3",
99
95
  slugify: "^1.6.6",
100
- "socket.io": "^4.6.1",
101
- "socket.io-client": "^4.6.1",
96
+ "socket.io": "^4.7.2",
97
+ "socket.io-client": "^4.7.2",
102
98
  "socketio-auth": "^0.1.1",
103
99
  "swagger-jsdoc": "^6.2.8",
104
- "swagger-ui-express": "^4.6.3",
105
- uuid: "^9.0.0",
106
- vm2: "^3.9.17",
100
+ "swagger-ui-express": "^5.0.0",
101
+ uuid: "^9.0.1",
107
102
  "word-error-rate": "0.0.7",
108
103
  "write-yaml": "^1.0.0",
109
104
  xlsx: "^0.18.5",
110
105
  xregexp: "^5.1.1",
111
- yaml: "^2.2.2"
106
+ yaml: "^2.3.4"
112
107
  };
113
108
  var devDependencies = {
114
- "@babel/core": "^7.21.8",
115
- "@babel/node": "^7.20.7",
116
- "@babel/plugin-transform-runtime": "^7.21.4",
117
- "@babel/preset-env": "^7.21.5",
118
- chai: "^4.3.7",
109
+ "@babel/core": "^7.23.3",
110
+ "@babel/node": "^7.22.19",
111
+ "@babel/plugin-transform-runtime": "^7.23.3",
112
+ "@babel/preset-env": "^7.23.3",
113
+ chai: "^4.3.10",
119
114
  "chai-as-promised": "^7.1.1",
120
115
  "cross-env": "^7.0.3",
121
- eslint: "^8.40.0",
122
- "eslint-config-standard": "^17.0.0",
123
- "eslint-plugin-import": "^2.27.5",
124
- "eslint-plugin-mocha": "^10.1.0",
125
- "eslint-plugin-n": "^15.7.0",
116
+ eslint: "^8.53.0",
117
+ "eslint-config-standard": "^17.1.0",
118
+ "eslint-plugin-import": "^2.29.0",
119
+ "eslint-plugin-mocha": "^10.2.0",
120
+ "eslint-plugin-n": "^16.3.1",
126
121
  "eslint-plugin-promise": "^6.1.1",
127
122
  "eslint-plugin-standard": "^4.1.0",
128
- "license-checker": "^25.0.1",
129
- "license-compatibility-checker": "^0.3.5",
130
123
  mocha: "^10.2.0",
131
- nock: "^13.3.1",
132
- "npm-check-updates": "^16.10.12",
124
+ nock: "^13.3.8",
125
+ "npm-check-updates": "^16.14.6",
133
126
  nyc: "^15.1.0",
134
127
  rollup: "2.79.1",
135
128
  "rollup-plugin-babel": "^4.4.0",
@@ -178,6 +171,7 @@ var Capabilities = {
178
171
  TESTSESSIONNAME: 'TESTSESSIONNAME',
179
172
  TESTCASENAME: 'TESTCASENAME',
180
173
  TEMPDIR: 'TEMPDIR',
174
+ SAFEDIR: 'SAFEDIR',
181
175
  CLEANUPTEMPDIR: 'CLEANUPTEMPDIR',
182
176
  WAITFORBOTTIMEOUT: 'WAITFORBOTTIMEOUT',
183
177
  CONTAINERMODE: 'CONTAINERMODE',
@@ -187,7 +181,7 @@ var Capabilities = {
187
181
  BOTIUMGRIDURL: 'BOTIUMGRIDURL',
188
182
  BOTIUMAPITOKEN: 'BOTIUMAPITOKEN',
189
183
  BOTIUMGRIDSLOT: 'BOTIUMGRIDSLOT',
190
- // Simple Reset Bot Settings
184
+ // Simple Rest Bot Settings
191
185
  SIMPLEREST_PING_URL: 'SIMPLEREST_PING_URL',
192
186
  SIMPLEREST_PING_VERB: 'SIMPLEREST_PING_VERB',
193
187
  SIMPLEREST_PING_BODY: 'SIMPLEREST_PING_BODY',
@@ -352,6 +346,7 @@ Capabilities.PROJECTNAME;
352
346
  Capabilities.TESTSESSIONNAME;
353
347
  Capabilities.TESTCASENAME;
354
348
  Capabilities.TEMPDIR;
349
+ Capabilities.SAFEDIR;
355
350
  Capabilities.CLEANUPTEMPDIR;
356
351
  Capabilities.WAITFORBOTTIMEOUT;
357
352
  Capabilities.CONTAINERMODE;
@@ -870,140 +865,6 @@ function getCjsExportFromNamespace (n) {
870
865
  return n && n['default'] || n;
871
866
  }
872
867
 
873
- const BotiumError$7 = class BotiumError extends Error {
874
- /**
875
- *
876
- * @param message
877
- * @param context A JSON with struct
878
- * {
879
- * type: 'some free text to identity the exception type',
880
- * source: 'source of the event',
881
- * ...
882
- */
883
- constructor(message, context, supressChildCheck) {
884
- super(message.message || message);
885
- if (!supressChildCheck && _getChildErrorsFromContext(context)) {
886
- throw Error('Create BotiumError with child errors using the fromList() method!');
887
- }
888
- // Saving class name in the property of our custom error as a shortcut.
889
- this.name = this.constructor.name;
890
-
891
- // Capturing stack trace, excluding constructor call from it.
892
- Error.captureStackTrace(this, this.constructor);
893
- this.context = context || {};
894
- this.context.message = message.message || message;
895
- }
896
- isAsserterError() {
897
- if (this.context) {
898
- const errArr = lodash.isArray(this.context) ? this.context : [this.context];
899
- const hasNotAsserterError = errArr.findIndex(errDetail => {
900
- if (errDetail.type === 'list') {
901
- if (errDetail.errors) {
902
- return errDetail.errors.findIndex(e => e.type !== 'asserter') >= 0;
903
- } else {
904
- return true;
905
- }
906
- } else {
907
- return errDetail.type !== 'asserter';
908
- }
909
- }) >= 0;
910
- if (hasNotAsserterError) return false;
911
- return true;
912
- } else {
913
- return false;
914
- }
915
- }
916
- prettify(includeJson) {
917
- const lines = [];
918
- if (this.context) {
919
- const errArr = lodash.isArray(this.context) ? this.context : [this.context];
920
- errArr.forEach(errDetail => {
921
- lines.push('########################################');
922
- if (errDetail.type === 'asserter') {
923
- const segments = [];
924
- segments.push(`ASSERTION FAILED in ${errDetail.source}${errDetail.subtype ? ` (${errDetail.subtype})` : ''}`);
925
- errDetail.cause && errDetail.cause.expected && !errDetail.cause.not && segments.push(` - Expected: ${JSON.stringify(errDetail.cause.expected)} `);
926
- errDetail.cause && errDetail.cause.expected && errDetail.cause.not && segments.push(` - NOT Expected: ${JSON.stringify(errDetail.cause.expected)} `);
927
- errDetail.cause && errDetail.cause.actual && segments.push(` - Actual: ${JSON.stringify(errDetail.cause.actual)}`);
928
- errDetail.cause && !errDetail.cause.actual && segments.push(' - Actual: empty');
929
- lines.push(segments.join(''));
930
- errDetail.input && errDetail.input.messageText && lines.push(`INPUT: ${errDetail.input.messageText}`);
931
- } else if (errDetail.message) {
932
- lines.push(`${errDetail.message}`);
933
- }
934
- if (errDetail.transcript && errDetail.transcript.length > 0) {
935
- lines.push('------------ TRANSCRIPT ----------------------------');
936
- errDetail.transcript.forEach(transcriptStep => {
937
- if (transcriptStep.actual) {
938
- lines.push(transcriptStep.actual.prettify());
939
- }
940
- });
941
- }
942
- if (includeJson) {
943
- lines.push('------------ JSON CONTENT ----------------------------');
944
- try {
945
- const jsonOutput = JSON.stringify(errDetail);
946
- lines.push(jsonOutput);
947
- } catch (jsonErr) {
948
- lines.push(`JSON Output not possible: ${jsonErr.message}`);
949
- }
950
- }
951
- });
952
- }
953
- if (lines.length > 0) {
954
- return lines.join('\r\n');
955
- } else {
956
- return null;
957
- }
958
- }
959
- };
960
- const _getChildErrorsFromContext = context => {
961
- if (context && context.errors && lodash.isArray(context.errors)) {
962
- return context.errors;
963
- }
964
- return false;
965
- };
966
- const botiumErrorFromErr$2 = (message, err) => {
967
- if (err instanceof BotiumError$7) {
968
- return new BotiumError$7(message, err.context, true);
969
- } else {
970
- return new BotiumError$7(message, {
971
- err
972
- }, true);
973
- }
974
- };
975
- const botiumErrorFromList$2 = (errors, {
976
- type = 'list',
977
- source = 'BotiumError',
978
- flat = true
979
- }) => {
980
- const message = errors.map(err => err.message || err.toString()).join(',\n');
981
- let children = [];
982
- for (const error of errors) {
983
- if (error instanceof BotiumError$7) {
984
- const childErrors = flat && _getChildErrorsFromContext(error.context);
985
- if (childErrors && childErrors.length) {
986
- children = children.concat(childErrors);
987
- } else if (error.context) {
988
- children.push(error.context);
989
- }
990
- } else {
991
- children.push(error);
992
- }
993
- }
994
- const result = new BotiumError$7(message, {
995
- errors: children,
996
- type,
997
- source
998
- }, true);
999
- return result;
1000
- };
1001
- var BotiumError_1 = {
1002
- BotiumError: BotiumError$7,
1003
- botiumErrorFromErr: botiumErrorFromErr$2,
1004
- botiumErrorFromList: botiumErrorFromList$2
1005
- };
1006
-
1007
868
  const LOGIC_HOOK_INCLUDE$1 = 'INCLUDE';
1008
869
  var LogicHookConsts = {
1009
870
  LOGIC_HOOK_INCLUDE: LOGIC_HOOK_INCLUDE$1,
@@ -1190,13 +1051,7 @@ LogicHookConsts.DEFAULT_ASSERTERS;
1190
1051
  LogicHookConsts.DEFAULT_LOGIC_HOOKS;
1191
1052
  LogicHookConsts.DEFAULT_USER_INPUTS;
1192
1053
 
1193
- const {
1194
- NodeVM: NodeVM$2
1195
- } = vm2;
1196
1054
  const debug$m = debug$n('botium-core-asserterUtils');
1197
- const {
1198
- BotiumError: BotiumError$6
1199
- } = BotiumError_1;
1200
1055
  const {
1201
1056
  DEFAULT_ASSERTERS,
1202
1057
  DEFAULT_LOGIC_HOOKS,
@@ -1318,21 +1173,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1318
1173
  }, this.caps, args);
1319
1174
  }
1320
1175
  }
1321
- const _checkUnsafe = () => {
1322
- if (!this.caps[Capabilities.SECURITY_ALLOW_UNSAFE]) {
1323
- throw new BotiumError$6('Security Error. Using unsafe component is not allowed', {
1324
- type: 'security',
1325
- subtype: 'allow unsafe',
1326
- source: path.basename(__filename),
1327
- cause: {
1328
- src: !!src,
1329
- ref,
1330
- args,
1331
- hookType
1332
- }
1333
- });
1334
- }
1335
- };
1176
+ const allowUnsafe = !!this.caps[Capabilities.SECURITY_ALLOW_UNSAFE];
1336
1177
  if (!src) {
1337
1178
  const packageName = `botium-${hookType}-${ref}`;
1338
1179
  try {
@@ -1353,10 +1194,10 @@ var LogicHookUtils_1 = class LogicHookUtils {
1353
1194
  ...this.buildScriptContext
1354
1195
  }, this.caps, args);
1355
1196
  } else {
1356
- throw new Error(`${packageName} class or function or PluginClass field expected`);
1197
+ throw new Error('Either class or function or PluginClass field expected');
1357
1198
  }
1358
1199
  } catch (err) {
1359
- throw new Error(`Failed to fetch hook ${ref} ${hookType} from guessed package ${packageName} - ${err.message}`);
1200
+ throw new Error(`Logic Hook specification ${ref} ${hookType} (${packageName}) invalid: ${err.message}`);
1360
1201
  }
1361
1202
  }
1362
1203
  if (isClass(src)) {
@@ -1367,7 +1208,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1367
1208
  ...this.buildScriptContext
1368
1209
  }, this.caps, args);
1369
1210
  } catch (err) {
1370
- throw new Error(`Failed to load package ${ref} from provided class - ${err.message}`);
1211
+ throw new Error(`Logic Hook specification ${ref} from class invalid: ${err.message}`);
1371
1212
  }
1372
1213
  }
1373
1214
  if (lodash.isFunction(src)) {
@@ -1377,7 +1218,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1377
1218
  ...this.buildScriptContext
1378
1219
  }, this.caps, args);
1379
1220
  } catch (err) {
1380
- throw new Error(`Failed to load package ${ref} from provided function - ${err.message}`);
1221
+ throw new Error(`Logic Hook specification ${ref} from function invalid: ${err.message}`);
1381
1222
  }
1382
1223
  }
1383
1224
  if (lodash.isObject(src) && !lodash.isString(src)) {
@@ -1387,26 +1228,15 @@ var LogicHookUtils_1 = class LogicHookUtils {
1387
1228
  const script = src[key];
1388
1229
  if (lodash.isFunction(script)) {
1389
1230
  return script(args);
1390
- } else if (lodash.isString(script)) {
1391
- try {
1392
- const vm = new NodeVM$2({
1393
- eval: false,
1394
- require: false,
1395
- sandbox: args
1396
- });
1397
- return vm.run(script);
1398
- } catch (err) {
1399
- throw new Error(`Script ${key} is not valid - ${err.message || err}`);
1400
- }
1401
1231
  } else {
1402
- throw new Error(`Script "${key}" is not valid - only functions and javascript code accepted`);
1232
+ throw new Error(`Script ${key} is not valid - only functions accepted`);
1403
1233
  }
1404
1234
  };
1405
1235
  return result;
1406
1236
  }, {});
1407
1237
  return hookObject;
1408
1238
  } catch (err) {
1409
- throw new Error(`Failed to load package ${ref} ${hookType} from provided src function - ${err.message}`);
1239
+ throw new Error(`Logic Hook specification ${ref} ${hookType} from provided src (${util.inspect(src)}) invalid: ${err.message}`);
1410
1240
  }
1411
1241
  }
1412
1242
  if (lodash.isString(src)) {
@@ -1417,8 +1247,8 @@ var LogicHookUtils_1 = class LogicHookUtils {
1417
1247
  }];
1418
1248
  if (src.indexOf('/') >= 0) {
1419
1249
  tryLoads.push({
1420
- tryLoadPackageName: src.substr(0, src.lastIndexOf('/')),
1421
- tryLoadAsserterByName: src.substr(src.lastIndexOf('/') + 1)
1250
+ tryLoadPackageName: src.substring(0, src.lastIndexOf('/')),
1251
+ tryLoadAsserterByName: src.substring(src.lastIndexOf('/') + 1)
1422
1252
  });
1423
1253
  }
1424
1254
  const tryLoadFromSource = (tryRequire, tryAsserterName) => {
@@ -1456,28 +1286,33 @@ var LogicHookUtils_1 = class LogicHookUtils {
1456
1286
  ...this.buildScriptContext
1457
1287
  }, this.caps, args);
1458
1288
  } else {
1459
- throw new Error(`${src} class or function expected`);
1289
+ throw new Error('Expected class or function');
1460
1290
  }
1461
1291
  };
1462
1292
  for (const tryLoad of tryLoads) {
1463
- const tryLoadFile = path.resolve(process.cwd(), tryLoad.tryLoadPackageName);
1464
- if (fs.existsSync(tryLoadFile)) {
1465
- _checkUnsafe();
1293
+ if (this.caps.SAFEDIR) {
1294
+ const tryLoadFile = path.resolve(this.caps.SAFEDIR, tryLoad.tryLoadPackageName);
1295
+ if (tryLoadFile.startsWith(path.resolve(this.caps.SAFEDIR))) {
1296
+ if (fs.existsSync(tryLoadFile)) {
1297
+ try {
1298
+ return tryLoadFromSource(tryLoadFile, tryLoad.tryLoadAsserterByName);
1299
+ } catch (err) {
1300
+ loadErr.push(`Logic Hook specification ${ref} ${hookType} from "${src}" invalid: ${err.message} `);
1301
+ }
1302
+ }
1303
+ }
1304
+ }
1305
+ if (allowUnsafe || tryLoad.tryLoadPackageName.startsWith('botium-')) {
1466
1306
  try {
1467
- return tryLoadFromSource(tryLoadFile, tryLoad.tryLoadAsserterByName);
1307
+ return tryLoadFromSource(tryLoad.tryLoadPackageName, tryLoad.tryLoadAsserterByName);
1468
1308
  } catch (err) {
1469
- loadErr.push(`Failed to fetch ${ref} ${hookType} from ${src} - ${err.message} `);
1309
+ loadErr.push(`Logic Hook specification ${ref} ${hookType} from "${src}" invalid: ${err.message} `);
1470
1310
  }
1471
1311
  }
1472
- try {
1473
- return tryLoadFromSource(tryLoad.tryLoadPackageName, tryLoad.tryLoadAsserterByName);
1474
- } catch (err) {
1475
- loadErr.push(`Failed to fetch ${ref} ${hookType} from ${src} - ${err.message} `);
1476
- }
1477
1312
  }
1478
1313
  loadErr.forEach(debug$m);
1479
1314
  }
1480
- throw new Error(`Failed to fetch ${ref} ${hookType}, no idea how to load ...`);
1315
+ throw new Error(`Logic Hook specification ${ref} ${hookType} from "${util.inspect(src)}" invalid : no loader available`);
1481
1316
  }
1482
1317
  };
1483
1318
 
@@ -2284,19 +2119,150 @@ var helper = {
2284
2119
  toPercent: toPercent$1
2285
2120
  };
2286
2121
 
2122
+ const BotiumError$4 = class BotiumError extends Error {
2123
+ /**
2124
+ *
2125
+ * @param message
2126
+ * @param context A JSON with struct
2127
+ * {
2128
+ * type: 'some free text to identity the exception type',
2129
+ * source: 'source of the event',
2130
+ * ...
2131
+ */
2132
+ constructor(message, context, supressChildCheck) {
2133
+ super(message.message || message);
2134
+ if (!supressChildCheck && _getChildErrorsFromContext(context)) {
2135
+ throw Error('Create BotiumError with child errors using the fromList() method!');
2136
+ }
2137
+ // Saving class name in the property of our custom error as a shortcut.
2138
+ this.name = this.constructor.name;
2139
+
2140
+ // Capturing stack trace, excluding constructor call from it.
2141
+ Error.captureStackTrace(this, this.constructor);
2142
+ this.context = context || {};
2143
+ this.context.message = message.message || message;
2144
+ }
2145
+ isAsserterError() {
2146
+ if (this.context) {
2147
+ const errArr = lodash.isArray(this.context) ? this.context : [this.context];
2148
+ const hasNotAsserterError = errArr.findIndex(errDetail => {
2149
+ if (errDetail.type === 'list') {
2150
+ if (errDetail.errors) {
2151
+ return errDetail.errors.findIndex(e => e.type !== 'asserter') >= 0;
2152
+ } else {
2153
+ return true;
2154
+ }
2155
+ } else {
2156
+ return errDetail.type !== 'asserter';
2157
+ }
2158
+ }) >= 0;
2159
+ if (hasNotAsserterError) return false;
2160
+ return true;
2161
+ } else {
2162
+ return false;
2163
+ }
2164
+ }
2165
+ prettify(includeJson) {
2166
+ const lines = [];
2167
+ if (this.context) {
2168
+ const errArr = lodash.isArray(this.context) ? this.context : [this.context];
2169
+ errArr.forEach(errDetail => {
2170
+ lines.push('########################################');
2171
+ if (errDetail.type === 'asserter') {
2172
+ const segments = [];
2173
+ segments.push(`ASSERTION FAILED in ${errDetail.source}${errDetail.subtype ? ` (${errDetail.subtype})` : ''}`);
2174
+ errDetail.cause && errDetail.cause.expected && !errDetail.cause.not && segments.push(` - Expected: ${JSON.stringify(errDetail.cause.expected)} `);
2175
+ errDetail.cause && errDetail.cause.expected && errDetail.cause.not && segments.push(` - NOT Expected: ${JSON.stringify(errDetail.cause.expected)} `);
2176
+ errDetail.cause && errDetail.cause.actual && segments.push(` - Actual: ${JSON.stringify(errDetail.cause.actual)}`);
2177
+ errDetail.cause && !errDetail.cause.actual && segments.push(' - Actual: empty');
2178
+ lines.push(segments.join(''));
2179
+ errDetail.input && errDetail.input.messageText && lines.push(`INPUT: ${errDetail.input.messageText}`);
2180
+ } else if (errDetail.message) {
2181
+ lines.push(`${errDetail.message}`);
2182
+ }
2183
+ if (errDetail.transcript && errDetail.transcript.length > 0) {
2184
+ lines.push('------------ TRANSCRIPT ----------------------------');
2185
+ errDetail.transcript.forEach(transcriptStep => {
2186
+ if (transcriptStep.actual) {
2187
+ lines.push(transcriptStep.actual.prettify());
2188
+ }
2189
+ });
2190
+ }
2191
+ if (includeJson) {
2192
+ lines.push('------------ JSON CONTENT ----------------------------');
2193
+ try {
2194
+ const jsonOutput = JSON.stringify(errDetail);
2195
+ lines.push(jsonOutput);
2196
+ } catch (jsonErr) {
2197
+ lines.push(`JSON Output not possible: ${jsonErr.message}`);
2198
+ }
2199
+ }
2200
+ });
2201
+ }
2202
+ if (lines.length > 0) {
2203
+ return lines.join('\r\n');
2204
+ } else {
2205
+ return null;
2206
+ }
2207
+ }
2208
+ };
2209
+ const _getChildErrorsFromContext = context => {
2210
+ if (context && context.errors && lodash.isArray(context.errors)) {
2211
+ return context.errors;
2212
+ }
2213
+ return false;
2214
+ };
2215
+ const botiumErrorFromErr$2 = (message, err) => {
2216
+ if (err instanceof BotiumError$4) {
2217
+ return new BotiumError$4(message, err.context, true);
2218
+ } else {
2219
+ return new BotiumError$4(message, {
2220
+ err
2221
+ }, true);
2222
+ }
2223
+ };
2224
+ const botiumErrorFromList$2 = (errors, {
2225
+ type = 'list',
2226
+ source = 'BotiumError',
2227
+ flat = true
2228
+ }) => {
2229
+ const message = errors.map(err => err.message || err.toString()).join(',\n');
2230
+ let children = [];
2231
+ for (const error of errors) {
2232
+ if (error instanceof BotiumError$4) {
2233
+ const childErrors = flat && _getChildErrorsFromContext(error.context);
2234
+ if (childErrors && childErrors.length) {
2235
+ children = children.concat(childErrors);
2236
+ } else if (error.context) {
2237
+ children.push(error.context);
2238
+ }
2239
+ } else {
2240
+ children.push(error);
2241
+ }
2242
+ }
2243
+ const result = new BotiumError$4(message, {
2244
+ errors: children,
2245
+ type,
2246
+ source
2247
+ }, true);
2248
+ return result;
2249
+ };
2250
+ var BotiumError_1 = {
2251
+ BotiumError: BotiumError$4,
2252
+ botiumErrorFromErr: botiumErrorFromErr$2,
2253
+ botiumErrorFromList: botiumErrorFromList$2
2254
+ };
2255
+
2287
2256
  const debug$k = debug$n('botium-core-ScriptingMemory');
2288
2257
  const {
2289
2258
  v1: uuidv1
2290
2259
  } = uuid;
2291
- const {
2292
- NodeVM: NodeVM$1
2293
- } = vm2;
2294
2260
  const {
2295
2261
  quoteRegexpString: quoteRegexpString$1,
2296
2262
  toString: toString$2
2297
2263
  } = helper;
2298
2264
  const {
2299
- BotiumError: BotiumError$5
2265
+ BotiumError: BotiumError$3
2300
2266
  } = BotiumError_1;
2301
2267
 
2302
2268
  // If they got parameter, then it will be a string always.
@@ -2453,28 +2419,6 @@ const SCRIPTING_FUNCTIONS_RAW = {
2453
2419
  if (root && root.length > 0) return root[0];else return '';
2454
2420
  },
2455
2421
  numberOfArguments: 1
2456
- },
2457
- $func: {
2458
- handler: (caps, code) => {
2459
- if (code == null) {
2460
- throw Error('func function used without args!');
2461
- }
2462
- try {
2463
- const vm = new NodeVM$1({
2464
- eval: false,
2465
- require: false,
2466
- env: caps[Capabilities.SECURITY_ALLOW_UNSAFE] ? process.env : {},
2467
- sandbox: {
2468
- caps,
2469
- moment
2470
- }
2471
- });
2472
- return vm.run(`module.exports = (${code})`);
2473
- } catch (err) {
2474
- throw Error(`func function execution failed - ${err}`);
2475
- }
2476
- },
2477
- numberOfArguments: 1
2478
2422
  }
2479
2423
  };
2480
2424
  const SCRIPTING_FUNCTIONS$1 = lodash.mapValues(SCRIPTING_FUNCTIONS_RAW, (funcOrStruct, name) => {
@@ -2483,7 +2427,7 @@ const SCRIPTING_FUNCTIONS$1 = lodash.mapValues(SCRIPTING_FUNCTIONS_RAW, (funcOrS
2483
2427
  return {
2484
2428
  handler: (caps, ...rest) => {
2485
2429
  if (!caps[Capabilities.SECURITY_ALLOW_UNSAFE] && funcOrStruct.unsafe) {
2486
- throw new BotiumError$5(`Security Error. Using unsafe scripting memory function ${name} is not allowed`, {
2430
+ throw new BotiumError$3(`Security Error. Using unsafe scripting memory function ${name} is not allowed`, {
2487
2431
  type: 'security',
2488
2432
  subtype: 'allow unsafe',
2489
2433
  source: path.basename(__filename),
@@ -2623,7 +2567,7 @@ ScriptingMemory.SCRIPTING_FUNCTIONS;
2623
2567
 
2624
2568
  const debug$j = debug$n('botium-core-Convo');
2625
2569
  const {
2626
- BotiumError: BotiumError$4,
2570
+ BotiumError: BotiumError$2,
2627
2571
  botiumErrorFromErr: botiumErrorFromErr$1,
2628
2572
  botiumErrorFromList: botiumErrorFromList$1
2629
2573
  } = BotiumError_1;
@@ -2925,6 +2869,8 @@ class Convo$6 {
2925
2869
  let botMsg = null;
2926
2870
  let waitForBotSays = true;
2927
2871
  let skipTranscriptStep = false;
2872
+ let conditionalGroupId = null;
2873
+ let conditionMetInGroup = false;
2928
2874
  for (let i = 0; i < this.conversation.length; i++) {
2929
2875
  const convoStep = this.conversation[i];
2930
2876
  const currentStepIndex = i;
@@ -3047,7 +2993,6 @@ class Convo$6 {
3047
2993
  throw failErr;
3048
2994
  }
3049
2995
  } else if (convoStep.sender === 'bot') {
3050
- const previousWaitForBotSays = waitForBotSays;
3051
2996
  if (waitForBotSays) {
3052
2997
  botMsg = null;
3053
2998
  } else {
@@ -3104,24 +3049,40 @@ class Convo$6 {
3104
3049
  throw failErr;
3105
3050
  }
3106
3051
  if (convoStep.conditional) {
3107
- const nextConvoStep = this.conversation[i + 1];
3108
- if (!previousWaitForBotSays) {
3109
- skipTranscriptStep = true;
3110
- }
3111
3052
  waitForBotSays = false;
3053
+ let endOfConditionalGroup = false;
3054
+ conditionalGroupId = convoStep.logicHooks.find(lh => lh.name.startsWith('CONDITIONAL_STEP')).args[1];
3055
+ const nextConvoStep = this.conversation[i + 1];
3112
3056
  if (!nextConvoStep || nextConvoStep.sender !== 'bot' || !nextConvoStep.logicHooks || !nextConvoStep.logicHooks.some(lh => lh.name.toUpperCase().startsWith('CONDITIONAL_STEP'))) {
3113
- waitForBotSays = true;
3057
+ endOfConditionalGroup = true;
3114
3058
  } else {
3115
- const conditionalLogicHook = convoStep.logicHooks.find(lh => lh.name.startsWith('CONDITIONAL_STEP'));
3116
3059
  const nextConditionalLogicHook = nextConvoStep.logicHooks.find(lh => lh.name.startsWith('CONDITIONAL_STEP'));
3117
- waitForBotSays = conditionalLogicHook.args[1] !== nextConditionalLogicHook.args[1];
3060
+ endOfConditionalGroup = conditionalGroupId !== nextConditionalLogicHook.args[1];
3118
3061
  }
3119
- if (convoStep.conditional.skip) {
3062
+ if (convoStep.conditional.skip || conditionMetInGroup) {
3063
+ skipTranscriptStep = true;
3064
+ if (endOfConditionalGroup && !conditionMetInGroup && !convoStep.optional) {
3065
+ const failErr = new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: Non of the conditions are met in ${conditionalGroupId ? `'${conditionalGroupId}' ` : ''}condition group`);
3066
+ debug$j(failErr);
3067
+ throw failErr;
3068
+ }
3069
+ if (endOfConditionalGroup) {
3070
+ waitForBotSays = !convoStep.optional;
3071
+ conditionalGroupId = undefined;
3072
+ conditionMetInGroup = false;
3073
+ }
3120
3074
  continue;
3075
+ } else {
3076
+ conditionMetInGroup = true;
3077
+ if (endOfConditionalGroup) {
3078
+ waitForBotSays = !convoStep.optional;
3079
+ conditionalGroupId = undefined;
3080
+ conditionMetInGroup = false;
3081
+ }
3121
3082
  }
3122
3083
  }
3123
3084
  if (!botMsg || !botMsg.messageText && !botMsg.media && !botMsg.buttons && !botMsg.cards && !botMsg.sourceData && !botMsg.nlp) {
3124
- const failErr = new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot says nothing`);
3085
+ const failErr = new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot says nothing`);
3125
3086
  debug$j(failErr);
3126
3087
  try {
3127
3088
  this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
@@ -3207,7 +3168,7 @@ class Convo$6 {
3207
3168
  try {
3208
3169
  this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
3209
3170
  } catch (failErr) {}
3210
- if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS] && err instanceof BotiumError$4) {
3171
+ if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS] && err instanceof BotiumError$2) {
3211
3172
  assertErrors.push(err);
3212
3173
  } else {
3213
3174
  throw failErr;
@@ -3223,7 +3184,7 @@ class Convo$6 {
3223
3184
  }
3224
3185
  }
3225
3186
  } else {
3226
- const failErr = new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: invalid sender - ${util.inspect(convoStep.sender)}`);
3187
+ const failErr = new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: invalid sender - ${util.inspect(convoStep.sender)}`);
3227
3188
  debug$j(failErr);
3228
3189
  try {
3229
3190
  this.scriptingEvents.fail && this.scriptingEvents.fail(failErr);
@@ -3232,7 +3193,7 @@ class Convo$6 {
3232
3193
  }
3233
3194
  } catch (err) {
3234
3195
  if (lastMeConvoStep) {
3235
- if (err instanceof BotiumError$4 && err.context) {
3196
+ if (err instanceof BotiumError$2 && err.context) {
3236
3197
  err.context.input = new ConvoStep$1(lastMeConvoStep);
3237
3198
  err.context.transcript = [...transcriptSteps, {
3238
3199
  ...transcriptStep
@@ -3245,7 +3206,7 @@ class Convo$6 {
3245
3206
  }
3246
3207
  }
3247
3208
  transcriptStep.err = err;
3248
- if (err instanceof BotiumError$4 && container.caps[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]) {
3209
+ if (err instanceof BotiumError$2 && container.caps[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]) {
3249
3210
  if (!err.isAsserterError()) {
3250
3211
  throw err;
3251
3212
  }
@@ -3278,10 +3239,10 @@ class Convo$6 {
3278
3239
  if (expected === null || expected === undefined) return;
3279
3240
  if (lodash.isArray(expected)) {
3280
3241
  if (!lodash.isArray(result)) {
3281
- throw new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot response expected array, got "${result}"`);
3242
+ throw new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot response expected array, got "${result}"`);
3282
3243
  }
3283
3244
  if (expected.length !== result.length) {
3284
- throw new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot response expected array length ${expected.length}, got ${result.length}`);
3245
+ throw new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot response expected array length ${expected.length}, got ${result.length}`);
3285
3246
  }
3286
3247
  for (let i = 0; i < expected.length; i++) {
3287
3248
  this._compareObject(container, scriptingMemory, convoStep, result[i], expected[i]);
@@ -3291,7 +3252,7 @@ class Convo$6 {
3291
3252
  if (Object.prototype.hasOwnProperty.call(result, key)) {
3292
3253
  this._compareObject(container, scriptingMemory, convoStep, result[key], expected[key]);
3293
3254
  } else {
3294
- throw new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot response "${result}" missing expected property: ${key}`);
3255
+ throw new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot response "${result}" missing expected property: ${key}`);
3295
3256
  }
3296
3257
  });
3297
3258
  } else {
@@ -3420,14 +3381,14 @@ class Convo$6 {
3420
3381
  includeLogicHooks.forEach(includeLogicHook => {
3421
3382
  const alreadyThereAt = parentPConvos.indexOf(includeLogicHook);
3422
3383
  if (alreadyThereAt >= 0) {
3423
- throw new BotiumError$4(`Partial convos are included circular. "${includeLogicHook}" is referenced by "/${parentPConvos.slice(0, alreadyThereAt).join('/')}" and by "/${parentPConvos.join('/')}" `);
3384
+ throw new BotiumError$2(`Partial convos are included circular. "${includeLogicHook}" is referenced by "/${parentPConvos.slice(0, alreadyThereAt).join('/')}" and by "/${parentPConvos.join('/')}" `);
3424
3385
  }
3425
3386
  if (!partialConvos || Object.keys(partialConvos).length === 0) {
3426
- throw new BotiumError$4(`Cant find partial convo with name ${includeLogicHook} (There are no partial convos)`);
3387
+ throw new BotiumError$2(`Cant find partial convo with name ${includeLogicHook} (There are no partial convos)`);
3427
3388
  }
3428
3389
  const partialConvo = partialConvos[includeLogicHook];
3429
3390
  if (!partialConvo) {
3430
- throw new BotiumError$4(`Cant find partial convo with name ${includeLogicHook} (available partial convos: ${Object.keys(partialConvos).join(',')})`);
3391
+ throw new BotiumError$2(`Cant find partial convo with name ${includeLogicHook} (available partial convos: ${Object.keys(partialConvos).join(',')})`);
3431
3392
  }
3432
3393
  _getEffectiveConversationRecursive(partialConvo.conversation, [...parentPConvos, includeLogicHook], result, true);
3433
3394
  debug$j(`Partial convo ${includeLogicHook} included`);
@@ -3762,44 +3723,21 @@ var JsonToJson = {
3762
3723
  precompile: precompile$2
3763
3724
  };
3764
3725
 
3765
- const {
3766
- NodeVM
3767
- } = vm2;
3768
3726
  const debug$h = debug$n('botium-core-HookUtils');
3769
- const {
3770
- BotiumError: BotiumError$3
3771
- } = BotiumError_1;
3772
- const executeHook$2 = async (caps, hook, args) => {
3773
- return executeHookSync$1(caps, hook, args);
3727
+ const executeHook$2 = async (caps, hook, ...args) => {
3728
+ return executeHookSync$1(caps, hook, ...args);
3774
3729
  };
3775
- const executeHookSync$1 = (caps, hook, args) => {
3730
+ const executeHookSync$1 = (caps, hook, ...args) => {
3776
3731
  if (!hook) {
3777
3732
  return;
3778
3733
  }
3779
3734
  if (lodash.isFunction(hook)) {
3780
3735
  try {
3781
- return hook(args);
3736
+ return hook(...args);
3782
3737
  } catch (err) {
3783
3738
  throw new Error(`Calling Hook function failed: ${err.message}`);
3784
3739
  }
3785
3740
  }
3786
- if (lodash.isString(hook)) {
3787
- try {
3788
- const vm = new NodeVM({
3789
- eval: false,
3790
- require: false,
3791
- sandbox: args
3792
- });
3793
- const r = vm.run(hook);
3794
- if (lodash.isFunction(r)) {
3795
- return r(args);
3796
- } else {
3797
- return r;
3798
- }
3799
- } catch (err) {
3800
- throw new Error(`Calling Hook Javascript code failed: ${err.message}`);
3801
- }
3802
- }
3803
3741
  throw new Error(`Unknown hook ${typeof hook}`);
3804
3742
  };
3805
3743
  const getHook$3 = (caps, data) => {
@@ -3812,46 +3750,40 @@ const getHook$3 = (caps, data) => {
3812
3750
  return data;
3813
3751
  }
3814
3752
  if (lodash.isString(data)) {
3815
- let resultWithRequire;
3816
- let tryLoadFile = path.resolve(process.cwd(), data);
3817
- if (fs.existsSync(tryLoadFile)) {
3818
- try {
3819
- resultWithRequire = commonjsRequire(tryLoadFile);
3820
- } catch (err) {}
3821
- } else {
3822
- tryLoadFile = data;
3823
- try {
3824
- resultWithRequire = commonjsRequire(data);
3825
- } catch (err) {}
3826
- }
3827
- if (resultWithRequire) {
3828
- if (!allowUnsafe) {
3829
- throw new BotiumError$3('Security Error. Using unsafe custom hook with require is not allowed', {
3830
- type: 'security',
3831
- subtype: 'allow unsafe',
3832
- source: path.basename(__filename),
3833
- cause: {
3834
- SECURITY_ALLOW_UNSAFE: caps[Capabilities.SECURITY_ALLOW_UNSAFE],
3835
- hookData: data
3753
+ if (caps.SAFEDIR) {
3754
+ const tryLoadFile = path.resolve(caps.SAFEDIR, data);
3755
+ if (tryLoadFile.startsWith(path.resolve(caps.SAFEDIR))) {
3756
+ if (fs.existsSync(tryLoadFile)) {
3757
+ try {
3758
+ const resultWithRequire = commonjsRequire(tryLoadFile);
3759
+ if (lodash.isFunction(resultWithRequire)) {
3760
+ debug$h(`found hook, type: safedir, in ${tryLoadFile}`);
3761
+ return resultWithRequire;
3762
+ } else {
3763
+ throw new Error(`Expected function from hook specification "${util.inspect(data)}", got: "${util.inspect(resultWithRequire)}"`);
3764
+ }
3765
+ } catch (err) {
3766
+ debug$h(`Failed loading hook, type: safedir, from ${tryLoadFile} failed: ${err.message || err}`);
3836
3767
  }
3837
- });
3838
- }
3839
- if (lodash.isFunction(resultWithRequire)) {
3840
- debug$h(`found hook, type: require, in ${tryLoadFile}`);
3841
- return resultWithRequire;
3842
- } else {
3843
- throw new Error(`Cant load hook ${tryLoadFile} because it is not a function`);
3768
+ }
3844
3769
  }
3845
3770
  }
3846
- try {
3847
- esprima.parseScript(data);
3848
- } catch (err) {
3849
- throw new Error(`Cant load hook, syntax is not valid - ${util.inspect(err)}`);
3771
+ if (allowUnsafe || data.startsWith('botium-')) {
3772
+ const tryLoadFile = data;
3773
+ try {
3774
+ const resultWithRequire = commonjsRequire(tryLoadFile);
3775
+ if (lodash.isFunction(resultWithRequire)) {
3776
+ debug$h(`found hook, type: require, in ${tryLoadFile}`);
3777
+ return resultWithRequire;
3778
+ } else {
3779
+ throw new Error(`Expected function from hook specification "${util.inspect(data)}", got: "${util.inspect(resultWithRequire)}"`);
3780
+ }
3781
+ } catch (err) {
3782
+ debug$h(`Failed loading hook, type: require, from ${tryLoadFile} failed: ${err.message || err}`);
3783
+ }
3850
3784
  }
3851
- debug$h('Found hook, type: JavaScript as String');
3852
- return data;
3853
3785
  }
3854
- throw new Error(`Not valid hook ${util.inspect(data)}`);
3786
+ throw new Error(`Hook specification "${util.inspect(data)}" invalid: no loader available`);
3855
3787
  };
3856
3788
  var HookUtils = {
3857
3789
  getHook: getHook$3,
@@ -5347,7 +5279,7 @@ const {
5347
5279
  ConvoStep
5348
5280
  } = Convo_1;
5349
5281
  const {
5350
- BotiumError: BotiumError$2,
5282
+ BotiumError: BotiumError$1,
5351
5283
  botiumErrorFromList,
5352
5284
  botiumErrorFromErr
5353
5285
  } = BotiumError_1;
@@ -5623,7 +5555,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5623
5555
  const werArgs = this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS];
5624
5556
  const threshold = [',', '.'].find(p => `${werArgs[0]}`.includes(p)) ? parseFloat(werArgs[0]) : parseInt(werArgs[0]) / 100;
5625
5557
  const message = `${stepTag}: Word Error Rate (${toPercent(wer)}) higher than accepted (${toPercent(threshold)})`;
5626
- throw new BotiumError$2(message, {
5558
+ throw new BotiumError$1(message, {
5627
5559
  type: 'asserter',
5628
5560
  source: asserterType,
5629
5561
  params: {
@@ -5645,7 +5577,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5645
5577
  message += ' expected to match ';
5646
5578
  message += tomatch && tomatch.length > 1 ? 'one of ' : '';
5647
5579
  message += `${tomatch.map(e => e ? '"' + e + '"' : '<any response>').join(', ')}`;
5648
- throw new BotiumError$2(message, {
5580
+ throw new BotiumError$1(message, {
5649
5581
  type: 'asserter',
5650
5582
  source: asserterType,
5651
5583
  params: {
@@ -5678,7 +5610,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5678
5610
  const werArgs = this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS];
5679
5611
  const threshold = [',', '.'].find(p => `${werArgs[0]}`.includes(p)) ? parseFloat(werArgs[0]) : parseInt(werArgs[0]) / 100;
5680
5612
  const message = `${stepTag}: Word Error Rate (${toPercent(wer)}) lower than accepted (${toPercent(threshold)})`;
5681
- throw new BotiumError$2(message, {
5613
+ throw new BotiumError$1(message, {
5682
5614
  type: 'asserter',
5683
5615
  source: asserterType,
5684
5616
  params: {
@@ -5700,7 +5632,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5700
5632
  message += ' expected NOT to match ';
5701
5633
  message += nottomatch && nottomatch.length > 1 ? 'one of ' : '';
5702
5634
  message += `${nottomatch.map(e => e ? '"' + e + '"' : '<any response>').join(', ')}`;
5703
- throw new BotiumError$2(message, {
5635
+ throw new BotiumError$1(message, {
5704
5636
  type: 'asserter',
5705
5637
  source: asserterType,
5706
5638
  params: {
@@ -5750,7 +5682,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5750
5682
  if (asserter[notAsserterType]) {
5751
5683
  return p(this.retryHelperAsserter, () => asserter[notAsserterType](params));
5752
5684
  } else {
5753
- return pnot(this.retryHelperAsserter, () => asserter[asserterType](params), new BotiumError$2(`${convoStep.stepTag}: Expected asserter ${asserter.name || asserterSpec.name} with args "${params.args}" to fail`, {
5685
+ return pnot(this.retryHelperAsserter, () => asserter[asserterType](params), new BotiumError$1(`${convoStep.stepTag}: Expected asserter ${asserter.name || asserterSpec.name} with args "${params.args}" to fail`, {
5754
5686
  type: 'asserter',
5755
5687
  source: asserter.name || asserterSpec.name,
5756
5688
  params: {
@@ -6145,7 +6077,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6145
6077
  return !entry.header.name;
6146
6078
  });
6147
6079
  if (aggregatedNoNames.length) {
6148
- throw new BotiumError$2('Scripting Memory Definition(s) without name', {
6080
+ throw new BotiumError$1('Scripting Memory Definition(s) without name', {
6149
6081
  type: 'Scripting Memory',
6150
6082
  subtype: 'Scripting Memory without name',
6151
6083
  source: 'ScriptingProvider',
@@ -6160,7 +6092,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6160
6092
  return !entry.values || !Object.keys(entry.values).length;
6161
6093
  });
6162
6094
  if (aggregatedNoVariables.length) {
6163
- throw new BotiumError$2(`Scripting Memory Definition(s) ${aggregatedNoVariables.map(e => e.header.name).join(', ')} without variable`, {
6095
+ throw new BotiumError$1(`Scripting Memory Definition(s) ${aggregatedNoVariables.map(e => e.header.name).join(', ')} without variable`, {
6164
6096
  type: 'Scripting Memory',
6165
6097
  subtype: 'Scripting Memory without variable',
6166
6098
  source: 'ScriptingProvider',
@@ -6175,7 +6107,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6175
6107
  return !lodash.isUndefined(entry.values['']);
6176
6108
  });
6177
6109
  if (aggregatedNoVariableNames.length) {
6178
- throw new BotiumError$2(`Scripting Memory Definition(s) ${aggregatedNoVariableNames.map(e => e.header.name).join(', ')} without variable name`, {
6110
+ throw new BotiumError$1(`Scripting Memory Definition(s) ${aggregatedNoVariableNames.map(e => e.header.name).join(', ')} without variable name`, {
6179
6111
  type: 'Scripting Memory',
6180
6112
  subtype: 'Scripting Memory without variable name',
6181
6113
  source: 'ScriptingProvider',
@@ -6203,7 +6135,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6203
6135
  }
6204
6136
  }
6205
6137
  if (aggregatedDuplicates.length) {
6206
- throw new BotiumError$2(`Scripting Memory Definition name(s) "${lodash.uniq(aggregatedDuplicates.map(d => d.scriptingMemory.header.name)).join(', ')}" are not unique`, {
6138
+ throw new BotiumError$1(`Scripting Memory Definition name(s) "${lodash.uniq(aggregatedDuplicates.map(d => d.scriptingMemory.header.name)).join(', ')}" are not unique`, {
6207
6139
  type: 'Scripting Memory',
6208
6140
  subtype: 'Scripting Memory name collision',
6209
6141
  source: 'ScriptingProvider',
@@ -6234,7 +6166,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6234
6166
  }
6235
6167
  }
6236
6168
  if (aggregatedIntersections.length) {
6237
- throw new BotiumError$2(`Scripting Memory Definitions "${aggregatedIntersections.map(i => i.scriptingMemory.header.name).join(', ')}" are invalid because variable name collision"`, {
6169
+ throw new BotiumError$1(`Scripting Memory Definitions "${aggregatedIntersections.map(i => i.scriptingMemory.header.name).join(', ')}" are invalid because variable name collision"`, {
6238
6170
  type: 'Scripting Memory',
6239
6171
  subtype: 'Scripting Memory variable name collision',
6240
6172
  source: 'ScriptingProvider',
@@ -6797,7 +6729,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6797
6729
  }
6798
6730
  } else if (scriptingMemories) {
6799
6731
  if (!scriptingMemories.header || !scriptingMemories.header.name) {
6800
- throw new BotiumError$2('Scripting Memory Definition has no name', {
6732
+ throw new BotiumError$1('Scripting Memory Definition has no name', {
6801
6733
  type: 'Compiler',
6802
6734
  subtype: 'Scripting memory without name',
6803
6735
  source: 'ScriptingProvider',
@@ -6807,7 +6739,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6807
6739
  });
6808
6740
  }
6809
6741
  if (!scriptingMemories.values || !Object.keys(scriptingMemories.values).length) {
6810
- throw new BotiumError$2('Scripting Memory Definition has no variables', {
6742
+ throw new BotiumError$1('Scripting Memory Definition has no variables', {
6811
6743
  type: 'Compiler',
6812
6744
  subtype: 'Scripting memory without variable',
6813
6745
  source: 'ScriptingProvider',
@@ -6817,7 +6749,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6817
6749
  });
6818
6750
  }
6819
6751
  if (scriptingMemories.values && !lodash.isUndefined(scriptingMemories.values[''])) {
6820
- throw new BotiumError$2('Scripting Memory Definition variable has no name', {
6752
+ throw new BotiumError$1('Scripting Memory Definition variable has no name', {
6821
6753
  type: 'Compiler',
6822
6754
  subtype: 'Scripting memory without variable name',
6823
6755
  source: 'ScriptingProvider',
@@ -7704,7 +7636,7 @@ const {
7704
7636
  escapeJSONString
7705
7637
  } = Utils;
7706
7638
  const {
7707
- BotiumError: BotiumError$1
7639
+ BotiumError
7708
7640
  } = BotiumError_1;
7709
7641
  mustache.escape = s => s;
7710
7642
  var SimpleRestContainer_1 = class SimpleRestContainer {
@@ -8001,22 +7933,32 @@ var SimpleRestContainer_1 = class SimpleRestContainer {
8001
7933
  }
8002
7934
  const result = [];
8003
7935
  if (isFromUser) {
8004
- const _extractFrom = (root, jsonPaths) => {
8005
- const flattened = [];
7936
+ const _extractFrom = (root, jsonPaths, acceptFn = null) => {
7937
+ const result = [];
8006
7938
  for (const jsonPath of jsonPaths) {
7939
+ const jsonPathRes = [];
8007
7940
  const rb = jsonpath.query(root, jsonPath);
8008
7941
  if (lodash.isArray(rb)) {
8009
- lodash.flattenDeep(rb).forEach(r => flattened.push(r));
8010
- } else if (rb) {
8011
- flattened.push(rb);
7942
+ lodash.flattenDeep(rb).forEach(r => jsonPathRes.push(r));
7943
+ } else {
7944
+ jsonPathRes.push(rb);
7945
+ }
7946
+ if (acceptFn) {
7947
+ result.push(...jsonPathRes.filter(r => acceptFn(root, jsonPath, r)));
7948
+ } else {
7949
+ result.push(...jsonPathRes);
8012
7950
  }
8013
7951
  }
8014
- return flattened;
7952
+ return result;
8015
7953
  };
8016
7954
  const jsonPathRoots = [];
8017
7955
  const jsonPathsBody = getAllCapValues(Capabilities.SIMPLEREST_BODY_JSONPATH, this.caps);
8018
7956
  if (jsonPathsBody.length > 0) {
8019
- jsonPathRoots.push(..._extractFrom(body, jsonPathsBody));
7957
+ jsonPathRoots.push(..._extractFrom(body, jsonPathsBody, (root, jsonPath, r) => {
7958
+ if (r && lodash.isObject(r)) return true;
7959
+ debug$4(`Ignoring result body from ${jsonPath} - not a querieable object (${util.inspect(r)})`);
7960
+ return false;
7961
+ }));
8020
7962
  } else {
8021
7963
  jsonPathRoots.push(body);
8022
7964
  }
@@ -8175,7 +8117,7 @@ var SimpleRestContainer_1 = class SimpleRestContainer {
8175
8117
  const jsonBody = Utils.toJsonWeak(body);
8176
8118
  const errKey = Object.keys(jsonBody).find(k => k.startsWith('err') || k.startsWith('fail'));
8177
8119
  if (errKey) {
8178
- return reject(new BotiumError$1(`got error response: ${response.statusCode}/${response.statusMessage} - ${jsonBody[errKey]}`, {
8120
+ return reject(new BotiumError(`got error response: ${response.statusCode}/${response.statusMessage} - ${jsonBody[errKey]}`, {
8179
8121
  message: Utils.shortenJsonString(body)
8180
8122
  }));
8181
8123
  }
@@ -8630,9 +8572,6 @@ var SimpleRestContainer_1 = class SimpleRestContainer {
8630
8572
  };
8631
8573
 
8632
8574
  const debug$3 = debug$n('botium-connector-PluginConnectorContainer-helper');
8633
- const {
8634
- BotiumError
8635
- } = BotiumError_1;
8636
8575
  const pluginResolver = containermode => {
8637
8576
  if (containermode === 'simplerest') {
8638
8577
  return SimpleRestContainer_1;
@@ -8683,20 +8622,6 @@ const loadConnectorModule = (PluginClass, args) => {
8683
8622
  };
8684
8623
  const tryLoadPlugin$1 = (containermode, modulepath, args) => {
8685
8624
  const pluginLoaderSpec = modulepath || containermode;
8686
- const _checkUnsafe = (caps, mode, cause) => {
8687
- if (!caps[Capabilities.SECURITY_ALLOW_UNSAFE]) {
8688
- throw new BotiumError(`Security Error. Using unsafe connector mode "${mode}" is not allowed`, {
8689
- type: 'security',
8690
- subtype: 'allow unsafe',
8691
- source: 'src/containers/plugins/index.js',
8692
- cause: {
8693
- SECURITY_ALLOW_UNSAFE: caps[Capabilities.SECURITY_ALLOW_UNSAFE],
8694
- mode,
8695
- ...cause
8696
- }
8697
- });
8698
- }
8699
- };
8700
8625
  if (pluginResolver(pluginLoaderSpec)) {
8701
8626
  const pluginInstance = new (pluginResolver(pluginLoaderSpec))(args);
8702
8627
  debug$3('Botium plugin loaded from internal plugin resolver');
@@ -8708,44 +8633,47 @@ const tryLoadPlugin$1 = (containermode, modulepath, args) => {
8708
8633
  return pluginInstance;
8709
8634
  }
8710
8635
  const loadErr = [];
8636
+ const allowUnsafe = !!args.caps[Capabilities.SECURITY_ALLOW_UNSAFE];
8711
8637
  if (lodash.isString(pluginLoaderSpec)) {
8712
- const tryLoadFile = path.resolve(process.cwd(), pluginLoaderSpec);
8713
- if (fs.existsSync(tryLoadFile)) {
8714
- _checkUnsafe(args.caps, 'Using work dir', {
8715
- modulepath,
8716
- containermode
8717
- });
8638
+ if (args.caps.SAFEDIR) {
8639
+ const tryLoadFile = path.resolve(args.caps.SAFEDIR, pluginLoaderSpec);
8640
+ if (tryLoadFile.startsWith(path.resolve(args.caps.SAFEDIR))) {
8641
+ if (fs.existsSync(tryLoadFile)) {
8642
+ try {
8643
+ let plugin = commonjsRequire(tryLoadFile);
8644
+ if (plugin.default) {
8645
+ plugin = plugin.default;
8646
+ }
8647
+ if (!plugin.PluginVersion || !plugin.PluginClass) {
8648
+ loadErr.push(`Invalid Botium plugin loaded from ${tryLoadFile}, expected PluginVersion, PluginClass fields`);
8649
+ } else {
8650
+ const pluginInstance = loadConnectorModule(plugin.PluginClass, args);
8651
+ debug$3(`Botium plugin loaded from ${tryLoadFile}`);
8652
+ return pluginInstance;
8653
+ }
8654
+ } catch (err) {
8655
+ loadErr.push(`Loading Botium plugin from ${tryLoadFile} failed - ${err.message}`);
8656
+ }
8657
+ }
8658
+ }
8659
+ }
8660
+ if (allowUnsafe) {
8718
8661
  try {
8719
- let plugin = commonjsRequire(tryLoadFile);
8662
+ let plugin = commonjsRequire(pluginLoaderSpec);
8720
8663
  if (plugin.default) {
8721
8664
  plugin = plugin.default;
8722
8665
  }
8723
8666
  if (!plugin.PluginVersion || !plugin.PluginClass) {
8724
- loadErr.push(`Invalid Botium plugin loaded from ${tryLoadFile}, expected PluginVersion, PluginClass fields`);
8667
+ loadErr.push(`Invalid Botium plugin loaded from ${pluginLoaderSpec}, expected PluginVersion, PluginClass fields`);
8725
8668
  } else {
8726
8669
  const pluginInstance = loadConnectorModule(plugin.PluginClass, args);
8727
- debug$3(`Botium plugin loaded from ${tryLoadFile}`);
8670
+ debug$3(`Botium plugin loaded from ${pluginLoaderSpec}. Plugin version is ${getModuleVersionSafe(pluginLoaderSpec)}`);
8728
8671
  return pluginInstance;
8729
8672
  }
8730
8673
  } catch (err) {
8731
- loadErr.push(`Loading Botium plugin from ${tryLoadFile} failed - ${err.message}`);
8674
+ loadErr.push(`Loading Botium plugin from ${pluginLoaderSpec} failed - ${err.message}`);
8732
8675
  }
8733
8676
  }
8734
- try {
8735
- let plugin = commonjsRequire(pluginLoaderSpec);
8736
- if (plugin.default) {
8737
- plugin = plugin.default;
8738
- }
8739
- if (!plugin.PluginVersion || !plugin.PluginClass) {
8740
- loadErr.push(`Invalid Botium plugin loaded from ${pluginLoaderSpec}, expected PluginVersion, PluginClass fields`);
8741
- } else {
8742
- const pluginInstance = loadConnectorModule(plugin.PluginClass, args);
8743
- debug$3(`Botium plugin loaded from ${pluginLoaderSpec}. Plugin version is ${getModuleVersionSafe(pluginLoaderSpec)}`);
8744
- return pluginInstance;
8745
- }
8746
- } catch (err) {
8747
- loadErr.push(`Loading Botium plugin from ${pluginLoaderSpec} failed - ${err.message}`);
8748
- }
8749
8677
  const tryLoadPackage = `botium-connector-${pluginLoaderSpec}`;
8750
8678
  try {
8751
8679
  let plugin = commonjsRequire(tryLoadPackage);
@@ -8909,6 +8837,13 @@ var PluginConnectorContainer_1 = class PluginConnectorContainer extends BaseCont
8909
8837
  return Promise.reject(new Error(`Clean - Botium plugin failed: ${util.inspect(err)}`));
8910
8838
  }
8911
8839
  }
8840
+ GetMetaData() {
8841
+ try {
8842
+ return this.pluginInstance.GetMetaData ? this.pluginInstance.GetMetaData() || Promise.resolve() : Promise.resolve();
8843
+ } catch (err) {
8844
+ return Promise.reject(new Error(`GetMetaData - Botium plugin failed: ${util.inspect(err)}`));
8845
+ }
8846
+ }
8912
8847
  };
8913
8848
 
8914
8849
  var require$$3 = getCjsExportFromNamespace(_package$1);