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
@@ -15,7 +15,6 @@ var lodash = require('lodash');
15
15
  var boolean$1 = require('boolean');
16
16
  var events = require('events');
17
17
  var debug$n = require('debug');
18
- var vm2 = require('vm2');
19
18
  var isClass = require('is-class');
20
19
  var crypto = require('crypto');
21
20
  var globby = require('globby');
@@ -25,7 +24,6 @@ var uuid = require('uuid');
25
24
  var jsonpath = require('jsonpath');
26
25
  var isJson$1 = require('is-json');
27
26
  var wordErrorRate = require('word-error-rate');
28
- var esprima = require('esprima');
29
27
  var markdownIt = require('markdown-it');
30
28
  var xlsx = require('xlsx');
31
29
  var sync = require('csv-parse/sync');
@@ -55,7 +53,6 @@ var lodash__default = /*#__PURE__*/_interopDefaultLegacy(lodash);
55
53
  var boolean__default = /*#__PURE__*/_interopDefaultLegacy(boolean$1);
56
54
  var events__default = /*#__PURE__*/_interopDefaultLegacy(events);
57
55
  var debug__default = /*#__PURE__*/_interopDefaultLegacy(debug$n);
58
- var vm2__default = /*#__PURE__*/_interopDefaultLegacy(vm2);
59
56
  var isClass__default = /*#__PURE__*/_interopDefaultLegacy(isClass);
60
57
  var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto);
61
58
  var globby__default = /*#__PURE__*/_interopDefaultLegacy(globby);
@@ -65,7 +62,6 @@ var uuid__default = /*#__PURE__*/_interopDefaultLegacy(uuid);
65
62
  var jsonpath__default = /*#__PURE__*/_interopDefaultLegacy(jsonpath);
66
63
  var isJson__default = /*#__PURE__*/_interopDefaultLegacy(isJson$1);
67
64
  var wordErrorRate__default = /*#__PURE__*/_interopDefaultLegacy(wordErrorRate);
68
- var esprima__default = /*#__PURE__*/_interopDefaultLegacy(esprima);
69
65
  var markdownIt__default = /*#__PURE__*/_interopDefaultLegacy(markdownIt);
70
66
  var xlsx__default = /*#__PURE__*/_interopDefaultLegacy(xlsx);
71
67
  var sync__default = /*#__PURE__*/_interopDefaultLegacy(sync);
@@ -81,7 +77,7 @@ var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
81
77
  var bodyParser__default = /*#__PURE__*/_interopDefaultLegacy(bodyParser);
82
78
 
83
79
  var name = "botium-core";
84
- var version$1 = "1.13.19";
80
+ var version$1 = "1.14.0";
85
81
  var description = "The Selenium for Chatbots";
86
82
  var main = "index.js";
87
83
  var module$1 = "dist/botium-es.js";
@@ -99,7 +95,6 @@ var scripts = {
99
95
  link: "npm link botium-connector-dialogflow botium-connector-webdriverio botium-connector-directline3 botium-connector-watson botium-connector-alexa-smapi botium-connector-echo",
100
96
  test: "cross-env NODE_PATH=\"./test/plugins/plugindir/fromfolder:./test/plugins/plugindir/fromfile:./test/security/resources\" mocha \"./test/**/*.spec.js\"",
101
97
  "coverage:report": "nyc report --reporter=lcov npm test",
102
- "license-checker": "license-checker > LICENSES-3RDPARTY.txt",
103
98
  "update-dependencies": "npm-check-updates --reject globby,rollup -u --timeout 120000"
104
99
  };
