@itentialopensource/adapter-utils 5.10.16 → 5.10.18

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.
package/README.md CHANGED
@@ -3,7 +3,7 @@ Itential Adapter Utilities
3
3
 
4
4
  Itential Adapter Utilities is a set of Node.js runtime libraries used by Itential Adapters.
5
5
 
6
- Many of the capabilities supported in Itential Adapters are built into this library so that they can e better maintained and added to adapters.
6
+ Many of the capabilities supported in Itential Adapters are built into this library so that they can be better maintained and added to adapters.
7
7
 
8
8
  # Usage
9
9
 
@@ -267,54 +267,6 @@ function waitForSystem(callProperties) {
267
267
  });
268
268
  }
269
269
 
270
- /*
271
- * INTERNAL FUNCTION: Get the best match for the moc k data response
272
- */
273
- function matchMock(uriPath, method, type, mockresponses, respDatatype) {
274
- // Go through the mock data keys to find the proper data to return
275
- for (let p = 0; p < mockresponses.length; p += 1) {
276
- // is this the mock data for this call
277
- if (Object.hasOwnProperty.call(mockresponses[p], 'name')
278
- && uriPath === mockresponses[p].name) {
279
- if (Object.hasOwnProperty.call(mockresponses[p], 'method')
280
- && method.toUpperCase() === mockresponses[p].method.toUpperCase()) {
281
- if (Object.hasOwnProperty.call(mockresponses[p], 'type')
282
- && type.toUpperCase() === mockresponses[p].type.toUpperCase()) {
283
- // This is the mock data we really want as it best matches the request
284
- const specificResp = {
285
- status: 'success',
286
- code: 200,
287
- response: {}
288
- };
289
-
290
- if (Object.hasOwnProperty.call(mockresponses[p], 'response')) {
291
- // if a status is defined in the response, use it
292
- if (Object.hasOwnProperty.call(mockresponses[p].response, 'response')
293
- && Object.hasOwnProperty.call(mockresponses[p].response, 'status')) {
294
- specificResp.code = mockresponses[p].response.status;
295
-
296
- if (respDatatype && respDatatype.toUpperCase() === 'XML2JSON') {
297
- specificResp.response = mockresponses[p].response.response;
298
- } else {
299
- specificResp.response = JSON.stringify(mockresponses[p].response.response);
300
- }
301
- } else if (respDatatype && respDatatype.toUpperCase() === 'XML2JSON') {
302
- // if no response field, assume that the entire data is the response
303
- specificResp.response = mockresponses[p].response;
304
- } else {
305
- specificResp.response = JSON.stringify(mockresponses[p].response);
306
- }
307
- }
308
-
309
- return specificResp;
310
- }
311
- }
312
- }
313
- }
314
-
315
- return null;
316
- }
317
-
318
270
  /*
319
271
  * INTERNAL FUNCTION: recursively inspect body data if heirarchical
320
272
  */
