botium-core 1.13.19 → 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 (32) hide show
  1. package/dist/botium-cjs.js +298 -382
  2. package/dist/botium-cjs.js.map +1 -1
  3. package/dist/botium-es.js +298 -380
  4. package/dist/botium-es.js.map +1 -1
  5. package/package.json +20 -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/ScriptingMemory.js +0 -24
  15. package/src/scripting/logichook/LogicHookUtils.js +27 -47
  16. package/test/compiler/precompilerscript.spec.js +24 -26
  17. package/test/connectors/pluginconnectorcontainer.spec.js +60 -0
  18. package/test/connectors/simplerest.spec.js +24 -27
  19. package/test/convo/fillAndApplyScriptingMemory.spec.js +1 -47
  20. package/test/hooks/customhooks.spec.js +3 -25
  21. package/test/logichooks/hookfromsrc.spec.js +13 -3
  22. package/test/plugins/plugins.spec.js +29 -2
  23. package/test/security/allowUnsafe.spec.js +20 -129
  24. package/LICENSES-3RDPARTY.txt +0 -6450
  25. package/test/scripting/asserters/convos/customembeddedasserterwithhugo.convo.txt +0 -7
  26. package/test/scripting/asserters/convos/customembeddedasserterwithouthugo.convo.txt +0 -7
  27. package/test/scripting/asserters/customEmbeddedAsserter.json +0 -14
  28. package/test/scripting/asserters/customEmbeddedAsserter.spec.js +0 -55
  29. package/test/scripting/logichooks/convos/custom_embedded.convo.txt +0 -8
  30. package/test/scripting/logichooks/customEmbedded.json +0 -14
  31. package/test/scripting/logichooks/customEmbedded.spec.js +0 -44
  32. 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.0";
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",
69
+ "@babel/runtime": "^7.22.15",
73
70
  async: "^3.2.4",
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.0",
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",
@@ -91,45 +87,42 @@ var dependencies = {
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.1",
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",
100
+ "swagger-ui-express": "^5.0.0",
105
101
  uuid: "^9.0.0",
106
- vm2: "^3.9.17",
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.2"
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.22.17",
110
+ "@babel/node": "^7.22.15",
111
+ "@babel/plugin-transform-runtime": "^7.22.15",
112
+ "@babel/preset-env": "^7.22.15",
113
+ chai: "^4.3.8",
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",
116
+ eslint: "^8.49.0",
117
+ "eslint-config-standard": "^17.1.0",
118
+ "eslint-plugin-import": "^2.28.1",
124
119
  "eslint-plugin-mocha": "^10.1.0",
125
- "eslint-plugin-n": "^15.7.0",
120
+ "eslint-plugin-n": "^16.1.0",
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.3",
125
+ "npm-check-updates": "^16.13.3",
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;
@@ -3121,7 +3065,7 @@ class Convo$6 {
3121
3065
  }
3122
3066
  }
3123
3067
  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`);
3068
+ const failErr = new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot says nothing`);
3125
3069
  debug$j(failErr);
3126
3070
  try {
3127
3071
  this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
@@ -3207,7 +3151,7 @@ class Convo$6 {
3207
3151
  try {
3208
3152
  this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
3209
3153
  } catch (failErr) {}
3210
- if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS] && err instanceof BotiumError$4) {
3154
+ if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS] && err instanceof BotiumError$2) {
3211
3155
  assertErrors.push(err);
3212
3156
  } else {
3213
3157
  throw failErr;
@@ -3223,7 +3167,7 @@ class Convo$6 {
3223
3167
  }
3224
3168
  }
3225
3169
  } else {
3226
- const failErr = new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: invalid sender - ${util.inspect(convoStep.sender)}`);
3170
+ const failErr = new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: invalid sender - ${util.inspect(convoStep.sender)}`);
3227
3171
  debug$j(failErr);