105
100
  var repository = {
@@ -113,14 +108,13 @@ var bugs = {
113
108
  };
114
109
  var homepage = "https://www.botium.ai";
115
110
  var dependencies = {
116
- "@babel/runtime": "^7.21.5",
111
+ "@babel/runtime": "^7.22.15",
117
112
  async: "^3.2.4",
118
113
  "body-parser": "^1.20.2",
119
114
  boolean: "^3.2.0",
120
115
  bottleneck: "^2.19.5",
121
- "csv-parse": "^5.3.10",
116
+ "csv-parse": "^5.5.0",
122
117
  debug: "^4.3.4",
123
- esprima: "^4.0.1",
124
118
  express: "^4.18.2",
125
119
  globby: "11.0.4",
126
120
  ioredis: "^5.3.2",
@@ -135,45 +129,42 @@ var dependencies = {
135
129
  "moment-timezone": "^0.5.43",
136
130
  mustache: "^4.2.0",
137
131
  "promise-retry": "^2.0.1",
138
- "promise.allsettled": "^1.0.6",
132
+ "promise.allsettled": "^1.0.7",
139
133
  randomatic: "^3.1.1",
140
134
  request: "^2.88.2",
141
- rimraf: "^5.0.0",
135
+ rimraf: "^5.0.1",
142
136
  "sanitize-filename": "^1.6.3",
143
137
  slugify: "^1.6.6",
144
- "socket.io": "^4.6.1",
145
- "socket.io-client": "^4.6.1",
138
+ "socket.io": "^4.7.2",
139
+ "socket.io-client": "^4.7.2",
146
140
  "socketio-auth": "^0.1.1",
147
141
  "swagger-jsdoc": "^6.2.8",
148
- "swagger-ui-express": "^4.6.3",
142
+ "swagger-ui-express": "^5.0.0",
149
143
  uuid: "^9.0.0",
150
- vm2: "^3.9.17",
151
144
  "word-error-rate": "0.0.7",
152
145
  "write-yaml": "^1.0.0",
153
146
  xlsx: "^0.18.5",
154
147
  xregexp: "^5.1.1",
155
- yaml: "^2.2.2"
148
+ yaml: "^2.3.2"
156
149
  };
157
150
  var devDependencies = {
158
- "@babel/core": "^7.21.8",
159
- "@babel/node": "^7.20.7",
160
- "@babel/plugin-transform-runtime": "^7.21.4",
161
- "@babel/preset-env": "^7.21.5",
162
- chai: "^4.3.7",
151
+ "@babel/core": "^7.22.17",
152
+ "@babel/node": "^7.22.15",
153
+ "@babel/plugin-transform-runtime": "^7.22.15",
154
+ "@babel/preset-env": "^7.22.15",
155
+ chai: "^4.3.8",
163
156
  "chai-as-promised": "^7.1.1",
164
157
  "cross-env": "^7.0.3",
165
- eslint: "^8.40.0",
166
- "eslint-config-standard": "^17.0.0",
167
- "eslint-plugin-import": "^2.27.5",
158
+ eslint: "^8.49.0",
159
+ "eslint-config-standard": "^17.1.0",
160
+ "eslint-plugin-import": "^2.28.1",
168
161
  "eslint-plugin-mocha": "^10.1.0",
169
- "eslint-plugin-n": "^15.7.0",
162
+ "eslint-plugin-n": "^16.1.0",
170
163
  "eslint-plugin-promise": "^6.1.1",
171
164
  "eslint-plugin-standard": "^4.1.0",
172
- "license-checker": "^25.0.1",
173
- "license-compatibility-checker": "^0.3.5",
174
165
  mocha: "^10.2.0",
175
- nock: "^13.3.1",
176
- "npm-check-updates": "^16.10.12",
166
+ nock: "^13.3.3",
167
+ "npm-check-updates": "^16.13.3",
177
168
  nyc: "^15.1.0",
178
169
  rollup: "2.79.1",
179
170
  "rollup-plugin-babel": "^4.4.0",
@@ -222,6 +213,7 @@ var Capabilities = {
222
213
  TESTSESSIONNAME: 'TESTSESSIONNAME',
223
214
  TESTCASENAME: 'TESTCASENAME',
224
215
  TEMPDIR: 'TEMPDIR',
216
+ SAFEDIR: 'SAFEDIR',
225
217
  CLEANUPTEMPDIR: 'CLEANUPTEMPDIR',
226
218
  WAITFORBOTTIMEOUT: 'WAITFORBOTTIMEOUT',
227
219
  CONTAINERMODE: 'CONTAINERMODE',
@@ -231,7 +223,7 @@ var Capabilities = {
231
223
  BOTIUMGRIDURL: 'BOTIUMGRIDURL',
232
224
  BOTIUMAPITOKEN: 'BOTIUMAPITOKEN',
233
225
  BOTIUMGRIDSLOT: 'BOTIUMGRIDSLOT',
234
- // Simple Reset Bot Settings
226
+ // Simple Rest Bot Settings
235
227
  SIMPLEREST_PING_URL: 'SIMPLEREST_PING_URL',
236
228
  SIMPLEREST_PING_VERB: 'SIMPLEREST_PING_VERB',
237
229
  SIMPLEREST_PING_BODY: 'SIMPLEREST_PING_BODY',
@@ -396,6 +388,7 @@ Capabilities.PROJECTNAME;
396
388
  Capabilities.TESTSESSIONNAME;
397
389
  Capabilities.TESTCASENAME;
398
390
  Capabilities.TEMPDIR;
391
+ Capabilities.SAFEDIR;
399
392
  Capabilities.CLEANUPTEMPDIR;
400
393
  Capabilities.WAITFORBOTTIMEOUT;
401
394
  Capabilities.CONTAINERMODE;
@@ -914,140 +907,6 @@ function getCjsExportFromNamespace (n) {
914
907
  return n && n['default'] || n;
915
908
  }
916
909
 
917
- const BotiumError$7 = class BotiumError extends Error {
918
- /**
919
- *
920
- * @param message
921
- * @param context A JSON with struct
922
- * {
923
- * type: 'some free text to identity the exception type',
924
- * source: 'source of the event',
925
- * ...
926
- */
927
- constructor(message, context, supressChildCheck) {
928
- super(message.message || message);
929
- if (!supressChildCheck && _getChildErrorsFromContext(context)) {
930
- throw Error('Create BotiumError with child errors using the fromList() method!');
931
- }
932
- // Saving class name in the property of our custom error as a shortcut.
933
- this.name = this.constructor.name;
934
-
935
- // Capturing stack trace, excluding constructor call from it.
936
- Error.captureStackTrace(this, this.constructor);
937
- this.context = context || {};
938
- this.context.message = message.message || message;
939
- }
940
- isAsserterError() {
941
- if (this.context) {
942
- const errArr = lodash__default["default"].isArray(this.context) ? this.context : [this.context];
943
- const hasNotAsserterError = errArr.findIndex(errDetail => {
944
- if (errDetail.type === 'list') {
945
- if (errDetail.errors) {
946
- return errDetail.errors.findIndex(e => e.type !== 'asserter') >= 0;
947
- } else {
948
- return true;
949
- }
950
- } else {
951
- return errDetail.type !== 'asserter';
952
- }
953
- }) >= 0;
954
- if (hasNotAsserterError) return false;
955
- return true;
956
- } else {
957
- return false;
958
- }
959
- }
960
- prettify(includeJson) {
961
- const lines = [];
962
- if (this.context) {
963
- const errArr = lodash__default["default"].isArray(this.context) ? this.context : [this.context];
964
- errArr.forEach(errDetail => {
965
- lines.push('########################################');
966
- if (errDetail.type === 'asserter') {
967
- const segments = [];
968
- segments.push(`ASSERTION FAILED in ${errDetail.source}${errDetail.subtype ? ` (${errDetail.subtype})` : ''}`);
969
- errDetail.cause && errDetail.cause.expected && !errDetail.cause.not && segments.push(` - Expected: ${JSON.stringify(errDetail.cause.expected)} `);
970
- errDetail.cause && errDetail.cause.expected && errDetail.cause.not && segments.push(` - NOT Expected: ${JSON.stringify(errDetail.cause.expected)} `);
971
- errDetail.cause && errDetail.cause.actual && segments.push(` - Actual: ${JSON.stringify(errDetail.cause.actual)}`);
972
- errDetail.cause && !errDetail.cause.actual && segments.push(' - Actual: empty');
973
- lines.push(segments.join(''));
974
- errDetail.input && errDetail.input.messageText && lines.push(`INPUT: ${errDetail.input.messageText}`);
975
- } else if (errDetail.message) {
976
- lines.push(`${errDetail.message}`);
977
- }
978
- if (errDetail.transcript && errDetail.transcript.length > 0) {
979
- lines.push('------------ TRANSCRIPT ----------------------------');
980
- errDetail.transcript.forEach(transcriptStep => {
981
- if (transcriptStep.actual) {
982
- lines.push(transcriptStep.actual.prettify());
983
- }
984
- });
985
- }
986
- if (includeJson) {
987
- lines.push('------------ JSON CONTENT ----------------------------');
988
- try {
989
- const jsonOutput = JSON.stringify(errDetail);
990
- lines.push(jsonOutput);
991
- } catch (jsonErr) {
992
- lines.push(`JSON Output not possible: ${jsonErr.message}`);
993
- }
994
- }
995
- });
996
- }
997
- if (lines.length > 0) {
998
- return lines.join('\r\n');
999
- } else {
1000
- return null;
1001
- }
1002
- }
1003
- };
1004
- const _getChildErrorsFromContext = context => {
1005
- if (context && context.errors && lodash__default["default"].isArray(context.errors)) {
1006
- return context.errors;
1007
- }
1008
- return false;
1009
- };
1010
- const botiumErrorFromErr$2 = (message, err) => {
1011
- if (err instanceof BotiumError$7) {
1012
- return new BotiumError$7(message, err.context, true);
1013
- } else {
1014
- return new BotiumError$7(message, {
1015
- err
1016
- }, true);
1017
- }
1018
- };
1019
- const botiumErrorFromList$2 = (errors, {
1020
- type = 'list',
1021
- source = 'BotiumError',
1022
- flat = true
1023
- }) => {
1024
- const message = errors.map(err => err.message || err.toString()).join(',\n');
1025
- let children = [];
1026
- for (const error of errors) {
1027
- if (error instanceof BotiumError$7) {
1028
- const childErrors = flat && _getChildErrorsFromContext(error.context);
1029
- if (childErrors && childErrors.length) {
1030
- children = children.concat(childErrors);
1031
- } else if (error.context) {
1032
- children.push(error.context);
1033
- }
1034
- } else {
1035
- children.push(error);
1036
- }
1037
- }
1038
- const result = new BotiumError$7(message, {
1039
- errors: children,
1040
- type,
1041
- source
1042
- }, true);
1043
- return result;
1044
- };
1045
- var BotiumError_1 = {
1046
- BotiumError: BotiumError$7,
1047
- botiumErrorFromErr: botiumErrorFromErr$2,
1048
- botiumErrorFromList: botiumErrorFromList$2
1049
- };
1050
-
1051
910
  const LOGIC_HOOK_INCLUDE$1 = 'INCLUDE';
1052
911
  var LogicHookConsts = {
1053
912
  LOGIC_HOOK_INCLUDE: LOGIC_HOOK_INCLUDE$1,
@@ -1234,13 +1093,7 @@ LogicHookConsts.DEFAULT_ASSERTERS;
1234
1093
  LogicHookConsts.DEFAULT_LOGIC_HOOKS;
1235
1094
  LogicHookConsts.DEFAULT_USER_INPUTS;
1236
1095
 
1237
- const {
1238
- NodeVM: NodeVM$2
1239
- } = vm2__default["default"];
1240
1096
  const debug$m = debug__default["default"]('botium-core-asserterUtils');
1241
- const {
1242
- BotiumError: BotiumError$6
1243
- } = BotiumError_1;
1244
1097
  const {
1245
1098
  DEFAULT_ASSERTERS,
1246
1099
  DEFAULT_LOGIC_HOOKS,
@@ -1362,21 +1215,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1362
1215
  }, this.caps, args);
1363
1216
  }
1364
1217
  }
1365
- const _checkUnsafe = () => {
1366
- if (!this.caps[Capabilities.SECURITY_ALLOW_UNSAFE]) {
1367
- throw new BotiumError$6('Security Error. Using unsafe component is not allowed', {
1368
- type: 'security',
1369
- subtype: 'allow unsafe',
1370
- source: path__default["default"].basename(__filename),
1371
- cause: {
1372
- src: !!src,
1373
- ref,
1374
- args,
1375
- hookType
1376
- }
1377
- });
1378
- }
1379
- };
1218
+ const allowUnsafe = !!this.caps[Capabilities.SECURITY_ALLOW_UNSAFE];
1380
1219
  if (!src) {
1381
1220
  const packageName = `botium-${hookType}-${ref}`;
1382
1221
  try {
@@ -1397,10 +1236,10 @@ var LogicHookUtils_1 = class LogicHookUtils {
1397
1236
  ...this.buildScriptContext
1398
1237
  }, this.caps, args);
1399
1238
  } else {
1400
- throw new Error(`${packageName} class or function or PluginClass field expected`);
1239
+ throw new Error('Either class or function or PluginClass field expected');
1401
1240
  }
1402
1241
  } catch (err) {
1403
- throw new Error(`Failed to fetch hook ${ref} ${hookType} from guessed package ${packageName} - ${err.message}`);
1242
+ throw new Error(`Logic Hook specification ${ref} ${hookType} (${packageName}) invalid: ${err.message}`);
1404
1243
  }
1405
1244
  }
1406
1245
  if (isClass__default["default"](src)) {
@@ -1411,7 +1250,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1411
1250
  ...this.buildScriptContext
1412
1251
  }, this.caps, args);