@@ -347,20 +299,20 @@ function checkBodyData(uriPath, method, reqBdObj, mockresponses, respDatatype) {
347
299
  for (let a = 0; a < bVal.length; a += 1) {
348
300
  // should match fieldName-fieldValue
349
301
  const compStr = `${reqBKeys[k]}-${bVal[a]}`;
350
- specificResp = matchMock(uriPath, method, compStr, mockresponses, respDatatype);
302
+ specificResp = transUtilInst.matchResponse(uriPath, method, compStr, mockresponses, respDatatype);
351
303
 
352
304
  // if the data match is found break the for loop - will return below
353
- if (specificResp !== null) {
305
+ if (specificResp !== null && specificResp.response) {
354
306
  break;
355
307
  }
356
308
  }
357
309
  } else {
358
310
  // should match fieldName-fieldValue
359
311
  const compStr = `${reqBKeys[k]}-${bVal}`;
360
- specificResp = matchMock(uriPath, method, compStr, mockresponses, respDatatype);
312
+ specificResp = transUtilInst.matchResponse(uriPath, method, compStr, mockresponses, respDatatype);
361
313
  }
362
314
 
363
- if (specificResp !== null) {
315
+ if (specificResp !== null && specificResp.response) {
364
316
  break;
365
317
  }
366
318
  }
@@ -441,56 +393,9 @@ function returnStub(request, entitySchema, callProperties) {
441
393
  }
442
394
 
443
395
  // if there are path variables, see if there is something that matches a specific variable
444
- if (uriPath.indexOf('{pathv') >= 0) {
445
- const uriTemp = uriPath.split('?');
446
- const actTemp = reqPath.split('?');
447
- uriTemp[0] = uriTemp[0].replace(/{pathv/g, '/{pathv');
448
- uriTemp[0] = uriTemp[0].replace(/{version/g, '/{version');
449
- uriTemp[0] = uriTemp[0].replace(/{base/g, '/{base');
450
- uriTemp[0] = uriTemp[0].replace(/\/\//g, '/');
451
-
452
- // remove basepath from both paths
453
- // get rid of base path from the uriPath
454
- uriTemp[0] = uriTemp[0].replace(/\/{base_path}/g, '');
455
- // if a base path was added to the request, remove it
456
- if (callProperties && callProperties.base_path && callProperties.base_path !== '/') {
457
- actTemp[0] = actTemp[0].replace(callProperties.base_path, '');
458
- } else if (basepath && basepath !== '/') {
459
- actTemp[0] = actTemp[0].replace(basepath, '');
460
- }
461
-
462
- // remove version from both paths
463
- // get rid of version from the uriPath
464
- uriTemp[0] = uriTemp[0].replace(/\/{version}/g, '');
465
- // if a version was added to the request, remove it
466
- if (callProperties && callProperties.version) {
467
- actTemp[0] = actTemp[0].replace(`/${callProperties.version}`, '');
468
- } else if (version && version !== '/') {
469
- actTemp[0] = actTemp[0].replace(`/${version}`, '');
470
- }
471
-
472
- const uriArray = uriTemp[0].split('/');
473
- const actArray = actTemp[0].split('/');
474
-
475
- // if this is one of the generic requests need to pad the actual array or mock data for specific path variable will not work
476
- if (entitySchema.entitypath.indexOf('/{pathv1}/{pathv2}/{pathv3}/{pathv4}/{pathv5}/{pathv6}/{pathv7}/{pathv8}/{pathv9}/{pathv10}/{pathv11}/{pathv12}/{pathv13}/{pathv14}/{pathv15}/{pathv16}/{pathv17}/{pathv18}/{pathv19}/{pathv20}?{query}') >= 0) {
477
- for (let e = actArray.length; e < uriArray.length; e += 1) {
478
- actArray.push('');
479
- }
480
- }
481
-
482
- // the number of items in both should be the same
483
- if (uriArray.length === actArray.length) {
484
- for (let i = 0; i < uriArray.length; i += 1) {
485
- if (uriArray[i].indexOf('{pathv') >= 0) {
486
- specificResp = matchMock(uriPath, method, actArray[i], mockresponses, entitySchema.responseDatatype);
487
-
488
- if (specificResp !== null) {
489
- return specificResp;
490
- }
491
- }
492
- }
493
- }
396
+ specificResp = transUtilInst.getRespObjKeyFromPath(uriPath, reqPath, callProperties, basepath, version, method, false, entitySchema);
397
+ if (specificResp !== null && specificResp.response) {
398
+ return specificResp;
494
399
  }
495
400
 
496
401
  // if there are queiries or options, see if there is something that matches a specific input
@@ -504,9 +409,9 @@ function returnStub(request, entitySchema, callProperties) {
504
409
  if (qval !== undefined && qval !== null && qval !== '') {
505
410
  // stringifies it - in case it was not a string
506
411
  qval = `${qval}`;
507
- specificResp = matchMock(uriPath, method, qval, mockresponses, entitySchema.responseDatatype);
412
+ specificResp = transUtilInst.matchResponse(uriPath, method, qval, mockresponses, entitySchema.responseDatatype);
508
413
 
509
- if (specificResp !== null) {
414
+ if (specificResp !== null && specificResp.response) {
510
415
  return specificResp;
511
416
  }
512
417
  }
@@ -515,79 +420,36 @@ function returnStub(request, entitySchema, callProperties) {
515
420
 
516
421
  // if there is a request body, see if there is a specific response for body
517
422
  if (reqBody) {
518
- specificResp = matchMock(uriPath, method, 'WITHBODY', mockresponses, entitySchema.responseDatatype);
519
-
520
- if (specificResp !== null) {
423
+ specificResp = transUtilInst.matchResponse(uriPath, method, 'WITHBODY', mockresponses, entitySchema.responseDatatype);
424
+ if (specificResp !== null && specificResp.response) {
521
425
  return specificResp;
522
426
  }
523
427
  }
524
428
 
525
- // if there are path variables, see if there is a specific response for path vars
526
- if (uriPath.indexOf('{pathv') >= 0) {
527
- const uriTemp = uriPath.split('?');
528
- const actTemp = reqPath.split('?');
529
- uriTemp[0] = uriTemp[0].replace(/{pathv/g, '/{pathv');
530
- uriTemp[0] = uriTemp[0].replace(/{version/g, '/{version');
531
- uriTemp[0] = uriTemp[0].replace(/{base_path}/g, '/{base_path}');
532
- uriTemp[0] = uriTemp[0].replace(/\/\//g, '/');
533
-
534
- // remove basepath from both paths
535
- // get rid of base path from the uriPath
536
- uriTemp[0] = uriTemp[0].replace(/\/{base_path}/g, '');
537
- // if a base path was added to the request, remove it
538
- if (callProperties && callProperties.base_path && callProperties.base_path !== '/') {
539
- actTemp[0] = actTemp[0].replace(callProperties.base_path, '');
540
- } else if (basepath && basepath !== '/') {
541
- actTemp[0] = actTemp[0].replace(basepath, '');
542
- }
543
-
544
- // remove version from both paths
545
- // get rid of version from the uriPath
546
- uriTemp[0] = uriTemp[0].replace(/\/{version}/g, '');
547
- // if a version was added to the request, remove it
548
- if (callProperties && callProperties.version) {
549
- actTemp[0] = actTemp[0].replace(`/${callProperties.version}`, '');
550
- } else if (version && version !== '/') {
551
- actTemp[0] = actTemp[0].replace(`/${version}`, '');
552
- }
553
-
554
- const uriArray = uriTemp[0].split('/');
555
- const actArray = actTemp[0].split('/');
556
-
557
- // the number of items in both should be the same
558
- if (uriArray.length === actArray.length) {
559
- let cnt = 1;
560
- for (let i = 0; i < uriArray.length; i += 1) {
561
- if (uriArray[i].indexOf('{pathv') >= 0) {
562
- specificResp = matchMock(uriPath, method, `WITHPATHV${cnt}`, mockresponses, entitySchema.responseDatatype);
563
-
564
- if (specificResp !== null) {
565
- return specificResp;
566
- }
567
- cnt += 1;
568
- }
569
- }
570
- }
429
+ // if there are path variables, see if there is something that matches a specific variable
430
+ specificResp = transUtilInst.getRespObjKeyFromPath(uriPath, reqPath, callProperties, basepath, version, method, true, entitySchema);
431
+ if (specificResp !== null && specificResp.response) {
432
+ return specificResp;
571
433
  }
572
434
 
573
435
  // if there are queiries or options, see if there is a specific response for query or options
574
436
  if (uriPath.indexOf('?') >= 0) {
575
- specificResp = matchMock(uriPath, method, 'WITHQUERY', mockresponses, entitySchema.responseDatatype);
437
+ specificResp = transUtilInst.matchResponse(uriPath, method, 'WITHQUERY', mockresponses, entitySchema.responseDatatype);
576
438
 
577
- if (specificResp !== null) {
439
+ if (specificResp !== null && specificResp.response) {
578
440
  return specificResp;
579
441
  }
580
442
 
581
- specificResp = matchMock(uriPath, method, 'WITHOPTIONS', mockresponses, entitySchema.responseDatatype);
443
+ specificResp = transUtilInst.matchResponse(uriPath, method, 'WITHOPTIONS', mockresponses, entitySchema.responseDatatype);
582
444
 
583
- if (specificResp !== null) {
445
+ if (specificResp !== null && specificResp.response) {
584
446
  return specificResp;
585
447
  }
586
448
  }
587
449
 
588
- specificResp = matchMock(uriPath, method, 'DEFAULT', mockresponses, entitySchema.responseDatatype);
450
+ specificResp = transUtilInst.matchResponse(uriPath, method, 'DEFAULT', mockresponses, entitySchema.responseDatatype);
589
451
 
590
- if (specificResp !== null) {
452
+ if (specificResp !== null && specificResp.response) {
591
453
  return specificResp;
592
454
  }
593
455
 
@@ -3244,7 +3106,7 @@ function requestAuthenticate(request, entitySchema, invalidToken, callProperties
3244
3106
  }
3245
3107
 
3246
3108
  // format the authentication string
3247
- log.debug(`${origin}: ${JSON.stringify(propUtilInst.scrubSensitiveInfo(tres, addSensitiveItems))} being used for user: ${useUser}`);
3109
+ log.debug(`${origin}: ${JSON.stringify(propUtilInst.scrubSensitiveInfo(tres, addSensitiveItems))} being used`);
3248
3110
  const authStrs = [];
3249
3111
  if (callProperties && callProperties.authentication && callProperties.authentication.auth_field_format) {
3250
3112
  if (Array.isArray(callProperties.authentication.auth_field_format)) {
@@ -3306,7 +3168,7 @@ function requestAuthenticate(request, entitySchema, invalidToken, callProperties
3306
3168
  return callback(null, errorObj);
3307
3169
  }
3308
3170
 
3309
- log.debug(`${origin}: ${JSON.stringify(propUtilInst.scrubSensitiveInfo(tokenObj, addSensitiveItems))} being used for user: ${useUser}`);
3171
+ log.debug(`${origin}: ${JSON.stringify(propUtilInst.scrubSensitiveInfo(tokenObj, addSensitiveItems))} being used`);
3310
3172
  const authStrs = [];
3311
3173
  if (callProperties && callProperties.authentication && callProperties.authentication.auth_field_format) {
3312
3174
  if (Array.isArray(callProperties.authentication.auth_field_format)) {
@@ -4579,7 +4441,7 @@ class ConnectorRest {
4579
4441
  return waitForMongo()
4580
4442
  .then(() => {
4581
4443
  if (archiving) {
4582
- const colRes = this.dbUtil.createCollection(archiveColl, (err, res) => {
4444
+ const colRes = this.dbUtil.createCollection(archiveColl, null, null, (err, res) => {
4583
4445
  if (err) {
4584
4446
  log.error(`${origin}: collection ${archiveColl} could not be created.`);
4585
4447
  return callback(false);
@@ -5113,7 +4975,7 @@ class ConnectorRest {
5113
4975
  try {
5114
4976
  if (!throttleEnabled) {
5115
4977
  log.error(`${origin}: Throttling not enabled, no queue`);
5116
- return [];
4978
+ return callback([]);
5117
4979
  }
5118
4980
 
5119
4981
  return throttleEng.getQueue(callback);
@@ -0,0 +1,14 @@
1
+ /* @copyright Itential, LLC 2025 */
2
+
3
+ module.exports = {
4
+ // Global Strings
5
+ globalStrings: {
6
+ pathVarMarker: '{pathv', // path variable format is {pathv#} - number is dynamic can not match
7
+ versionMarker: '{version}',
8
+ basePathMarker: '{base_path}',
9
+ withPathVarPrefix: 'WITHPATHV',
10
+ urlSplit: '?',
11
+ pathSplit: '/',
12
+ globalFlag: 'g'
13
+ }
14
+ };
@@ -550,6 +550,7 @@ class AdapterPropertyUtil {
550
550
  name: entitySchema.responseObjects[i].name,
551
551
  method: entitySchema.responseObjects[i].method,
552
552
  type: entitySchema.responseObjects[i].type,
553
+ key: entitySchema.responseObjects[i].key || '',
553
554
  file: entitySchema.responseObjects[i].mockFile
554
555
  };
555
556
 
@@ -969,6 +970,7 @@ class AdapterPropertyUtil {
969
970
  name: entitySchema.responseObjects[i].name,
970
971
  method: entitySchema.responseObjects[i].method,
971
972
  type: entitySchema.responseObjects[i].type,
973
+ key: entitySchema.responseObjects[i].key || '',
972
974
  file: entitySchema.responseObjects[i].mockFile
973
975
  };
974
976
 
@@ -1267,14 +1269,20 @@ class AdapterPropertyUtil {
1267
1269
  retData[key] = this.scrubSensitiveInfo(retData[key], addItems);
1268
1270
  }
1269
1271
  } else {
1270
- // go through sensitive word list - maybe can use find in
1272
+ let gotit = false;
1273
+ // go through sensitive word list to mask the entire string
1271
1274
  for (let j = 0; j < sensList.length; j += 1) {
1272
1275
  if (key.toLowerCase() === sensList[j]) {
1273
1276
  // if sensitive, mask
1274
1277
  retData[key] = '** masked **';
1278
+ gotit = true;
1275
1279
  break;
1276
1280
  }
1277
1281
  }
1282
+ // if not masking the string as a whole - may need to parse part of it
1283
+ if (!gotit) {
1284
+ retData[key] = this.scrubSensitiveInfo(retData[key], addItems);
1285
+ }
1278
1286
  }
1279
1287
  });
1280
1288
 
@@ -28,31 +28,6 @@ let stripEscapes = false;
28
28
  let returnResponseHeaders = true;
29
29
  let healthcheckHeaders = null;
30
30
  let xmlArrayKeys = null;
31
- // INTERNAL FUNCTIONS
32
- /*
33
- * INTERNAL FUNCTION: Get the best match for the mock data response
34
- */
35
- function matchResponse(uriPath, method, type, mockresponses) {
36
- // Go through the mock data keys to find the proper data to return
37
- for (let p = 0; p < mockresponses.length; p += 1) {
38
- // is this the mock data for this call
39
- if (Object.hasOwnProperty.call(mockresponses[p], 'name')
40
- && uriPath === mockresponses[p].name) {
41
- if (Object.hasOwnProperty.call(mockresponses[p], 'method')
42
- && method.toUpperCase() === mockresponses[p].method.toUpperCase()) {
43
- if (Object.hasOwnProperty.call(mockresponses[p], 'type')
44
- && type.toUpperCase() === mockresponses[p].type.toUpperCase()) {
45
- // This is the Key we really want as it best matches the request
46
- if (Object.hasOwnProperty.call(mockresponses[p], 'key')) {
47
- return mockresponses[p].key;
48
- }
49
- }
50
- }
51
- }
52
- }
53
-
54
- return null;
55
- }
56
31
 
57
32
  /*
58
33
  * INTERNAL FUNCTION: recursively inspect body data if heirarchical
@@ -84,9 +59,12 @@ function checkBodyData(uriPath, method, reqBdObj, mockresponses) {
84
59
  } else if (Array.isArray(bVal)) {
85
60
  // if an array of data, need to check each data in the array
86
61
  for (let a = 0; a < bVal.length; a += 1) {
87
- // should match fieldName-fieldValue
62
+ // should match fieldName-fieldValue - NOTE: if we get the responseDatatype that should be passed in
88
63
  const compStr = `${reqBKeys[k]}-${bVal[a]}`;
89
- specificResp = matchResponse(uriPath, method, compStr, mockresponses);
64
+ const response = transUtilInst.matchResponse(uriPath, method, compStr, mockresponses, null);
65
+ if (response) {
66
+ specificResp = response.key;
67
+ }
90
68
 
91
69
  // if the data match is found break the for loop - will return below
92
70
  if (specificResp !== null) {
@@ -94,9 +72,12 @@ function checkBodyData(uriPath, method, reqBdObj, mockresponses) {
94
72
  }
95
73
  }
96
74
  } else {
97
- // should match fieldName-fieldValue
75
+ // should match fieldName-fieldValue - NOTE: if we get the responseDatatype that should be passed in
98
76
  const compStr = `${reqBKeys[k]}-${bVal}`;
99
- specificResp = matchResponse(uriPath, method, compStr, mockresponses);
77
+ const response = transUtilInst.matchResponse(uriPath, method, compStr, mockresponses, null);
78
+ if (response) {
79
+ specificResp = response.key;
80
+ }
100
81
  }
101
82
 
102
83
  if (specificResp !== null) {
@@ -271,48 +252,10 @@ function handleRestRequest(request, entityId, entitySchema, callProperties, filt
271
252
  }
272
253
 
273
254
  // if there are path variables, see if there is something that matches a specific variable
274
- if (respObjKey === null && uriPath.indexOf('{pathv') >= 0) {
275
- const uriTemp = uriPath.split('?');
276
- const actTemp = reqPath.split('?');
277
- uriTemp[0] = uriTemp[0].replace(/{pathv/g, '/{pathv');
278
- uriTemp[0] = uriTemp[0].replace(/{version/g, '/{version');
279
- uriTemp[0] = uriTemp[0].replace(/{base/g, '/{base');
280
- uriTemp[0] = uriTemp[0].replace(/\/\//g, '/');
281
-
282
- // remove basepath from both paths
283
- // get rid of base path from the uriPath
284
- uriTemp[0] = uriTemp[0].replace(/\/{base_path}/g, '');
285
- // if a base path was added to the request, remove it
286
- if (callProperties && callProperties.base_path && callProperties.base_path !== '/') {
287
- actTemp[0] = actTemp[0].replace(callProperties.base_path, '');
288
- } else if (basepathGl && basepathGl !== '/') {
289
- actTemp[0] = actTemp[0].replace(basepathGl, '');
290
- }
291
-
292
- // remove version from both paths
293
- // get rid of version from the uriPath
294
- uriTemp[0] = uriTemp[0].replace(/\/{version}/g, '');
295
- // if a version was added to the request, remove it
296
- if (callProperties && callProperties.version) {
297
- actTemp[0] = actTemp[0].replace(`/${callProperties.version}`, '');
298
- } else if (versionGl && versionGl !== '/') {
299
- actTemp[0] = actTemp[0].replace(`/${versionGl}`, '');
300
- }
301
-
302
- const uriArray = uriTemp[0].split('/');
303
- const actArray = actTemp[0].split('/');
304
-
305
- // the number of items in both should be the same
306
- if (uriArray.length === actArray.length) {
307
- for (let i = 0; i < uriArray.length; i += 1) {
308
- if (uriArray[i].indexOf('{pathv') >= 0) {
309
- respObjKey = matchResponse(uriPath, method, actArray[i], responseKeys);
310
-
311
- if (respObjKey !== null) {
312
- break;
313
- }
314
- }
315
- }
255
+ if (respObjKey === null) {
256
+ const specificResp = transUtilInst.getRespObjKeyFromPath(uriPath, reqPath, callProperties, basepathGl, versionGl, method, false, entitySchema);
257
+ if (specificResp) {
258
+ respObjKey = specificResp.key;
316
259
  }
317
260
  }
318
261
 
@@ -326,7 +269,10 @@ function handleRestRequest(request, entityId, entitySchema, callProperties, filt
326
269
  if (qval !== undefined && qval !== null && qval !== '') {
327
270
  // stringifies it - in case it was not a string
328
271
  qval = `${qval}`;
329
- respObjKey = matchResponse(uriPath, method, qval, responseKeys);
272
+ const specificResp = transUtilInst.matchResponse(uriPath, method, qval, responseKeys, entitySchema.responseDatatype);
273
+ if (specificResp) {
274
+ respObjKey = specificResp.key;
275
+ }
330
276
 
331
277
  if (respObjKey !== null) {
332
278
  break;
@@ -337,68 +283,40 @@ function handleRestRequest(request, entityId, entitySchema, callProperties, filt
337
283
 
338
284
  // if there is a request body, see if there is a specific response for body
339
285
  if (respObjKey === null && reqBody) {
340
- respObjKey = matchResponse(uriPath, method, 'WITHBODY', responseKeys);
286
+ const specificResp = transUtilInst.matchResponse(uriPath, method, 'WITHBODY', responseKeys, entitySchema.responseDatatype);
287
+ if (specificResp) {
288
+ respObjKey = specificResp.key;
289
+ }
341
290
  }
342
291
 
343
292
  // if there are path variables, see if there is a specific response for path vars
344
- if (respObjKey === null && uriPath.indexOf('{pathv') >= 0) {
345
- const uriTemp = uriPath.split('?');
346
- const actTemp = reqPath.split('?');
347
- uriTemp[0] = uriTemp[0].replace(/{pathv/g, '/{pathv');
348
- uriTemp[0] = uriTemp[0].replace(/{version/g, '/{version');
349
- uriTemp[0] = uriTemp[0].replace(/{base/g, '/{base');
350
- uriTemp[0] = uriTemp[0].replace(/\/\//g, '/');
351
-
352
- // remove basepath from both paths
353
- // get rid of base path from the uriPath
354
- uriTemp[0] = uriTemp[0].replace(/\/{base_path}/g, '');
355
- // if a base path was added to the request, remove it
356
- if (callProperties && callProperties.base_path && callProperties.base_path !== '/') {
357
- actTemp[0] = actTemp[0].replace(callProperties.base_path, '');
358
- } else if (basepathGl && basepathGl !== '/') {
359
- actTemp[0] = actTemp[0].replace(basepathGl, '');
360
- }
361
-
362
- // remove version from both paths
363
- // get rid of version from the uriPath
364
- uriTemp[0] = uriTemp[0].replace(/\/{version}/g, '');
365
- // if a version was added to the request, remove it
366
- if (callProperties && callProperties.version) {
367
- actTemp[0] = actTemp[0].replace(`/${callProperties.version}`, '');
368
- } else if (versionGl && versionGl !== '/') {
369
- actTemp[0] = actTemp[0].replace(`/${versionGl}`, '');
370
- }
371
-
372
- const uriArray = uriTemp[0].split('/');
373
- const actArray = actTemp[0].split('/');
374
-
375
- // the number of items in both should be the same
376
- if (uriArray.length === actArray.length) {
377
- let cnt = 1;
378
- for (let i = 0; i < uriArray.length; i += 1) {
379
- if (uriArray[i].indexOf('{pathv') >= 0) {
380
- respObjKey = matchResponse(uriPath, method, `WITHPATHV${cnt}`, responseKeys);
381
-
382
- if (respObjKey !== null) {
383
- break;
384
- }
385
- cnt += 1;
386
- }
387
- }
293
+ if (respObjKey === null) {
294
+ const specificResp = transUtilInst.getRespObjKeyFromPath(uriPath, reqPath, callProperties, basepathGl, versionGl, method, true, entitySchema);
295
+ if (specificResp) {
296
+ respObjKey = specificResp.key;
388
297
  }
389
298
  }
390
299
 
391
300
  // if there are queiries or options, see if there is a specific response for query or options
392
301
  if (respObjKey === null && uriPath.indexOf('?') >= 0) {
393
- respObjKey = matchResponse(uriPath, method, 'WITHQUERY', responseKeys);
302
+ let specificResp = transUtilInst.matchResponse(uriPath, method, 'WITHQUERY', responseKeys, entitySchema.responseDatatype);
303
+ if (specificResp) {
304
+ respObjKey = specificResp.key;
305
+ }
394
306
 
395
307
  if (respObjKey === null) {
396
- respObjKey = matchResponse(uriPath, method, 'WITHOPTIONS', responseKeys);
308
+ specificResp = transUtilInst.matchResponse(uriPath, method, 'WITHOPTIONS', responseKeys, entitySchema.responseDatatype);
309
+ if (specificResp) {
310
+ respObjKey = specificResp.key;
311
+ }
397
312
  }
398
313
  }
399
314
 
400
315
  if (respObjKey === null) {
401
- respObjKey = matchResponse(uriPath, method, 'DEFAULT', responseKeys);
316
+ const specificResp = transUtilInst.matchResponse(uriPath, method, 'DEFAULT', responseKeys, entitySchema.responseDatatype);
317
+ if (specificResp) {
318
+ respObjKey = specificResp.key;
319
+ }
402
320
  }
403
321
 
404
322
  if (respObjKey === null) {
@@ -524,6 +442,7 @@ function handleRestRequest(request, entityId, entitySchema, callProperties, filt
524
442
  return callback(retObject);
525
443
  });
526
444
  }
445
+
527
446
  // process the response - parse it
528
447
  try {
529
448
  retResponse = JSON.parse(resObj.response.trim());
package/lib/throttle.js CHANGED
@@ -442,7 +442,12 @@ function gettingCloseInterval(myRequest, transNum, callback) {
442
442
 
443
443
  try {
444
444
  let intRun = false;
445
- const fastInt = (avgTotal / avgSize) * 0.5;
445
+ let fastInt = (avgTotal / avgSize) * 0.5;
446
+
447
+ // prevent timeout overflow errors - 15 min max
448
+ if (fastInt > 900000) {
449
+ fastInt = 900000;
450
+ }
446
451
 
447
452
  // rapid inner interval - should be done when it is almost my time to run.
448
453
  const intervalObject = setInterval(() => {
@@ -1128,6 +1133,11 @@ class SystemXThrottle {
1128
1133
  outerInterval *= 0.95;
1129
1134
  }
1130
1135
 
1136
+ // prevent timeout overflow errors - 2 hours max
1137
+ if (outerInterval > 7200000) {
1138
+ outerInterval = 7200000;
1139
+ }
1140
+
1131
1141
  log.debug(`${origin}: Request ${queueItem.request_id} Transaction ${queueItem.transNum} Outer Interval set to: ${outerInterval}`);
1132
1142
 
1133
1143
  // outer interval to get a turn request
@@ -7,6 +7,7 @@
7
7
  /* eslint no-use-before-define: warn */
8
8
  /* eslint prefer-object-spread:warn */
9
9
  /* eslint prefer-destructuring:warn */
10
+ /* eslint no-continue:warn */
10
11
 
11
12
  /* NodeJS internal utilities */
12
13
  const fs = require('fs');
@@ -17,6 +18,16 @@ const AjvCl = require('ajv');
17
18
  const jsonQuery = require('json-query');
18
19
  const cryptoJS = require('crypto-js');
19
20
 
21
+ // get global strings
22
+ const { globalStrings } = require(path.join(__dirname, 'constants.js'));
23
+ const { pathVarMarker } = globalStrings;
24
+ const { versionMarker } = globalStrings;
25
+ const { basePathMarker } = globalStrings;
26
+ const { withPathVarPrefix } = globalStrings;
27
+ const { urlSplit } = globalStrings;
28
+ const { pathSplit } = globalStrings;
29
+ const { globalFlag } = globalStrings;
30
+
20
31
  let id = null;
21
32
  let propUtilInst = null;
22
33
  let translator = null;
@@ -943,6 +954,172 @@ class AdapterTranslatorUtil {
943
954
  return combinedObj;
944
955
  }
945
956
 
957
+ /**
958
+ * @summary Gets the property from call properties or global
959
+ *
960
+ * @function getPathProperty
961
+ * @param {String} globalProperty - global property value
962
+ * @param {String} propertyName - property name to find it in call properties
963
+ *
964
+ */
965
+ getPathProperty(globalProperty, propertyName, callProperties) {
966
+ const origin = `${this.myid}-translatorUtil-getPathProperty`;
967
+ log.trace(origin);
968
+
969
+ let propertyValue = `${pathSplit}${globalProperty}`;
970
+ if (callProperties && callProperties[propertyName]) {
971
+ propertyValue = `${pathSplit}${callProperties[propertyName]}`;
972
+ }
973
+
974
+ // remove any double slash that we may have introduced - consistency
975
+ return propertyValue.replace(new RegExp(`${pathSplit}${pathSplit}`, globalFlag), pathSplit);
976
+ }
977
+
978
+ /**
979
+ * @summary Matches the response to the response object to get the key
980
+ *
981
+ * @function matchResponse
982
+ * @param {String} uriPath - original path from the entitypath
983
+ * @param {String} method - method for the request
984
+ * @param {String} type - type for the mock response
985
+ * @param {Object} mockresponses - mock response objects
986
+ *
987
+ */
988
+ matchResponse(uriPath, method, type, mockresponses, respDatatype) {
989
+ const origin = `${this.myid}-translatorUtil-matchResponse`;
990
+ log.trace(origin);
991
+
992
+ // Go through the mock data keys to find the proper data to return
993
+ for (let p = 0; p < mockresponses.length; p += 1) {
994
+ // is this the mock data for this call
995
+ if (Object.hasOwnProperty.call(mockresponses[p], 'name') && uriPath === mockresponses[p].name
996
+ && Object.hasOwnProperty.call(mockresponses[p], 'method') && method.toUpperCase() === mockresponses[p].method.toUpperCase()
997
+ && Object.hasOwnProperty.call(mockresponses[p], 'type') && type.toUpperCase() === mockresponses[p].type.toUpperCase()) {
998
+ // This response best matches the request so return the key and data
999
+ const specificResp = {
1000
+ key: '',
1001
+ status: 'success',
1002
+ code: 200,
1003
+ response: {}
1004
+ };
1005
+
1006
+ if (Object.hasOwnProperty.call(mockresponses[p], 'key')) {
1007
+ specificResp.key = mockresponses[p].key;
1008
+ }
1009
+
1010
+ if (Object.hasOwnProperty.call(mockresponses[p], 'response')) {
1011
+ // if a status is defined in the response, use it
1012
+ if (Object.hasOwnProperty.call(mockresponses[p].response, 'response')
1013
+ && Object.hasOwnProperty.call(mockresponses[p].response, 'status')) {
1014
+ specificResp.code = mockresponses[p].response.status;
1015
+
1016
+ if (respDatatype && respDatatype.toUpperCase() === 'XML2JSON') {
1017
+ specificResp.response = mockresponses[p].response.response;
1018
+ } else {
1019
+ specificResp.response = JSON.stringify(mockresponses[p].response.response);
1020
+ }
1021
+ } else if (respDatatype && respDatatype.toUpperCase() === 'XML2JSON') {
1022
+ // if no response field, assume that the entire data is the response
1023
+ specificResp.response = mockresponses[p].response;
1024
+ } else {
1025
+ specificResp.response = JSON.stringify(mockresponses[p].response);
1026
+ }
1027
+ }
1028
+
1029
+ return specificResp;
1030
+ }
1031
+ }
1032
+
1033
+ return null;
1034
+ }
1035
+
1036
+ /**
1037
+ * @summary Gets the response object key from the path for determining how to match response
1038
+ * This might be used by token calls in the connector so it might be good to move out of here!
1039
+ *
1040
+ * @function getRespObjKeyFromPath
1041
+ * @param {String} uriPath - original path from the entitypath
1042
+ * @param {String} reqPath - path after translations - actual call path
1043
+ * @param {Object} callProperties - properties to override on this call
1044
+ * @param {String} basepathGl - base path global property
1045
+ * @param {String} versionGl - version global property
1046
+ * @param {String} method - method type for the request
1047
+ * @param {bollean} withPath - whether we are checking for with path vars
1048
+ * @param {Object} entitySchema - the entity schema for the request
1049
+ *
1050
+ */
1051
+ getRespObjKeyFromPath(uriPath, reqPath, callProperties, basepathGl, versionGl, method, withPath, entitySchema) {
1052
+ const origin = `${this.myid}-translatorUtil-getRespObjKeyFromPath`;
1053
+ log.trace(origin);
1054
+ let specificResp = null;
1055
+
1056
+ // if there are path variables, see if there is something that matches a specific variable
1057
+ if (uriPath.indexOf(pathVarMarker) >= 0) {
1058
+ const uriTemp = uriPath.split(urlSplit);
1059
+ const actTemp = reqPath.split(urlSplit);
1060
+
1061
+ // make sure the entitypath has a standard format since they can differ (e.g. slashes or no slashes)
1062
+ uriTemp[0] = uriTemp[0].replace(new RegExp(pathVarMarker, globalFlag), `${pathSplit}${pathVarMarker}`);
1063
+ uriTemp[0] = uriTemp[0].replace(new RegExp(versionMarker, globalFlag), `${pathSplit}${versionMarker}`);
1064
+ uriTemp[0] = uriTemp[0].replace(new RegExp(basePathMarker, globalFlag), `${pathSplit}${basePathMarker}`);
1065
+ uriTemp[0] = uriTemp[0].replace(new RegExp(`${pathSplit}${pathSplit}`, globalFlag), pathSplit);
1066
+
1067
+ // if the original path has {base_path}, remove base_path from both paths
1068
+ if (uriTemp[0].indexOf(basePathMarker) >= 0) {
1069
+ // get rid of base path marker from the original path
1070
+ uriTemp[0] = uriTemp[0].replace(new RegExp(`${pathSplit}${basePathMarker}`, globalFlag), '');
1071
+ // get rid of base path from the request path
1072
+ if (basepathGl && basepathGl !== '/') {
1073
+ actTemp[0] = actTemp[0].replace(this.getPathProperty(basepathGl, 'base_path', callProperties), '');
1074
+ }
1075
+ }
1076
+
1077
+ // if the original path has {version}, remove version from both paths
1078
+ if (uriTemp[0].indexOf(versionMarker) >= 0) {
1079
+ // get rid of version marker from the original path
1080
+ uriTemp[0] = uriTemp[0].replace(new RegExp(`${pathSplit}${versionMarker}`, globalFlag), '');
1081
+ // get rid of version from the request path
1082
+ if (versionGl && versionGl !== '/') {
1083
+ actTemp[0] = actTemp[0].replace(this.getPathProperty(versionGl, 'version', callProperties), '');
1084
+ }
1085
+ }
1086
+
1087
+ const uriArray = uriTemp[0].split(pathSplit);
1088
+ const actArray = actTemp[0].split(pathSplit);
1089
+
1090
+ // if this is one of the generic requests need to pad the actual array or mock data for specific path variable will not work
1091
+ if (entitySchema.entitypath.indexOf('/{pathv1}/{pathv2}/{pathv3}/{pathv4}/{pathv5}/{pathv6}/{pathv7}/{pathv8}/{pathv9}/{pathv10}/{pathv11}/{pathv12}/{pathv13}/{pathv14}/{pathv15}/{pathv16}/{pathv17}/{pathv18}/{pathv19}/{pathv20}?{query}') >= 0) {
1092
+ for (let e = actArray.length; e < uriArray.length; e += 1) {
1093
+ actArray.push('');
1094
+ }
1095
+ }
1096
+
1097
+ // the number of items in both should be the same
1098
+ if (uriArray.length === actArray.length) {
1099
+ let varCount = 1;
1100
+ // want to go through the path to find the path variables
1101
+ for (let i = 0; i < uriArray.length; i += 1) {
1102
+ // if this is a path variable in the original path
1103
+ if (uriArray[i].indexOf(pathVarMarker) >= 0) {
1104
+ // are we checking generic path vars (withPath) or specific path data
1105
+ if (withPath) {
1106
+ specificResp = this.matchResponse(uriPath, method, `${withPathVarPrefix}${varCount}`, entitySchema.mockresponses, entitySchema.responseDatatype);
1107
+ } else {
1108
+ specificResp = this.matchResponse(uriPath, method, actArray[i], entitySchema.mockresponses, entitySchema.responseDatatype);
1109
+ }
1110
+
1111
+ if (specificResp !== null) {
1112
+ break;
1113
+ }
1114
+ varCount += 1;
1115
+ }
1116
+ }
1117
+ }
1118
+ }
1119
+
1120
+ return specificResp;
1121
+ }
1122
+
946
1123
  /**
947
1124
  * @summary If the input is a stringified JSON object, return the JSON object. Otherwise,
948
1125
  * return the object that was provided.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itentialopensource/adapter-utils",
3
- "version": "5.10.16",
3
+ "version": "5.10.18",
4
4
  "description": "Itential Adapter Utility Libraries",
5
5
  "scripts": {
6
6
  "postinstall": "node utils/setup.js",