3228
3172
  try {
3229
3173
  this.scriptingEvents.fail && this.scriptingEvents.fail(failErr);
@@ -3232,7 +3176,7 @@ class Convo$6 {
3232
3176
  }
3233
3177
  } catch (err) {
3234
3178
  if (lastMeConvoStep) {
3235
- if (err instanceof BotiumError$4 && err.context) {
3179
+ if (err instanceof BotiumError$2 && err.context) {
3236
3180
  err.context.input = new ConvoStep$1(lastMeConvoStep);
3237
3181
  err.context.transcript = [...transcriptSteps, {
3238
3182
  ...transcriptStep
@@ -3245,7 +3189,7 @@ class Convo$6 {
3245
3189
  }
3246
3190
  }
3247
3191
  transcriptStep.err = err;
3248
- if (err instanceof BotiumError$4 && container.caps[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]) {
3192
+ if (err instanceof BotiumError$2 && container.caps[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]) {
3249
3193
  if (!err.isAsserterError()) {
3250
3194
  throw err;
3251
3195
  }
@@ -3278,10 +3222,10 @@ class Convo$6 {
3278
3222
  if (expected === null || expected === undefined) return;
3279
3223
  if (lodash.isArray(expected)) {
3280
3224
  if (!lodash.isArray(result)) {
3281
- throw new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot response expected array, got "${result}"`);
3225
+ throw new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot response expected array, got "${result}"`);
3282
3226
  }
3283
3227
  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}`);
3228
+ throw new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot response expected array length ${expected.length}, got ${result.length}`);
3285
3229
  }
3286
3230
  for (let i = 0; i < expected.length; i++) {
3287
3231
  this._compareObject(container, scriptingMemory, convoStep, result[i], expected[i]);
@@ -3291,7 +3235,7 @@ class Convo$6 {
3291
3235
  if (Object.prototype.hasOwnProperty.call(result, key)) {
3292
3236
  this._compareObject(container, scriptingMemory, convoStep, result[key], expected[key]);
3293
3237
  } else {
3294
- throw new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot response "${result}" missing expected property: ${key}`);
3238
+ throw new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot response "${result}" missing expected property: ${key}`);
3295
3239
  }
3296
3240
  });
3297
3241
  } else {
@@ -3420,14 +3364,14 @@ class Convo$6 {
3420
3364
  includeLogicHooks.forEach(includeLogicHook => {
3421
3365
  const alreadyThereAt = parentPConvos.indexOf(includeLogicHook);
3422
3366
  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('/')}" `);
3367
+ throw new BotiumError$2(`Partial convos are included circular. "${includeLogicHook}" is referenced by "/${parentPConvos.slice(0, alreadyThereAt).join('/')}" and by "/${parentPConvos.join('/')}" `);
3424
3368
  }
3425
3369
  if (!partialConvos || Object.keys(partialConvos).length === 0) {
3426
- throw new BotiumError$4(`Cant find partial convo with name ${includeLogicHook} (There are no partial convos)`);
3370
+ throw new BotiumError$2(`Cant find partial convo with name ${includeLogicHook} (There are no partial convos)`);
3427
3371
  }
3428
3372
  const partialConvo = partialConvos[includeLogicHook];
3429
3373
  if (!partialConvo) {
3430
- throw new BotiumError$4(`Cant find partial convo with name ${includeLogicHook} (available partial convos: ${Object.keys(partialConvos).join(',')})`);
3374
+ throw new BotiumError$2(`Cant find partial convo with name ${includeLogicHook} (available partial convos: ${Object.keys(partialConvos).join(',')})`);
3431
3375
  }
3432
3376
  _getEffectiveConversationRecursive(partialConvo.conversation, [...parentPConvos, includeLogicHook], result, true);
3433
3377
  debug$j(`Partial convo ${includeLogicHook} included`);
@@ -3762,44 +3706,21 @@ var JsonToJson = {
3762
3706
  precompile: precompile$2
3763
3707
  };
3764
3708
 
3765
- const {
3766
- NodeVM
3767
- } = vm2;
3768
3709
  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);
3710
+ const executeHook$2 = async (caps, hook, ...args) => {
3711
+ return executeHookSync$1(caps, hook, ...args);
3774
3712
  };
3775
- const executeHookSync$1 = (caps, hook, args) => {
3713
+ const executeHookSync$1 = (caps, hook, ...args) => {
3776
3714
  if (!hook) {
3777
3715
  return;
3778
3716
  }
3779
3717
  if (lodash.isFunction(hook)) {
3780
3718
  try {
3781
- return hook(args);
3719
+ return hook(...args);
3782
3720
  } catch (err) {
3783
3721
  throw new Error(`Calling Hook function failed: ${err.message}`);
3784
3722
  }
3785
3723
  }
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
3724
  throw new Error(`Unknown hook ${typeof hook}`);
3804
3725
  };
3805
3726
  const getHook$3 = (caps, data) => {
@@ -3812,46 +3733,40 @@ const getHook$3 = (caps, data) => {
3812
3733
  return data;
3813
3734
  }
3814
3735
  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
3736
+ if (caps.SAFEDIR) {
3737
+ const tryLoadFile = path.resolve(caps.SAFEDIR, data);
3738
+ if (tryLoadFile.startsWith(path.resolve(caps.SAFEDIR))) {
3739
+ if (fs.existsSync(tryLoadFile)) {
3740
+ try {
3741
+ const resultWithRequire = commonjsRequire(tryLoadFile);
3742
+ if (lodash.isFunction(resultWithRequire)) {
3743
+ debug$h(`found hook, type: safedir, in ${tryLoadFile}`);
3744
+ return resultWithRequire;
3745
+ } else {
3746
+ throw new Error(`Expected function from hook specification "${util.inspect(data)}", got: "${util.inspect(resultWithRequire)}"`);
3747
+ }
3748
+ } catch (err) {
3749
+ debug$h(`Failed loading hook, type: safedir, from ${tryLoadFile} failed: ${err.message || err}`);
3836
3750
  }
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`);
3751
+ }
3844
3752
  }
3845
3753
  }
3846
- try {
3847
- esprima.parseScript(data);
3848
- } catch (err) {
3849
- throw new Error(`Cant load hook, syntax is not valid - ${util.inspect(err)}`);
3754
+ if (allowUnsafe || data.startsWith('botium-')) {
3755
+ const tryLoadFile = data;
3756
+ try {
3757
+ const resultWithRequire = commonjsRequire(tryLoadFile);
3758
+ if (lodash.isFunction(resultWithRequire)) {
3759
+ debug$h(`found hook, type: require, in ${tryLoadFile}`);
3760
+ return resultWithRequire;
3761
+ } else {
3762
+ throw new Error(`Expected function from hook specification "${util.inspect(data)}", got: "${util.inspect(resultWithRequire)}"`);
3763
+ }
3764
+ } catch (err) {
3765
+ debug$h(`Failed loading hook, type: require, from ${tryLoadFile} failed: ${err.message || err}`);
3766
+ }
3850
3767
  }
3851
- debug$h('Found hook, type: JavaScript as String');
3852
- return data;
3853
3768
  }
3854
- throw new Error(`Not valid hook ${util.inspect(data)}`);
3769
+ throw new Error(`Hook specification "${util.inspect(data)}" invalid: no loader available`);
3855
3770
  };
3856
3771
  var HookUtils = {
3857
3772
  getHook: getHook$3,
@@ -5347,7 +5262,7 @@ const {
5347
5262
  ConvoStep
5348
5263
  } = Convo_1;
5349
5264
  const {
5350
- BotiumError: BotiumError$2,
5265
+ BotiumError: BotiumError$1,
5351
5266
  botiumErrorFromList,
5352
5267
  botiumErrorFromErr
5353
5268
  } = BotiumError_1;
@@ -5623,7 +5538,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5623
5538
  const werArgs = this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS];
5624
5539
  const threshold = [',', '.'].find(p => `${werArgs[0]}`.includes(p)) ? parseFloat(werArgs[0]) : parseInt(werArgs[0]) / 100;
5625
5540
  const message = `${stepTag}: Word Error Rate (${toPercent(wer)}) higher than accepted (${toPercent(threshold)})`;
5626
- throw new BotiumError$2(message, {
5541
+ throw new BotiumError$1(message, {
5627
5542
  type: 'asserter',
5628
5543
  source: asserterType,
5629
5544
  params: {
@@ -5645,7 +5560,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5645
5560
  message += ' expected to match ';
5646
5561
  message += tomatch && tomatch.length > 1 ? 'one of ' : '';
5647
5562
  message += `${tomatch.map(e => e ? '"' + e + '"' : '<any response>').join(', ')}`;
5648
- throw new BotiumError$2(message, {
5563
+ throw new BotiumError$1(message, {
5649
5564
  type: 'asserter',
5650
5565
  source: asserterType,
5651
5566
  params: {
@@ -5678,7 +5593,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5678
5593
  const werArgs = this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS];
5679
5594
  const threshold = [',', '.'].find(p => `${werArgs[0]}`.includes(p)) ? parseFloat(werArgs[0]) : parseInt(werArgs[0]) / 100;
5680
5595
  const message = `${stepTag}: Word Error Rate (${toPercent(wer)}) lower than accepted (${toPercent(threshold)})`;
5681
- throw new BotiumError$2(message, {
5596
+ throw new BotiumError$1(message, {
5682
5597
  type: 'asserter',
5683
5598
  source: asserterType,
5684
5599
  params: {
@@ -5700,7 +5615,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5700
5615
  message += ' expected NOT to match ';
5701
5616
  message += nottomatch && nottomatch.length > 1 ? 'one of ' : '';
5702
5617
  message += `${nottomatch.map(e => e ? '"' + e + '"' : '<any response>').join(', ')}`;
5703
- throw new BotiumError$2(message, {
5618
+ throw new BotiumError$1(message, {
5704
5619
  type: 'asserter',
5705
5620
  source: asserterType,
5706
5621
  params: {
@@ -5750,7 +5665,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5750
5665
  if (asserter[notAsserterType]) {
5751
5666
  return p(this.retryHelperAsserter, () => asserter[notAsserterType](params));
5752
5667
  } 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`, {
5668
+ 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
5669
  type: 'asserter',
5755
5670
  source: asserter.name || asserterSpec.name,
5756
5671
  params: {
@@ -6145,7 +6060,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6145
6060
  return !entry.header.name;
6146
6061
  });
6147
6062
  if (aggregatedNoNames.length) {
6148
- throw new BotiumError$2('Scripting Memory Definition(s) without name', {
6063
+ throw new BotiumError$1('Scripting Memory Definition(s) without name', {
6149
6064
  type: 'Scripting Memory',
6150
6065
  subtype: 'Scripting Memory without name',
6151
6066
  source: 'ScriptingProvider',
@@ -6160,7 +6075,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6160
6075
  return !entry.values || !Object.keys(entry.values).length;
6161
6076
  });
6162
6077
  if (aggregatedNoVariables.length) {
6163
- throw new BotiumError$2(`Scripting Memory Definition(s) ${aggregatedNoVariables.map(e => e.header.name).join(', ')} without variable`, {
6078
+ throw new BotiumError$1(`Scripting Memory Definition(s) ${aggregatedNoVariables.map(e => e.header.name).join(', ')} without variable`, {
6164
6079
  type: 'Scripting Memory',
6165
6080
  subtype: 'Scripting Memory without variable',
6166
6081
  source: 'ScriptingProvider',
@@ -6175,7 +6090,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6175
6090
  return !lodash.isUndefined(entry.values['']);
6176
6091
  });
6177
6092
  if (aggregatedNoVariableNames.length) {
6178
- throw new BotiumError$2(`Scripting Memory Definition(s) ${aggregatedNoVariableNames.map(e => e.header.name).join(', ')} without variable name`, {
6093
+ throw new BotiumError$1(`Scripting Memory Definition(s) ${aggregatedNoVariableNames.map(e => e.header.name).join(', ')} without variable name`, {
6179
6094
  type: 'Scripting Memory',
6180
6095
  subtype: 'Scripting Memory without variable name',
6181
6096
  source: 'ScriptingProvider',
@@ -6203,7 +6118,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6203
6118
  }
6204
6119
  }
6205
6120
  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`, {
6121
+ throw new BotiumError$1(`Scripting Memory Definition name(s) "${lodash.uniq(aggregatedDuplicates.map(d => d.scriptingMemory.header.name)).join(', ')}" are not unique`, {
6207
6122
  type: 'Scripting Memory',
6208
6123
  subtype: 'Scripting Memory name collision',
6209
6124
  source: 'ScriptingProvider',
@@ -6234,7 +6149,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6234
6149
  }
6235
6150
  }
6236
6151
  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"`, {
6152
+ throw new BotiumError$1(`Scripting Memory Definitions "${aggregatedIntersections.map(i => i.scriptingMemory.header.name).join(', ')}" are invalid because variable name collision"`, {
6238
6153
  type: 'Scripting Memory',
6239
6154
  subtype: 'Scripting Memory variable name collision',
6240
6155
  source: 'ScriptingProvider',
@@ -6797,7 +6712,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6797
6712
  }
6798
6713
  } else if (scriptingMemories) {
6799
6714
  if (!scriptingMemories.header || !scriptingMemories.header.name) {
6800
- throw new BotiumError$2('Scripting Memory Definition has no name', {
6715
+ throw new BotiumError$1('Scripting Memory Definition has no name', {
6801
6716
  type: 'Compiler',
6802
6717
  subtype: 'Scripting memory without name',
6803
6718
  source: 'ScriptingProvider',
@@ -6807,7 +6722,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6807
6722
  });
6808
6723
  }
6809
6724
  if (!scriptingMemories.values || !Object.keys(scriptingMemories.values).length) {
6810
- throw new BotiumError$2('Scripting Memory Definition has no variables', {
6725
+ throw new BotiumError$1('Scripting Memory Definition has no variables', {
6811
6726
  type: 'Compiler',
6812
6727
  subtype: 'Scripting memory without variable',
6813
6728
  source: 'ScriptingProvider',
@@ -6817,7 +6732,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6817
6732
  });
6818
6733
  }
6819
6734
  if (scriptingMemories.values && !lodash.isUndefined(scriptingMemories.values[''])) {
6820
- throw new BotiumError$2('Scripting Memory Definition variable has no name', {
6735
+ throw new BotiumError$1('Scripting Memory Definition variable has no name', {
6821
6736
  type: 'Compiler',
6822
6737
  subtype: 'Scripting memory without variable name',
6823
6738
  source: 'ScriptingProvider',
@@ -7704,7 +7619,7 @@ const {
7704
7619
  escapeJSONString
7705
7620
  } = Utils;
7706
7621
  const {
7707
- BotiumError: BotiumError$1
7622
+ BotiumError
7708
7623
  } = BotiumError_1;
7709
7624
  mustache.escape = s => s;
7710
7625
  var SimpleRestContainer_1 = class SimpleRestContainer {
@@ -8001,22 +7916,32 @@ var SimpleRestContainer_1 = class SimpleRestContainer {
8001
7916
  }
8002
7917
  const result = [];
8003
7918
  if (isFromUser) {
8004
- const _extractFrom = (root, jsonPaths) => {
8005
- const flattened = [];
7919
+ const _extractFrom = (root, jsonPaths, acceptFn = null) => {
7920
+ const result = [];
8006
7921
  for (const jsonPath of jsonPaths) {
7922
+ const jsonPathRes = [];
8007
7923
  const rb = jsonpath.query(root, jsonPath);
8008
7924
  if (lodash.isArray(rb)) {
8009
- lodash.flattenDeep(rb).forEach(r => flattened.push(r));
8010
- } else if (rb) {
8011
- flattened.push(rb);
7925
+ lodash.flattenDeep(rb).forEach(r => jsonPathRes.push(r));
7926
+ } else {
7927
+ jsonPathRes.push(rb);
7928
+ }
7929
+ if (acceptFn) {
7930
+ result.push(...jsonPathRes.filter(r => acceptFn(root, jsonPath, r)));
7931
+ } else {
7932
+ result.push(...jsonPathRes);
8012
7933
  }
8013
7934
  }
8014
- return flattened;
7935
+ return result;
8015
7936
  };
8016
7937
  const jsonPathRoots = [];
8017
7938
  const jsonPathsBody = getAllCapValues(Capabilities.SIMPLEREST_BODY_JSONPATH, this.caps);
8018
7939
  if (jsonPathsBody.length > 0) {
8019
- jsonPathRoots.push(..._extractFrom(body, jsonPathsBody));
7940
+ jsonPathRoots.push(..._extractFrom(body, jsonPathsBody, (root, jsonPath, r) => {
7941
+ if (r && lodash.isObject(r)) return true;
7942
+ debug$4(`Ignoring result body from ${jsonPath} - not a querieable object (${util.inspect(r)})`);
7943
+ return false;
7944
+ }));
8020
7945
  } else {
8021
7946
  jsonPathRoots.push(body);
8022
7947
  }
@@ -8175,7 +8100,7 @@ var SimpleRestContainer_1 = class SimpleRestContainer {
8175
8100
  const jsonBody = Utils.toJsonWeak(body);
8176
8101
  const errKey = Object.keys(jsonBody).find(k => k.startsWith('err') || k.startsWith('fail'));
8177
8102
  if (errKey) {
8178
- return reject(new BotiumError$1(`got error response: ${response.statusCode}/${response.statusMessage} - ${jsonBody[errKey]}`, {
8103
+ return reject(new BotiumError(`got error response: ${response.statusCode}/${response.statusMessage} - ${jsonBody[errKey]}`, {
8179
8104
  message: Utils.shortenJsonString(body)
8180
8105
  }));
8181
8106
  }
@@ -8630,9 +8555,6 @@ var SimpleRestContainer_1 = class SimpleRestContainer {
8630
8555
  };
8631
8556
 
8632
8557
  const debug$3 = debug$n('botium-connector-PluginConnectorContainer-helper');
8633
- const {
8634
- BotiumError
8635
- } = BotiumError_1;
8636
8558
  const pluginResolver = containermode => {
8637
8559
  if (containermode === 'simplerest') {
8638
8560
  return SimpleRestContainer_1;
@@ -8683,20 +8605,6 @@ const loadConnectorModule = (PluginClass, args) => {
8683
8605
  };
8684
8606
  const tryLoadPlugin$1 = (containermode, modulepath, args) => {
8685
8607
  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
8608
  if (pluginResolver(pluginLoaderSpec)) {
8701
8609
  const pluginInstance = new (pluginResolver(pluginLoaderSpec))(args);
8702
8610
  debug$3('Botium plugin loaded from internal plugin resolver');
@@ -8708,44 +8616,47 @@ const tryLoadPlugin$1 = (containermode, modulepath, args) => {
8708
8616
  return pluginInstance;
8709
8617
  }
8710
8618
  const loadErr = [];
8619
+ const allowUnsafe = !!args.caps[Capabilities.SECURITY_ALLOW_UNSAFE];
8711
8620
  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
- });
8621
+ if (args.caps.SAFEDIR) {
8622
+ const tryLoadFile = path.resolve(args.caps.SAFEDIR, pluginLoaderSpec);
8623
+ if (tryLoadFile.startsWith(path.resolve(args.caps.SAFEDIR))) {
8624
+ if (fs.existsSync(tryLoadFile)) {
8625
+ try {
8626
+ let plugin = commonjsRequire(tryLoadFile);
8627
+ if (plugin.default) {
8628
+ plugin = plugin.default;
8629
+ }
8630
+ if (!plugin.PluginVersion || !plugin.PluginClass) {
8631
+ loadErr.push(`Invalid Botium plugin loaded from ${tryLoadFile}, expected PluginVersion, PluginClass fields`);
8632
+ } else {
8633
+ const pluginInstance = loadConnectorModule(plugin.PluginClass, args);
8634
+ debug$3(`Botium plugin loaded from ${tryLoadFile}`);
8635
+ return pluginInstance;
8636
+ }
8637
+ } catch (err) {
8638
+ loadErr.push(`Loading Botium plugin from ${tryLoadFile} failed - ${err.message}`);
8639
+ }
8640
+ }
8641
+ }
8642
+ }
8643
+ if (allowUnsafe) {
8718
8644
  try {
8719
- let plugin = commonjsRequire(tryLoadFile);
8645
+ let plugin = commonjsRequire(pluginLoaderSpec);
8720
8646
  if (plugin.default) {
8721
8647
  plugin = plugin.default;
8722
8648
  }
8723
8649
  if (!plugin.PluginVersion || !plugin.PluginClass) {
8724
- loadErr.push(`Invalid Botium plugin loaded from ${tryLoadFile}, expected PluginVersion, PluginClass fields`);
8650
+ loadErr.push(`Invalid Botium plugin loaded from ${pluginLoaderSpec}, expected PluginVersion, PluginClass fields`);
8725
8651
  } else {
8726
8652
  const pluginInstance = loadConnectorModule(plugin.PluginClass, args);
8727
- debug$3(`Botium plugin loaded from ${tryLoadFile}`);
8653
+ debug$3(`Botium plugin loaded from ${pluginLoaderSpec}. Plugin version is ${getModuleVersionSafe(pluginLoaderSpec)}`);
8728
8654
  return pluginInstance;
8729
8655
  }
8730
8656
  } catch (err) {
8731
- loadErr.push(`Loading Botium plugin from ${tryLoadFile} failed - ${err.message}`);
8657
+ loadErr.push(`Loading Botium plugin from ${pluginLoaderSpec} failed - ${err.message}`);
8732
8658
  }
8733
8659
  }
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
8660
  const tryLoadPackage = `botium-connector-${pluginLoaderSpec}`;
8750
8661
  try {
8751
8662
  let plugin = commonjsRequire(tryLoadPackage);
@@ -8909,6 +8820,13 @@ var PluginConnectorContainer_1 = class PluginConnectorContainer extends BaseCont
8909
8820
  return Promise.reject(new Error(`Clean - Botium plugin failed: ${util.inspect(err)}`));
8910
8821
  }
8911
8822
  }
8823
+ GetMetaData() {
8824
+ try {
8825
+ return this.pluginInstance.GetMetaData ? this.pluginInstance.GetMetaData() || Promise.resolve() : Promise.resolve();
8826
+ } catch (err) {
8827
+ return Promise.reject(new Error(`GetMetaData - Botium plugin failed: ${util.inspect(err)}`));
8828
+ }
8829
+ }
8912
8830
  };
8913
8831
 
8914
8832
  var require$$3 = getCjsExportFromNamespace(_package$1);