1413
1252
  } catch (err) {
1414
- throw new Error(`Failed to load package ${ref} from provided class - ${err.message}`);
1253
+ throw new Error(`Logic Hook specification ${ref} from class invalid: ${err.message}`);
1415
1254
  }
1416
1255
  }
1417
1256
  if (lodash__default["default"].isFunction(src)) {
@@ -1421,7 +1260,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1421
1260
  ...this.buildScriptContext
1422
1261
  }, this.caps, args);
1423
1262
  } catch (err) {
1424
- throw new Error(`Failed to load package ${ref} from provided function - ${err.message}`);
1263
+ throw new Error(`Logic Hook specification ${ref} from function invalid: ${err.message}`);
1425
1264
  }
1426
1265
  }
1427
1266
  if (lodash__default["default"].isObject(src) && !lodash__default["default"].isString(src)) {
@@ -1431,26 +1270,15 @@ var LogicHookUtils_1 = class LogicHookUtils {
1431
1270
  const script = src[key];
1432
1271
  if (lodash__default["default"].isFunction(script)) {
1433
1272
  return script(args);
1434
- } else if (lodash__default["default"].isString(script)) {
1435
- try {
1436
- const vm = new NodeVM$2({
1437
- eval: false,
1438
- require: false,
1439
- sandbox: args
1440
- });
1441
- return vm.run(script);
1442
- } catch (err) {
1443
- throw new Error(`Script ${key} is not valid - ${err.message || err}`);
1444
- }
1445
1273
  } else {
1446
- throw new Error(`Script "${key}" is not valid - only functions and javascript code accepted`);
1274
+ throw new Error(`Script ${key} is not valid - only functions accepted`);
1447
1275
  }
1448
1276
  };
1449
1277
  return result;
1450
1278
  }, {});
1451
1279
  return hookObject;
1452
1280
  } catch (err) {
1453
- throw new Error(`Failed to load package ${ref} ${hookType} from provided src function - ${err.message}`);
1281
+ throw new Error(`Logic Hook specification ${ref} ${hookType} from provided src (${util__default["default"].inspect(src)}) invalid: ${err.message}`);
1454
1282
  }
1455
1283
  }
1456
1284
  if (lodash__default["default"].isString(src)) {
@@ -1461,8 +1289,8 @@ var LogicHookUtils_1 = class LogicHookUtils {
1461
1289
  }];
1462
1290
  if (src.indexOf('/') >= 0) {
1463
1291
  tryLoads.push({
1464
- tryLoadPackageName: src.substr(0, src.lastIndexOf('/')),
1465
- tryLoadAsserterByName: src.substr(src.lastIndexOf('/') + 1)
1292
+ tryLoadPackageName: src.substring(0, src.lastIndexOf('/')),
1293
+ tryLoadAsserterByName: src.substring(src.lastIndexOf('/') + 1)
1466
1294
  });
1467
1295
  }
1468
1296
  const tryLoadFromSource = (tryRequire, tryAsserterName) => {
@@ -1500,28 +1328,33 @@ var LogicHookUtils_1 = class LogicHookUtils {
1500
1328
  ...this.buildScriptContext
1501
1329
  }, this.caps, args);
1502
1330
  } else {
1503
- throw new Error(`${src} class or function expected`);
1331
+ throw new Error('Expected class or function');
1504
1332
  }
1505
1333
  };
1506
1334
  for (const tryLoad of tryLoads) {
1507
- const tryLoadFile = path__default["default"].resolve(process.cwd(), tryLoad.tryLoadPackageName);
1508
- if (fs__default["default"].existsSync(tryLoadFile)) {
1509
- _checkUnsafe();
1335
+ if (this.caps.SAFEDIR) {
1336
+ const tryLoadFile = path__default["default"].resolve(this.caps.SAFEDIR, tryLoad.tryLoadPackageName);
1337
+ if (tryLoadFile.startsWith(path__default["default"].resolve(this.caps.SAFEDIR))) {
1338
+ if (fs__default["default"].existsSync(tryLoadFile)) {
1339
+ try {
1340
+ return tryLoadFromSource(tryLoadFile, tryLoad.tryLoadAsserterByName);
1341
+ } catch (err) {
1342
+ loadErr.push(`Logic Hook specification ${ref} ${hookType} from "${src}" invalid: ${err.message} `);
1343
+ }
1344
+ }
1345
+ }
1346
+ }
1347
+ if (allowUnsafe || tryLoad.tryLoadPackageName.startsWith('botium-')) {
1510
1348
  try {
1511
- return tryLoadFromSource(tryLoadFile, tryLoad.tryLoadAsserterByName);
1349
+ return tryLoadFromSource(tryLoad.tryLoadPackageName, tryLoad.tryLoadAsserterByName);
1512
1350
  } catch (err) {
1513
- loadErr.push(`Failed to fetch ${ref} ${hookType} from ${src} - ${err.message} `);
1351
+ loadErr.push(`Logic Hook specification ${ref} ${hookType} from "${src}" invalid: ${err.message} `);
1514
1352
  }
1515
1353
  }
1516
- try {
1517
- return tryLoadFromSource(tryLoad.tryLoadPackageName, tryLoad.tryLoadAsserterByName);
1518
- } catch (err) {
1519
- loadErr.push(`Failed to fetch ${ref} ${hookType} from ${src} - ${err.message} `);
1520
- }
1521
1354
  }
1522
1355
  loadErr.forEach(debug$m);
1523
1356
  }
1524
- throw new Error(`Failed to fetch ${ref} ${hookType}, no idea how to load ...`);
1357
+ throw new Error(`Logic Hook specification ${ref} ${hookType} from "${util__default["default"].inspect(src)}" invalid : no loader available`);
1525
1358
  }
1526
1359
  };
1527
1360
 
@@ -2328,19 +2161,150 @@ var helper = {
2328
2161
  toPercent: toPercent$1
2329
2162
  };
2330
2163
 
2164
+ const BotiumError$4 = class BotiumError extends Error {
2165
+ /**
2166
+ *
2167
+ * @param message
2168
+ * @param context A JSON with struct
2169
+ * {
2170
+ * type: 'some free text to identity the exception type',
2171
+ * source: 'source of the event',
2172
+ * ...
2173
+ */
2174
+ constructor(message, context, supressChildCheck) {
2175
+ super(message.message || message);
2176
+ if (!supressChildCheck && _getChildErrorsFromContext(context)) {
2177
+ throw Error('Create BotiumError with child errors using the fromList() method!');
2178
+ }
2179
+ // Saving class name in the property of our custom error as a shortcut.
2180
+ this.name = this.constructor.name;
2181
+
2182
+ // Capturing stack trace, excluding constructor call from it.
2183
+ Error.captureStackTrace(this, this.constructor);
2184
+ this.context = context || {};
2185
+ this.context.message = message.message || message;
2186
+ }
2187
+ isAsserterError() {
2188
+ if (this.context) {
2189
+ const errArr = lodash__default["default"].isArray(this.context) ? this.context : [this.context];
2190
+ const hasNotAsserterError = errArr.findIndex(errDetail => {
2191
+ if (errDetail.type === 'list') {
2192
+ if (errDetail.errors) {
2193
+ return errDetail.errors.findIndex(e => e.type !== 'asserter') >= 0;
2194
+ } else {
2195
+ return true;
2196
+ }
2197
+ } else {
2198
+ return errDetail.type !== 'asserter';
2199
+ }
2200
+ }) >= 0;
2201
+ if (hasNotAsserterError) return false;
2202
+ return true;
2203
+ } else {
2204
+ return false;
2205
+ }
2206
+ }
2207
+ prettify(includeJson) {
2208
+ const lines = [];
2209
+ if (this.context) {
2210
+ const errArr = lodash__default["default"].isArray(this.context) ? this.context : [this.context];
2211
+ errArr.forEach(errDetail => {
2212
+ lines.push('########################################');
2213
+ if (errDetail.type === 'asserter') {
2214
+ const segments = [];
2215
+ segments.push(`ASSERTION FAILED in ${errDetail.source}${errDetail.subtype ? ` (${errDetail.subtype})` : ''}`);
2216
+ errDetail.cause && errDetail.cause.expected && !errDetail.cause.not && segments.push(` - Expected: ${JSON.stringify(errDetail.cause.expected)} `);
2217
+ errDetail.cause && errDetail.cause.expected && errDetail.cause.not && segments.push(` - NOT Expected: ${JSON.stringify(errDetail.cause.expected)} `);
2218
+ errDetail.cause && errDetail.cause.actual && segments.push(` - Actual: ${JSON.stringify(errDetail.cause.actual)}`);
2219
+ errDetail.cause && !errDetail.cause.actual && segments.push(' - Actual: empty');
2220
+ lines.push(segments.join(''));
2221
+ errDetail.input && errDetail.input.messageText && lines.push(`INPUT: ${errDetail.input.messageText}`);
2222
+ } else if (errDetail.message) {
2223
+ lines.push(`${errDetail.message}`);
2224
+ }
2225
+ if (errDetail.transcript && errDetail.transcript.length > 0) {
2226
+ lines.push('------------ TRANSCRIPT ----------------------------');
2227
+ errDetail.transcript.forEach(transcriptStep => {
2228
+ if (transcriptStep.actual) {
2229
+ lines.push(transcriptStep.actual.prettify());
2230
+ }
2231
+ });
2232
+ }
2233
+ if (includeJson) {
2234
+ lines.push('------------ JSON CONTENT ----------------------------');
2235
+ try {
2236
+ const jsonOutput = JSON.stringify(errDetail);
2237
+ lines.push(jsonOutput);
2238
+ } catch (jsonErr) {
2239
+ lines.push(`JSON Output not possible: ${jsonErr.message}`);
2240
+ }
2241
+ }
2242
+ });
2243
+ }
2244
+ if (lines.length > 0) {
2245
+ return lines.join('\r\n');
2246
+ } else {
2247
+ return null;
2248
+ }
2249
+ }
2250
+ };
2251
+ const _getChildErrorsFromContext = context => {
2252
+ if (context && context.errors && lodash__default["default"].isArray(context.errors)) {
2253
+ return context.errors;
2254
+ }
2255
+ return false;
2256
+ };
2257
+ const botiumErrorFromErr$2 = (message, err) => {
2258
+ if (err instanceof BotiumError$4) {
2259
+ return new BotiumError$4(message, err.context, true);
2260
+ } else {
2261
+ return new BotiumError$4(message, {
2262
+ err
2263
+ }, true);
2264
+ }
2265
+ };
2266
+ const botiumErrorFromList$2 = (errors, {
2267
+ type = 'list',
2268
+ source = 'BotiumError',
2269
+ flat = true
2270
+ }) => {
2271
+ const message = errors.map(err => err.message || err.toString()).join(',\n');
2272
+ let children = [];
2273
+ for (const error of errors) {
2274
+ if (error instanceof BotiumError$4) {
2275
+ const childErrors = flat && _getChildErrorsFromContext(error.context);
2276
+ if (childErrors && childErrors.length) {
2277
+ children = children.concat(childErrors);
2278
+ } else if (error.context) {
2279
+ children.push(error.context);
2280
+ }
2281
+ } else {
2282
+ children.push(error);
2283
+ }
2284
+ }
2285
+ const result = new BotiumError$4(message, {
2286
+ errors: children,
2287
+ type,
2288
+ source
2289
+ }, true);
2290
+ return result;
2291
+ };
2292
+ var BotiumError_1 = {
2293
+ BotiumError: BotiumError$4,
2294
+ botiumErrorFromErr: botiumErrorFromErr$2,
2295
+ botiumErrorFromList: botiumErrorFromList$2
2296
+ };
2297
+
2331
2298
  const debug$k = debug__default["default"]('botium-core-ScriptingMemory');
2332
2299
  const {
2333
2300
  v1: uuidv1
2334
2301
  } = uuid__default["default"];
2335
- const {
2336
- NodeVM: NodeVM$1
2337
- } = vm2__default["default"];
2338
2302
  const {
2339
2303
  quoteRegexpString: quoteRegexpString$1,
2340
2304
  toString: toString$2
2341
2305
  } = helper;
2342
2306
  const {
2343
- BotiumError: BotiumError$5
2307
+ BotiumError: BotiumError$3
2344
2308
  } = BotiumError_1;
2345
2309
 
2346
2310
  // If they got parameter, then it will be a string always.
@@ -2497,28 +2461,6 @@ const SCRIPTING_FUNCTIONS_RAW = {
2497
2461
  if (root && root.length > 0) return root[0];else return '';
2498
2462
  },
2499
2463
  numberOfArguments: 1
2500
- },
2501
- $func: {
2502
- handler: (caps, code) => {
2503
- if (code == null) {
2504
- throw Error('func function used without args!');
2505
- }
2506
- try {
2507
- const vm = new NodeVM$1({
2508
- eval: false,
2509
- require: false,
2510
- env: caps[Capabilities.SECURITY_ALLOW_UNSAFE] ? process.env : {},
2511
- sandbox: {
2512
- caps,
2513
- moment: moment__default["default"]
2514
- }
2515
- });
2516
- return vm.run(`module.exports = (${code})`);
2517
- } catch (err) {
2518
- throw Error(`func function execution failed - ${err}`);
2519
- }
2520
- },
2521
- numberOfArguments: 1
2522
2464
  }
2523
2465
  };
2524
2466
  const SCRIPTING_FUNCTIONS$1 = lodash__default["default"].mapValues(SCRIPTING_FUNCTIONS_RAW, (funcOrStruct, name) => {
@@ -2527,7 +2469,7 @@ const SCRIPTING_FUNCTIONS$1 = lodash__default["default"].mapValues(SCRIPTING_FUN
2527
2469
  return {
2528
2470
  handler: (caps, ...rest) => {
2529
2471
  if (!caps[Capabilities.SECURITY_ALLOW_UNSAFE] && funcOrStruct.unsafe) {
2530
- throw new BotiumError$5(`Security Error. Using unsafe scripting memory function ${name} is not allowed`, {
2472
+ throw new BotiumError$3(`Security Error. Using unsafe scripting memory function ${name} is not allowed`, {
2531
2473
  type: 'security',
2532
2474
  subtype: 'allow unsafe',
2533
2475
  source: path__default["default"].basename(__filename),
@@ -2667,7 +2609,7 @@ ScriptingMemory.SCRIPTING_FUNCTIONS;
2667
2609
 
2668
2610
  const debug$j = debug__default["default"]('botium-core-Convo');
2669
2611
  const {
2670
- BotiumError: BotiumError$4,
2612
+ BotiumError: BotiumError$2,
2671
2613
  botiumErrorFromErr: botiumErrorFromErr$1,
2672
2614
  botiumErrorFromList: botiumErrorFromList$1
2673
2615
  } = BotiumError_1;
@@ -3165,7 +3107,7 @@ class Convo$6 {
3165
3107
  }
3166
3108
  }
3167
3109
  if (!botMsg || !botMsg.messageText && !botMsg.media && !botMsg.buttons && !botMsg.cards && !botMsg.sourceData && !botMsg.nlp) {
3168
- const failErr = new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot says nothing`);
3110
+ const failErr = new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot says nothing`);
3169
3111
  debug$j(failErr);
3170
3112
  try {
3171
3113
  this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
@@ -3251,7 +3193,7 @@ class Convo$6 {
3251
3193
  try {
3252
3194
  this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
3253
3195
  } catch (failErr) {}
3254
- if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS] && err instanceof BotiumError$4) {
3196
+ if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS] && err instanceof BotiumError$2) {
3255
3197
  assertErrors.push(err);
3256
3198
  } else {
3257
3199
  throw failErr;
@@ -3267,7 +3209,7 @@ class Convo$6 {
3267
3209
  }
3268
3210
  }
3269
3211
  } else {
3270
- const failErr = new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: invalid sender - ${util__default["default"].inspect(convoStep.sender)}`);
3212
+ const failErr = new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: invalid sender - ${util__default["default"].inspect(convoStep.sender)}`);
3271
3213
  debug$j(failErr);
3272
3214
  try {
3273
3215
  this.scriptingEvents.fail && this.scriptingEvents.fail(failErr);
@@ -3276,7 +3218,7 @@ class Convo$6 {
3276
3218
  }
3277
3219
  } catch (err) {
3278
3220
  if (lastMeConvoStep) {
3279
- if (err instanceof BotiumError$4 && err.context) {
3221
+ if (err instanceof BotiumError$2 && err.context) {
3280
3222
  err.context.input = new ConvoStep$1(lastMeConvoStep);
3281
3223
  err.context.transcript = [...transcriptSteps, {
3282
3224
  ...transcriptStep
@@ -3289,7 +3231,7 @@ class Convo$6 {
3289
3231
  }
3290
3232
  }
3291
3233
  transcriptStep.err = err;
3292
- if (err instanceof BotiumError$4 && container.caps[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]) {
3234
+ if (err instanceof BotiumError$2 && container.caps[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]) {
3293
3235
  if (!err.isAsserterError()) {
3294
3236
  throw err;
3295
3237
  }
@@ -3322,10 +3264,10 @@ class Convo$6 {
3322
3264
  if (expected === null || expected === undefined) return;
3323
3265
  if (lodash__default["default"].isArray(expected)) {
3324
3266
  if (!lodash__default["default"].isArray(result)) {
3325
- throw new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot response expected array, got "${result}"`);
3267
+ throw new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot response expected array, got "${result}"`);
3326
3268
  }
3327
3269
  if (expected.length !== result.length) {
3328
- throw new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot response expected array length ${expected.length}, got ${result.length}`);
3270
+ throw new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot response expected array length ${expected.length}, got ${result.length}`);
3329
3271
  }
3330
3272
  for (let i = 0; i < expected.length; i++) {
3331
3273
  this._compareObject(container, scriptingMemory, convoStep, result[i], expected[i]);
@@ -3335,7 +3277,7 @@ class Convo$6 {
3335
3277
  if (Object.prototype.hasOwnProperty.call(result, key)) {
3336
3278
  this._compareObject(container, scriptingMemory, convoStep, result[key], expected[key]);
3337
3279
  } else {
3338
- throw new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot response "${result}" missing expected property: ${key}`);
3280
+ throw new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot response "${result}" missing expected property: ${key}`);
3339
3281
  }
3340
3282
  });
3341
3283
  } else {
@@ -3464,14 +3406,14 @@ class Convo$6 {
3464
3406
  includeLogicHooks.forEach(includeLogicHook => {
3465
3407
  const alreadyThereAt = parentPConvos.indexOf(includeLogicHook);
3466
3408
  if (alreadyThereAt >= 0) {
3467
- throw new BotiumError$4(`Partial convos are included circular. "${includeLogicHook}" is referenced by "/${parentPConvos.slice(0, alreadyThereAt).join('/')}" and by "/${parentPConvos.join('/')}" `);
3409
+ throw new BotiumError$2(`Partial convos are included circular. "${includeLogicHook}" is referenced by "/${parentPConvos.slice(0, alreadyThereAt).join('/')}" and by "/${parentPConvos.join('/')}" `);
3468
3410
  }
3469
3411
  if (!partialConvos || Object.keys(partialConvos).length === 0) {
3470
- throw new BotiumError$4(`Cant find partial convo with name ${includeLogicHook} (There are no partial convos)`);
3412
+ throw new BotiumError$2(`Cant find partial convo with name ${includeLogicHook} (There are no partial convos)`);
3471
3413
  }
3472
3414
  const partialConvo = partialConvos[includeLogicHook];
3473
3415
  if (!partialConvo) {
3474
- throw new BotiumError$4(`Cant find partial convo with name ${includeLogicHook} (available partial convos: ${Object.keys(partialConvos).join(',')})`);
3416
+ throw new BotiumError$2(`Cant find partial convo with name ${includeLogicHook} (available partial convos: ${Object.keys(partialConvos).join(',')})`);
3475
3417
  }
3476
3418
  _getEffectiveConversationRecursive(partialConvo.conversation, [...parentPConvos, includeLogicHook], result, true);
3477
3419
  debug$j(`Partial convo ${includeLogicHook} included`);
@@ -3806,44 +3748,21 @@ var JsonToJson = {
3806
3748
  precompile: precompile$2
3807
3749
  };
3808
3750
 
3809
- const {
3810
- NodeVM
3811
- } = vm2__default["default"];
3812
3751
  const debug$h = debug__default["default"]('botium-core-HookUtils');
3813
- const {
3814
- BotiumError: BotiumError$3
3815
- } = BotiumError_1;
3816
- const executeHook$2 = async (caps, hook, args) => {
3817
- return executeHookSync$1(caps, hook, args);
3752
+ const executeHook$2 = async (caps, hook, ...args) => {
3753
+ return executeHookSync$1(caps, hook, ...args);
3818
3754
  };
3819
- const executeHookSync$1 = (caps, hook, args) => {
3755
+ const executeHookSync$1 = (caps, hook, ...args) => {
3820
3756
  if (!hook) {
3821
3757
  return;
3822
3758
  }
3823
3759
  if (lodash__default["default"].isFunction(hook)) {
3824
3760
  try {
3825
- return hook(args);
3761
+ return hook(...args);
3826
3762
  } catch (err) {
3827
3763
  throw new Error(`Calling Hook function failed: ${err.message}`);
3828
3764
  }
3829
3765
  }
3830
- if (lodash__default["default"].isString(hook)) {
3831
- try {
3832
- const vm = new NodeVM({
3833
- eval: false,
3834
- require: false,
3835
- sandbox: args
3836
- });
3837
- const r = vm.run(hook);
3838
- if (lodash__default["default"].isFunction(r)) {
3839
- return r(args);
3840
- } else {
3841
- return r;
3842
- }
3843
- } catch (err) {
3844
- throw new Error(`Calling Hook Javascript code failed: ${err.message}`);
3845
- }
3846
- }
3847
3766
  throw new Error(`Unknown hook ${typeof hook}`);
3848
3767
  };
3849
3768
  const getHook$3 = (caps, data) => {
@@ -3856,46 +3775,40 @@ const getHook$3 = (caps, data) => {
3856
3775
  return data;
3857
3776
  }
3858
3777
  if (lodash__default["default"].isString(data)) {
3859
- let resultWithRequire;
3860
- let tryLoadFile = path__default["default"].resolve(process.cwd(), data);
3861
- if (fs__default["default"].existsSync(tryLoadFile)) {
3862
- try {
3863
- resultWithRequire = commonjsRequire(tryLoadFile);
3864
- } catch (err) {}
3865
- } else {
3866
- tryLoadFile = data;
3867
- try {
3868
- resultWithRequire = commonjsRequire(data);
3869
- } catch (err) {}
3870
- }
3871
- if (resultWithRequire) {
3872
- if (!allowUnsafe) {
3873
- throw new BotiumError$3('Security Error. Using unsafe custom hook with require is not allowed', {
3874
- type: 'security',
3875
- subtype: 'allow unsafe',
3876
- source: path__default["default"].basename(__filename),
3877
- cause: {
3878
- SECURITY_ALLOW_UNSAFE: caps[Capabilities.SECURITY_ALLOW_UNSAFE],
3879
- hookData: data
3778
+ if (caps.SAFEDIR) {
3779
+ const tryLoadFile = path__default["default"].resolve(caps.SAFEDIR, data);
3780
+ if (tryLoadFile.startsWith(path__default["default"].resolve(caps.SAFEDIR))) {
3781
+ if (fs__default["default"].existsSync(tryLoadFile)) {
3782
+ try {
3783
+ const resultWithRequire = commonjsRequire(tryLoadFile);
3784
+ if (lodash__default["default"].isFunction(resultWithRequire)) {
3785
+ debug$h(`found hook, type: safedir, in ${tryLoadFile}`);
3786
+ return resultWithRequire;
3787
+ } else {
3788
+ throw new Error(`Expected function from hook specification "${util__default["default"].inspect(data)}", got: "${util__default["default"].inspect(resultWithRequire)}"`);
3789
+ }
3790
+ } catch (err) {
3791
+ debug$h(`Failed loading hook, type: safedir, from ${tryLoadFile} failed: ${err.message || err}`);
3880
3792
  }
3881
- });
3882
- }
3883
- if (lodash__default["default"].isFunction(resultWithRequire)) {
3884
- debug$h(`found hook, type: require, in ${tryLoadFile}`);
3885
- return resultWithRequire;
3886
- } else {
3887
- throw new Error(`Cant load hook ${tryLoadFile} because it is not a function`);
3793
+ }
3888
3794
  }
3889
3795
  }
3890
- try {
3891
- esprima__default["default"].parseScript(data);
3892
- } catch (err) {
3893
- throw new Error(`Cant load hook, syntax is not valid - ${util__default["default"].inspect(err)}`);
3796
+ if (allowUnsafe || data.startsWith('botium-')) {
3797
+ const tryLoadFile = data;
3798
+ try {
3799
+ const resultWithRequire = commonjsRequire(tryLoadFile);
3800
+ if (lodash__default["default"].isFunction(resultWithRequire)) {
3801
+ debug$h(`found hook, type: require, in ${tryLoadFile}`);
3802
+ return resultWithRequire;
3803
+ } else {
3804
+ throw new Error(`Expected function from hook specification "${util__default["default"].inspect(data)}", got: "${util__default["default"].inspect(resultWithRequire)}"`);
3805
+ }
3806
+ } catch (err) {
3807
+ debug$h(`Failed loading hook, type: require, from ${tryLoadFile} failed: ${err.message || err}`);
3808
+ }
3894
3809
  }
3895
- debug$h('Found hook, type: JavaScript as String');
3896
- return data;
3897
3810
  }
3898
- throw new Error(`Not valid hook ${util__default["default"].inspect(data)}`);
3811
+ throw new Error(`Hook specification "${util__default["default"].inspect(data)}" invalid: no loader available`);
3899
3812
  };
3900
3813
  var HookUtils = {
3901
3814
  getHook: getHook$3,
@@ -5391,7 +5304,7 @@ const {
5391
5304
  ConvoStep
5392
5305
  } = Convo_1;
5393
5306
  const {
5394
- BotiumError: BotiumError$2,
5307
+ BotiumError: BotiumError$1,
5395
5308
  botiumErrorFromList,
5396
5309
  botiumErrorFromErr
5397
5310
  } = BotiumError_1;
@@ -5667,7 +5580,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5667
5580
  const werArgs = this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS];
5668
5581
  const threshold = [',', '.'].find(p => `${werArgs[0]}`.includes(p)) ? parseFloat(werArgs[0]) : parseInt(werArgs[0]) / 100;
5669
5582
  const message = `${stepTag}: Word Error Rate (${toPercent(wer)}) higher than accepted (${toPercent(threshold)})`;
5670
- throw new BotiumError$2(message, {
5583
+ throw new BotiumError$1(message, {
5671
5584
  type: 'asserter',
5672
5585
  source: asserterType,
5673
5586
  params: {
@@ -5689,7 +5602,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5689
5602
  message += ' expected to match ';
5690
5603
  message += tomatch && tomatch.length > 1 ? 'one of ' : '';
5691
5604
  message += `${tomatch.map(e => e ? '"' + e + '"' : '<any response>').join(', ')}`;
5692
- throw new BotiumError$2(message, {
5605
+ throw new BotiumError$1(message, {
5693
5606
  type: 'asserter',
5694
5607
  source: asserterType,
5695
5608
  params: {
@@ -5722,7 +5635,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5722
5635
  const werArgs = this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS];
5723
5636
  const threshold = [',', '.'].find(p => `${werArgs[0]}`.includes(p)) ? parseFloat(werArgs[0]) : parseInt(werArgs[0]) / 100;
5724
5637
  const message = `${stepTag}: Word Error Rate (${toPercent(wer)}) lower than accepted (${toPercent(threshold)})`;
5725
- throw new BotiumError$2(message, {
5638
+ throw new BotiumError$1(message, {
5726
5639
  type: 'asserter',
5727
5640
  source: asserterType,
5728
5641
  params: {
@@ -5744,7 +5657,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5744
5657
  message += ' expected NOT to match ';
5745
5658
  message += nottomatch && nottomatch.length > 1 ? 'one of ' : '';
5746
5659
  message += `${nottomatch.map(e => e ? '"' + e + '"' : '<any response>').join(', ')}`;
5747
- throw new BotiumError$2(message, {
5660
+ throw new BotiumError$1(message, {
5748
5661
  type: 'asserter',
5749
5662
  source: asserterType,
5750
5663
  params: {
@@ -5794,7 +5707,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5794
5707
  if (asserter[notAsserterType]) {
5795
5708
  return p(this.retryHelperAsserter, () => asserter[notAsserterType](params));
5796
5709
  } else {
5797
- return pnot(this.retryHelperAsserter, () => asserter[asserterType](params), new BotiumError$2(`${convoStep.stepTag}: Expected asserter ${asserter.name || asserterSpec.name} with args "${params.args}" to fail`, {
5710
+ return pnot(this.retryHelperAsserter, () => asserter[asserterType](params), new BotiumError$1(`${convoStep.stepTag}: Expected asserter ${asserter.name || asserterSpec.name} with args "${params.args}" to fail`, {
5798
5711
  type: 'asserter',
5799
5712
  source: asserter.name || asserterSpec.name,
5800
5713
  params: {
@@ -6189,7 +6102,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6189
6102
  return !entry.header.name;
6190
6103
  });
6191
6104
  if (aggregatedNoNames.length) {
6192
- throw new BotiumError$2('Scripting Memory Definition(s) without name', {
6105
+ throw new BotiumError$1('Scripting Memory Definition(s) without name', {
6193
6106
  type: 'Scripting Memory',
6194
6107
  subtype: 'Scripting Memory without name',
6195
6108
  source: 'ScriptingProvider',
@@ -6204,7 +6117,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6204
6117
  return !entry.values || !Object.keys(entry.values).length;
6205
6118
  });
6206
6119
  if (aggregatedNoVariables.length) {
6207
- throw new BotiumError$2(`Scripting Memory Definition(s) ${aggregatedNoVariables.map(e => e.header.name).join(', ')} without variable`, {
6120
+ throw new BotiumError$1(`Scripting Memory Definition(s) ${aggregatedNoVariables.map(e => e.header.name).join(', ')} without variable`, {
6208
6121
  type: 'Scripting Memory',
6209
6122
  subtype: 'Scripting Memory without variable',
6210
6123
  source: 'ScriptingProvider',
@@ -6219,7 +6132,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6219
6132
  return !lodash__default["default"].isUndefined(entry.values['']);
6220
6133
  });
6221
6134
  if (aggregatedNoVariableNames.length) {
6222
- throw new BotiumError$2(`Scripting Memory Definition(s) ${aggregatedNoVariableNames.map(e => e.header.name).join(', ')} without variable name`, {
6135
+ throw new BotiumError$1(`Scripting Memory Definition(s) ${aggregatedNoVariableNames.map(e => e.header.name).join(', ')} without variable name`, {
6223
6136
  type: 'Scripting Memory',
6224
6137
  subtype: 'Scripting Memory without variable name',
6225
6138
  source: 'ScriptingProvider',
@@ -6247,7 +6160,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6247
6160
  }
6248
6161
  }
6249
6162
  if (aggregatedDuplicates.length) {
6250
- throw new BotiumError$2(`Scripting Memory Definition name(s) "${lodash__default["default"].uniq(aggregatedDuplicates.map(d => d.scriptingMemory.header.name)).join(', ')}" are not unique`, {
6163
+ throw new BotiumError$1(`Scripting Memory Definition name(s) "${lodash__default["default"].uniq(aggregatedDuplicates.map(d => d.scriptingMemory.header.name)).join(', ')}" are not unique`, {
6251
6164
  type: 'Scripting Memory',
6252
6165
  subtype: 'Scripting Memory name collision',
6253
6166
  source: 'ScriptingProvider',
@@ -6278,7 +6191,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6278
6191
  }
6279
6192
  }
6280
6193
  if (aggregatedIntersections.length) {
6281
- throw new BotiumError$2(`Scripting Memory Definitions "${aggregatedIntersections.map(i => i.scriptingMemory.header.name).join(', ')}" are invalid because variable name collision"`, {
6194
+ throw new BotiumError$1(`Scripting Memory Definitions "${aggregatedIntersections.map(i => i.scriptingMemory.header.name).join(', ')}" are invalid because variable name collision"`, {
6282
6195
  type: 'Scripting Memory',
6283
6196
  subtype: 'Scripting Memory variable name collision',
6284
6197
  source: 'ScriptingProvider',
@@ -6841,7 +6754,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6841
6754
  }
6842
6755
  } else if (scriptingMemories) {
6843
6756
  if (!scriptingMemories.header || !scriptingMemories.header.name) {
6844
- throw new BotiumError$2('Scripting Memory Definition has no name', {
6757
+ throw new BotiumError$1('Scripting Memory Definition has no name', {
6845
6758
  type: 'Compiler',
6846
6759
  subtype: 'Scripting memory without name',
6847
6760
  source: 'ScriptingProvider',
@@ -6851,7 +6764,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6851
6764
  });
6852
6765
  }
6853
6766
  if (!scriptingMemories.values || !Object.keys(scriptingMemories.values).length) {
6854
- throw new BotiumError$2('Scripting Memory Definition has no variables', {
6767
+ throw new BotiumError$1('Scripting Memory Definition has no variables', {
6855
6768
  type: 'Compiler',
6856
6769
  subtype: 'Scripting memory without variable',
6857
6770
  source: 'ScriptingProvider',
@@ -6861,7 +6774,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6861
6774
  });
6862
6775
  }
6863
6776
  if (scriptingMemories.values && !lodash__default["default"].isUndefined(scriptingMemories.values[''])) {
6864
- throw new BotiumError$2('Scripting Memory Definition variable has no name', {
6777
+ throw new BotiumError$1('Scripting Memory Definition variable has no name', {
6865
6778
  type: 'Compiler',
6866
6779
  subtype: 'Scripting memory without variable name',
6867
6780
  source: 'ScriptingProvider',
@@ -7748,7 +7661,7 @@ const {
7748
7661
  escapeJSONString
7749
7662
  } = Utils;
7750
7663
  const {
7751
- BotiumError: BotiumError$1
7664
+ BotiumError
7752
7665
  } = BotiumError_1;
7753
7666
  mustache__default["default"].escape = s => s;
7754
7667
  var SimpleRestContainer_1 = class SimpleRestContainer {
@@ -8045,22 +7958,32 @@ var SimpleRestContainer_1 = class SimpleRestContainer {
8045
7958
  }
8046
7959
  const result = [];
8047
7960
  if (isFromUser) {
8048
- const _extractFrom = (root, jsonPaths) => {
8049
- const flattened = [];
7961
+ const _extractFrom = (root, jsonPaths, acceptFn = null) => {
7962
+ const result = [];
8050
7963
  for (const jsonPath of jsonPaths) {
7964
+ const jsonPathRes = [];
8051
7965
  const rb = jsonpath__default["default"].query(root, jsonPath);
8052
7966
  if (lodash__default["default"].isArray(rb)) {
8053
- lodash__default["default"].flattenDeep(rb).forEach(r => flattened.push(r));
8054
- } else if (rb) {
8055
- flattened.push(rb);
7967
+ lodash__default["default"].flattenDeep(rb).forEach(r => jsonPathRes.push(r));
7968
+ } else {
7969
+ jsonPathRes.push(rb);
7970
+ }
7971
+ if (acceptFn) {
7972
+ result.push(...jsonPathRes.filter(r => acceptFn(root, jsonPath, r)));
7973
+ } else {
7974
+ result.push(...jsonPathRes);
8056
7975
  }
8057
7976
  }
8058
- return flattened;
7977
+ return result;
8059
7978
  };
8060
7979
  const jsonPathRoots = [];
8061
7980
  const jsonPathsBody = getAllCapValues(Capabilities.SIMPLEREST_BODY_JSONPATH, this.caps);
8062
7981
  if (jsonPathsBody.length > 0) {
8063
- jsonPathRoots.push(..._extractFrom(body, jsonPathsBody));
7982
+ jsonPathRoots.push(..._extractFrom(body, jsonPathsBody, (root, jsonPath, r) => {
7983
+ if (r && lodash__default["default"].isObject(r)) return true;
7984
+ debug$4(`Ignoring result body from ${jsonPath} - not a querieable object (${util__default["default"].inspect(r)})`);
7985
+ return false;
7986
+ }));
8064
7987
  } else {
8065
7988
  jsonPathRoots.push(body);
8066
7989
  }
@@ -8219,7 +8142,7 @@ var SimpleRestContainer_1 = class SimpleRestContainer {
8219
8142
  const jsonBody = Utils.toJsonWeak(body);
8220
8143
  const errKey = Object.keys(jsonBody).find(k => k.startsWith('err') || k.startsWith('fail'));
8221
8144
  if (errKey) {
8222
- return reject(new BotiumError$1(`got error response: ${response.statusCode}/${response.statusMessage} - ${jsonBody[errKey]}`, {
8145
+ return reject(new BotiumError(`got error response: ${response.statusCode}/${response.statusMessage} - ${jsonBody[errKey]}`, {
8223
8146
  message: Utils.shortenJsonString(body)
8224
8147
  }));
8225
8148
  }
@@ -8674,9 +8597,6 @@ var SimpleRestContainer_1 = class SimpleRestContainer {
8674
8597
  };
8675
8598
 
8676
8599
  const debug$3 = debug__default["default"]('botium-connector-PluginConnectorContainer-helper');
8677
- const {
8678
- BotiumError
8679
- } = BotiumError_1;
8680
8600
  const pluginResolver = containermode => {
8681
8601
  if (containermode === 'simplerest') {
8682
8602
  return SimpleRestContainer_1;
@@ -8727,20 +8647,6 @@ const loadConnectorModule = (PluginClass, args) => {
8727
8647
  };
8728
8648
  const tryLoadPlugin$1 = (containermode, modulepath, args) => {
8729
8649
  const pluginLoaderSpec = modulepath || containermode;
8730
- const _checkUnsafe = (caps, mode, cause) => {
8731
- if (!caps[Capabilities.SECURITY_ALLOW_UNSAFE]) {
8732
- throw new BotiumError(`Security Error. Using unsafe connector mode "${mode}" is not allowed`, {
8733
- type: 'security',
8734
- subtype: 'allow unsafe',
8735
- source: 'src/containers/plugins/index.js',
8736
- cause: {
8737
- SECURITY_ALLOW_UNSAFE: caps[Capabilities.SECURITY_ALLOW_UNSAFE],
8738
- mode,
8739
- ...cause
8740
- }
8741
- });
8742
- }
8743
- };
8744
8650
  if (pluginResolver(pluginLoaderSpec)) {
8745
8651
  const pluginInstance = new (pluginResolver(pluginLoaderSpec))(args);
8746
8652
  debug$3('Botium plugin loaded from internal plugin resolver');
@@ -8752,44 +8658,47 @@ const tryLoadPlugin$1 = (containermode, modulepath, args) => {
8752
8658
  return pluginInstance;
8753
8659
  }
8754
8660
  const loadErr = [];
8661
+ const allowUnsafe = !!args.caps[Capabilities.SECURITY_ALLOW_UNSAFE];
8755
8662
  if (lodash__default["default"].isString(pluginLoaderSpec)) {
8756
- const tryLoadFile = path__default["default"].resolve(process.cwd(), pluginLoaderSpec);
8757
- if (fs__default["default"].existsSync(tryLoadFile)) {
8758
- _checkUnsafe(args.caps, 'Using work dir', {
8759
- modulepath,
8760
- containermode
8761
- });
8663
+ if (args.caps.SAFEDIR) {
8664
+ const tryLoadFile = path__default["default"].resolve(args.caps.SAFEDIR, pluginLoaderSpec);
8665
+ if (tryLoadFile.startsWith(path__default["default"].resolve(args.caps.SAFEDIR))) {
8666
+ if (fs__default["default"].existsSync(tryLoadFile)) {
8667
+ try {
8668
+ let plugin = commonjsRequire(tryLoadFile);
8669
+ if (plugin.default) {
8670
+ plugin = plugin.default;
8671
+ }
8672
+ if (!plugin.PluginVersion || !plugin.PluginClass) {
8673
+ loadErr.push(`Invalid Botium plugin loaded from ${tryLoadFile}, expected PluginVersion, PluginClass fields`);
8674
+ } else {
8675
+ const pluginInstance = loadConnectorModule(plugin.PluginClass, args);
8676
+ debug$3(`Botium plugin loaded from ${tryLoadFile}`);
8677
+ return pluginInstance;
8678
+ }
8679
+ } catch (err) {
8680
+ loadErr.push(`Loading Botium plugin from ${tryLoadFile} failed - ${err.message}`);
8681
+ }
8682
+ }
8683
+ }
8684
+ }
8685
+ if (allowUnsafe) {
8762
8686
  try {
8763
- let plugin = commonjsRequire(tryLoadFile);
8687
+ let plugin = commonjsRequire(pluginLoaderSpec);
8764
8688
  if (plugin.default) {
8765
8689
  plugin = plugin.default;
8766
8690
  }
8767
8691
  if (!plugin.PluginVersion || !plugin.PluginClass) {
8768
- loadErr.push(`Invalid Botium plugin loaded from ${tryLoadFile}, expected PluginVersion, PluginClass fields`);
8692
+ loadErr.push(`Invalid Botium plugin loaded from ${pluginLoaderSpec}, expected PluginVersion, PluginClass fields`);
8769
8693
  } else {
8770
8694
  const pluginInstance = loadConnectorModule(plugin.PluginClass, args);
8771
- debug$3(`Botium plugin loaded from ${tryLoadFile}`);
8695
+ debug$3(`Botium plugin loaded from ${pluginLoaderSpec}. Plugin version is ${getModuleVersionSafe(pluginLoaderSpec)}`);
8772
8696
  return pluginInstance;
8773
8697
  }
8774
8698
  } catch (err) {
8775
- loadErr.push(`Loading Botium plugin from ${tryLoadFile} failed - ${err.message}`);
8699
+ loadErr.push(`Loading Botium plugin from ${pluginLoaderSpec} failed - ${err.message}`);
8776
8700
  }
8777
8701
  }
8778
- try {
8779
- let plugin = commonjsRequire(pluginLoaderSpec);
8780
- if (plugin.default) {
8781
- plugin = plugin.default;
8782
- }
8783
- if (!plugin.PluginVersion || !plugin.PluginClass) {
8784
- loadErr.push(`Invalid Botium plugin loaded from ${pluginLoaderSpec}, expected PluginVersion, PluginClass fields`);
8785
- } else {
8786
- const pluginInstance = loadConnectorModule(plugin.PluginClass, args);
8787
- debug$3(`Botium plugin loaded from ${pluginLoaderSpec}. Plugin version is ${getModuleVersionSafe(pluginLoaderSpec)}`);
8788
- return pluginInstance;
8789
- }
8790
- } catch (err) {
8791
- loadErr.push(`Loading Botium plugin from ${pluginLoaderSpec} failed - ${err.message}`);
8792
- }
8793
8702
  const tryLoadPackage = `botium-connector-${pluginLoaderSpec}`;
8794
8703
  try {
8795
8704
  let plugin = commonjsRequire(tryLoadPackage);
@@ -8953,6 +8862,13 @@ var PluginConnectorContainer_1 = class PluginConnectorContainer extends BaseCont
8953
8862
  return Promise.reject(new Error(`Clean - Botium plugin failed: ${util__default["default"].inspect(err)}`));
8954
8863
  }
8955
8864
  }
8865
+ GetMetaData() {
8866
+ try {
8867
+ return this.pluginInstance.GetMetaData ? this.pluginInstance.GetMetaData() || Promise.resolve() : Promise.resolve();
8868
+ } catch (err) {
8869
+ return Promise.reject(new Error(`GetMetaData - Botium plugin failed: ${util__default["default"].inspect(err)}`));
8870
+ }
8871
+ }
8956
8872
  };
8957
8873
 
8958
8874
  var require$$3 = getCjsExportFromNamespace(_package$1);