@itentialopensource/adapter-utils 4.47.0 → 4.48.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,4 +1,24 @@
1
1
 
2
+ ## 4.48.1 [09-22-2022]
3
+
4
+ * Add capability to send base64 and buffer in formData
5
+
6
+ Closes ADAPT-2380
7
+
8
+ See merge request itentialopensource/adapter-utils!238
9
+
10
+ ---
11
+
12
+ ## 4.48.0 [08-16-2022]
13
+
14
+ * Changes to support entitypath object with multiple paths
15
+
16
+ Closes ADAPT-2331
17
+
18
+ See merge request itentialopensource/adapter-utils!236
19
+
20
+ ---
21
+
2
22
  ## 4.47.0 [08-13-2022]
3
23
 
4
24
  * Add SSO capability into service instance config
@@ -45,6 +45,7 @@ let host = null;
45
45
  let port = null;
46
46
  let basepath = null;
47
47
  let version = null;
48
+ let choosepath = null;
48
49
  let authMethod = null;
49
50
  let authField = null;
50
51
  let authFormat = null;
@@ -254,11 +255,11 @@ function matchMock(uriPath, method, type, mockresponses, respDatatype) {
254
255
  for (let p = 0; p < mockresponses.length; p += 1) {
255
256
  // is this the mock data for this call
256
257
  if (Object.hasOwnProperty.call(mockresponses[p], 'name')
257
- && uriPath === mockresponses[p].name) {
258
+ && uriPath === mockresponses[p].name) {
258
259
  if (Object.hasOwnProperty.call(mockresponses[p], 'method')
259
- && method.toUpperCase() === mockresponses[p].method.toUpperCase()) {
260
+ && method.toUpperCase() === mockresponses[p].method.toUpperCase()) {
260
261
  if (Object.hasOwnProperty.call(mockresponses[p], 'type')
261
- && type.toUpperCase() === mockresponses[p].type.toUpperCase()) {
262
+ && type.toUpperCase() === mockresponses[p].type.toUpperCase()) {
262
263
  // This is the mock data we really want as it best matches the request
263
264
  const specificResp = {
264
265
  status: 'success',
@@ -269,7 +270,7 @@ function matchMock(uriPath, method, type, mockresponses, respDatatype) {
269
270
  if (Object.hasOwnProperty.call(mockresponses[p], 'response')) {
270
271
  // if a status is defined in the response, use it
271
272
  if (Object.hasOwnProperty.call(mockresponses[p].response, 'response')
272
- && Object.hasOwnProperty.call(mockresponses[p].response, 'status')) {
273
+ && Object.hasOwnProperty.call(mockresponses[p].response, 'status')) {
273
274
  specificResp.code = mockresponses[p].response.status;
274
275
 
275
276
  if (respDatatype && respDatatype.toUpperCase() === 'XML2JSON') {
@@ -395,7 +396,7 @@ function returnStub(request, entitySchema, callProperties) {
395
396
 
396
397
  // if there is a request body, see if there is something that matches a specific input
397
398
  if (reqBody && (!entitySchema || !entitySchema.requestDatatype
398
- || entitySchema.requestDatatype.toUpperCase() === 'JSON' || entitySchema.requestDatatype.toUpperCase() === 'URLENCODE')) {
399
+ || entitySchema.requestDatatype.toUpperCase() === 'JSON' || entitySchema.requestDatatype.toUpperCase() === 'URLENCODE')) {
399
400
  let reqBdObj = null;
400
401
  if (entitySchema && entitySchema.requestDatatype && entitySchema.requestDatatype.toUpperCase() === 'URLENCODE') {
401
402
  reqBdObj = querystring.parse(reqBody.trim());
@@ -660,38 +661,60 @@ function makeRequest(request, entitySchema, callProperties, startTrip, attempt,
660
661
  }
661
662
  // add the data for each field into the form
662
663
  const mykeys = Object.keys(mybody);
663
- for (let k = 0; k < mykeys.length; k += 1) {
664
- if (mykeys[k] === 'file') {
665
- let fileVal = mybody[mykeys[k]];
666
- if (fileVal.indexOf('@') === 0) {
667
- // if there are multiple parts - first part is file, other part can be name
668
- const filePart = fileVal.split(';');
669
- let fileName = null;
670
- fileVal = fs.readFileSync(`node_modules/@itentialopensource/adapter-forwardnetworks/uploads/${filePart[0].substring(1)}`);
671
-
672
- // see if we have a filename that we should add to the formdata
673
- for (let p = 1; p < filePart.length; p += 1) {
674
- if (filePart[p].indexOf('name=') === 0) {
675
- fileName = filePart[p].substring(5);
664
+ if (mykeys.length === 2 && mykeys[0] === 'file' && mykeys[1] === 'convertBase64ToBuffer') {
665
+ const filePart = mybody[mykeys[0]].split(';');
666
+ let fileName = null;
667
+ // see if we have a filename that we should add to the formdata
668
+ for (let p = 1; p < filePart.length; p += 1) {
669
+ if (filePart[p].indexOf('name=') === 0) {
670
+ fileName = filePart[p].substring(5);
671
+ }
672
+ }
673
+ if (mybody.convertBase64ToBuffer === true) {
674
+ let fileBuffer = filePart[filePart.length - 1];
675
+ if (filePart[filePart.length - 1].startsWith('base64')) {
676
+ fileBuffer = Buffer.from(filePart[filePart.length - 1].substring(7), 'base64');
677
+ }
678
+ log.debug(`APPENDING: ${mykeys[0]}, WITH VALUE ${fileBuffer}, AND NAME ${fileName}`);
679
+ formData.append(mykeys[0], fileBuffer, fileName);
680
+ } else {
681
+ log.debug(`APPENDING: ${mykeys[0]}, WITH VALUE ${filePart[filePart.length - 1]}, AND NAME ${fileName}`);
682
+ formData.append(mykeys[0], filePart[filePart.length - 1], fileName);
683
+ }
684
+ } else {
685
+ for (let k = 0; k < mykeys.length; k += 1) {
686
+ if (mykeys[k] === 'file') {
687
+ let fileVal = mybody[mykeys[k]];
688
+ if (fileVal.indexOf('@') === 0) {
689
+ // if there are multiple parts - first part is file, other part can be name
690
+ const filePart = fileVal.split(';');
691
+ let fileName = null;
692
+ fileVal = fs.readFileSync(`node_modules/@itentialopensource/adapter-forwardnetworks/uploads/${filePart[0].substring(1)}`);
693
+
694
+ // see if we have a filename that we should add to the formdata
695
+ for (let p = 1; p < filePart.length; p += 1) {
696
+ if (filePart[p].indexOf('name=') === 0) {
697
+ fileName = filePart[p].substring(5);
698
+ }
699
+ }
700
+ if (fileName) {
701
+ // with filename
702
+ log.debug(`APPENDING: ${mykeys[k]}, WITH VALUE ${fileVal}, AND NAME ${fileName}`);
703
+ formData.append(mykeys[k], fileVal, fileName);
704
+ } else {
705
+ // with read in file but no file name
706
+ log.debug(`APPENDING: ${mykeys[k]}, WITH VALUE ${fileVal}`);
707
+ formData.append(mykeys[k], fileVal);
676
708
  }
677
- }
678
- if (fileName) {
679
- // with filename
680
- log.debug(`APPENDING: ${mykeys[k]}, WITH VALUE ${fileVal}, AND NAME ${fileName}`);
681
- formData.append(mykeys[k], fileVal, fileName);
682
709
  } else {
683
- // with read in file but no file name
710
+ // no file or file name just contents - original
684
711
  log.debug(`APPENDING: ${mykeys[k]}, WITH VALUE ${fileVal}`);
685
712
  formData.append(mykeys[k], fileVal);
686
713
  }
687
714
  } else {
688
- // no file or file name just contents - original
689
- log.debug(`APPENDING: ${mykeys[k]}, WITH VALUE ${fileVal}`);
690
- formData.append(mykeys[k], fileVal);
715
+ log.debug(`APPENDING: ${mykeys[k]}, WITH VALUE ${mybody[mykeys[k]]}`);
716
+ formData.append(mykeys[k], mybody[mykeys[k]]);
691
717
  }
692
- } else {
693
- log.debug(`APPENDING: ${mykeys[k]}, WITH VALUE ${mybody[mykeys[k]]}`);
694
- formData.append(mykeys[k], mybody[mykeys[k]]);
695
718
  }
696
719
  }
697
720
  // get the new headers
@@ -887,7 +910,7 @@ function makeRequest(request, entitySchema, callProperties, startTrip, attempt,
887
910
 
888
911
  // write to the http request data to the body if not a get (gets do not have data in the body)
889
912
  if ((request.header.method !== 'GET' || entitySchema.sendGetBody)
890
- && ((typeof request.body === 'object' && Object.keys(request.body).length > 0)
913
+ && ((typeof request.body === 'object' && Object.keys(request.body).length > 0)
891
914
  || (typeof request.body === 'string' && request.body !== '{}') || entitySchema.sendEmpty)) {
892
915
  if (entitySchema.requestDatatype.toUpperCase() === 'FORM') {
893
916
  // pass the formData to the request
@@ -1204,7 +1227,7 @@ function getToken(reqPath, options, tokenSchema, bodyString, callProperties, cal
1204
1227
 
1205
1228
  // process primary token from header
1206
1229
  if (tokenSchema.responseSchema && tokenSchema.responseSchema.properties && tokenSchema.responseSchema.properties.token
1207
- && tokenSchema.responseSchema.properties.token.placement && tokenSchema.responseSchema.properties.token.placement.toUpperCase() === 'HEADER') {
1230
+ && tokenSchema.responseSchema.properties.token.placement && tokenSchema.responseSchema.properties.token.placement.toUpperCase() === 'HEADER') {
1208
1231
  if (!tokenSchema.responseSchema.properties.token.external_name) {
1209
1232
  const errorObj = transUtilInst.formatErrorObject(origin, 'Unable To Get Primary Token', ['Primary Token', result.code], null, null, null);
1210
1233
  log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
@@ -1503,7 +1526,7 @@ function buildTokenRequest(reqPath, reqBody, callProperties, callback) {
1503
1526
 
1504
1527
  try {
1505
1528
  // Get the entity schema from the file system
1506
- return propUtilInst.getEntitySchema('.system', 'getToken', this.dbUtil, (tokenSchema, healthError) => {
1529
+ return propUtilInst.getEntitySchema('.system', 'getToken', choosepath, this.dbUtil, (tokenSchema, healthError) => {
1507
1530
  if (healthError || !tokenSchema || Object.keys(tokenSchema).length === 0) {
1508
1531
  log.debug(`${origin}: Using adapter properties for token information`);
1509
1532
  tokenSchema = null;
@@ -1793,7 +1816,7 @@ function buildTokenRequest(reqPath, reqBody, callProperties, callback) {
1793
1816
 
1794
1817
  // only add global options if there are global options to add
1795
1818
  if (globalRequest && globalRequest.uriOptions
1796
- && Object.keys(globalRequest.uriOptions).length > 0) {
1819
+ && Object.keys(globalRequest.uriOptions).length > 0) {
1797
1820
  const optionString = querystring.stringify(globalRequest.uriOptions);
1798
1821
 
1799
1822
  // if no query paramters yet - start with ?
@@ -2105,7 +2128,7 @@ function validToken(user, reqBody, invalidToken, callback) {
2105
2128
  // if the token expired (or will expire within a minute),
2106
2129
  // or it is invalid (failed) remove it from the token list
2107
2130
  if (tokenList[i].expire < expireCheck
2108
- || tokenList[i].token.token === invalidToken) {
2131
+ || tokenList[i].token.token === invalidToken) {
2109
2132
  tokenList.splice(i, 1);
2110
2133
  break;
2111
2134
  }
@@ -2819,7 +2842,7 @@ function handleEndThrottleResponse(request, myTransTime, claimedLic, makeResp, r
2819
2842
 
2820
2843
  // If the request was successful
2821
2844
  if (makeResp !== null && makeResp.code !== undefined
2822
- && Number(makeResp.code) >= 200 && Number(makeResp.code) <= 299) {
2845
+ && Number(makeResp.code) >= 200 && Number(makeResp.code) <= 299) {
2823
2846
  const newResp = {
2824
2847
  icode: `AD.${makeResp.code}`,
2825
2848
  response: makeResp.response,
@@ -2918,7 +2941,7 @@ function retryInvalidResponse(request, callProperties, myTransTime, claimedLic,
2918
2941
  let retries = numRetries;
2919
2942
  if (callProperties && callProperties.request && callProperties.request.limit_retry_error) {
2920
2943
  if (typeof callProperties.request.limit_retry_error === 'number'
2921
- || typeof callProperties.request.limit_retry_error === 'string') {
2944
+ || typeof callProperties.request.limit_retry_error === 'string') {
2922
2945
  retryError = [Number(callProperties.request.limit_retry_error)];
2923
2946
  } else if (Array.isArray(callProperties.request.limit_retry_error)) {
2924
2947
  retryError = [];
@@ -2926,10 +2949,10 @@ function retryInvalidResponse(request, callProperties, myTransTime, claimedLic,
2926
2949
  if (typeof callProperties.request.limit_retry_error[l] === 'number') {
2927
2950
  retryError.push(Number(callProperties.request.limit_retry_error[l]));
2928
2951
  } else if (typeof callProperties.request.limit_retry_error[l] === 'string'
2929
- && callProperties.request.limit_retry_error[l].indexOf('-') < 0) {
2952
+ && callProperties.request.limit_retry_error[l].indexOf('-') < 0) {
2930
2953
  retryError.push(Number(callProperties.request.limit_retry_error[l]));
2931
2954
  } else if (typeof callProperties.request.limit_retry_error[l] === 'string'
2932
- && callProperties.request.limit_retry_error[l].indexOf('-') >= 0) {
2955
+ && callProperties.request.limit_retry_error[l].indexOf('-') >= 0) {
2933
2956
  const srange = Number(callProperties.request.limit_retry_error[l].split('-')[0]);
2934
2957
  const erange = Number(callProperties.request.limit_retry_error[l].split('-')[1]);
2935
2958
  for (let r = srange; r <= erange; r += 1) {
@@ -2946,7 +2969,7 @@ function retryInvalidResponse(request, callProperties, myTransTime, claimedLic,
2946
2969
  // if the response is valid - good data or legitimate data error
2947
2970
  // stop trying if we have tried enough
2948
2971
  if (numTries > retries || (mres !== null && mres.code !== undefined && !retryError.includes(Number(mres.code))
2949
- && (authMethod !== 'request_token' || Number(mres.code) !== Number(tokenError)))) {
2972
+ && (authMethod !== 'request_token' || Number(mres.code) !== Number(tokenError)))) {
2950
2973
  const newresp = mres;
2951
2974
  newresp.retries = numTries;
2952
2975
 
@@ -3082,7 +3105,7 @@ function noQueueRequest(request, callProperties, overallTime, entitySchema, call
3082
3105
  let retries = numRetries;
3083
3106
  if (callProperties && callProperties.request && callProperties.request.limit_retry_error) {
3084
3107
  if (typeof callProperties.request.limit_retry_error === 'number'
3085
- || typeof callProperties.request.limit_retry_error === 'string') {
3108
+ || typeof callProperties.request.limit_retry_error === 'string') {
3086
3109
  retryError = [Number(callProperties.request.limit_retry_error)];
3087
3110
  } else if (Array.isArray(callProperties.request.limit_retry_error)) {
3088
3111
  retryError = [];
@@ -3090,10 +3113,10 @@ function noQueueRequest(request, callProperties, overallTime, entitySchema, call
3090
3113
  if (typeof callProperties.request.limit_retry_error[l] === 'number') {
3091
3114
  retryError.push(Number(callProperties.request.limit_retry_error[l]));
3092
3115
  } else if (typeof callProperties.request.limit_retry_error[l] === 'string'
3093
- && callProperties.request.limit_retry_error[l].indexOf('-') < 0) {
3116
+ && callProperties.request.limit_retry_error[l].indexOf('-') < 0) {
3094
3117
  retryError.push(Number(callProperties.request.limit_retry_error[l]));
3095
3118
  } else if (typeof callProperties.request.limit_retry_error[l] === 'string'
3096
- && callProperties.request.limit_retry_error[l].indexOf('-') >= 0) {
3119
+ && callProperties.request.limit_retry_error[l].indexOf('-') >= 0) {
3097
3120
  const srange = Number(callProperties.request.limit_retry_error[l].split('-')[0]);
3098
3121
  const erange = Number(callProperties.request.limit_retry_error[l].split('-')[1]);
3099
3122
  for (let r = srange; r <= erange; r += 1) {
@@ -3109,14 +3132,14 @@ function noQueueRequest(request, callProperties, overallTime, entitySchema, call
3109
3132
 
3110
3133
  // if invalid token, handle that and retry
3111
3134
  if (mres !== null && mres.code !== undefined && Number(mres.code) === Number(tokenError)
3112
- && authMethod === 'request_token') {
3135
+ && authMethod === 'request_token') {
3113
3136
  // if we took an invalid token - try one more time
3114
3137
  return handleInvalidToken(request, callProperties, 0, { request_id: 0 }, mres, overallTime, overallTime, 0, 1, entitySchema, callback);
3115
3138
  }
3116
3139
 
3117
3140
  // if the response is valid - good data or legitimate data error
3118
3141
  if (retries < 1 || (mres !== null && mres.code !== undefined && !retryError.includes(Number(mres.code))
3119
- && (authMethod !== 'request_token' || Number(mres.code) !== Number(tokenError)))) {
3142
+ && (authMethod !== 'request_token' || Number(mres.code) !== Number(tokenError)))) {
3120
3143
  return handleEndResponse(request, mres, overallTime, callback);
3121
3144
  }
3122
3145
 
@@ -3181,7 +3204,7 @@ function queueThrottleRequest(request, callProperties, myRequestId, myTransTime,
3181
3204
  let retries = numRetries;
3182
3205
  if (callProperties && callProperties.request && callProperties.request.limit_retry_error) {
3183
3206
  if (typeof callProperties.request.limit_retry_error === 'number'
3184
- || typeof callProperties.request.limit_retry_error === 'string') {
3207
+ || typeof callProperties.request.limit_retry_error === 'string') {
3185
3208
  retryError = [Number(callProperties.request.limit_retry_error)];
3186
3209
  } else if (Array.isArray(callProperties.request.limit_retry_error)) {
3187
3210
  retryError = [];
@@ -3189,10 +3212,10 @@ function queueThrottleRequest(request, callProperties, myRequestId, myTransTime,
3189
3212
  if (typeof callProperties.request.limit_retry_error[l] === 'number') {
3190
3213
  retryError.push(Number(callProperties.request.limit_retry_error[l]));
3191
3214
  } else if (typeof callProperties.request.limit_retry_error[l] === 'string'
3192
- && callProperties.request.limit_retry_error[l].indexOf('-') < 0) {
3215
+ && callProperties.request.limit_retry_error[l].indexOf('-') < 0) {
3193
3216
  retryError.push(Number(callProperties.request.limit_retry_error[l]));
3194
3217
  } else if (typeof callProperties.request.limit_retry_error[l] === 'string'
3195
- && callProperties.request.limit_retry_error[l].indexOf('-') >= 0) {
3218
+ && callProperties.request.limit_retry_error[l].indexOf('-') >= 0) {
3196
3219
  const srange = Number(callProperties.request.limit_retry_error[l].split('-')[0]);
3197
3220
  const erange = Number(callProperties.request.limit_retry_error[l].split('-')[1]);
3198
3221
  for (let r = srange; r <= erange; r += 1) {
@@ -3208,14 +3231,14 @@ function queueThrottleRequest(request, callProperties, myRequestId, myTransTime,
3208
3231
 
3209
3232
  // if invalid token, handle that and retry
3210
3233
  if (mres !== null && mres.code !== undefined && Number(mres.code) === Number(tokenError)
3211
- && authMethod === 'request_token') {
3234
+ && authMethod === 'request_token') {
3212
3235
  // if we took an invalid token - try one more time
3213
3236
  return handleInvalidToken(request, callProperties, myTransTime, claimedLic, mres, reqTime, overallTime, waitEnd, 1, entitySchema, callback);
3214
3237
  }
3215
3238
 
3216
3239
  // if the response is valid - good data or legitimate data error
3217
3240
  if (retries < 1 || (mres !== null && mres.code !== undefined && !retryError.includes(Number(mres.code))
3218
- && (authMethod !== 'request_token' || Number(mres.code) !== Number(tokenError)))) {
3241
+ && (authMethod !== 'request_token' || Number(mres.code) !== Number(tokenError)))) {
3219
3242
  return handleEndThrottleResponse(request, myTransTime, claimedLic, mres, reqTime, overallTime, waitEnd, callback);
3220
3243
  }
3221
3244
 
@@ -3317,6 +3340,11 @@ class ConnectorRest {
3317
3340
  version = props.version;
3318
3341
  }
3319
3342
 
3343
+ // set the choosepath (optional - default is null)
3344
+ if (typeof props.choosepath === 'string') {
3345
+ choosepath = props.choosepath;
3346
+ }
3347
+
3320
3348
  if (props.authentication) {
3321
3349
  // set the authentication method (required - default is null)
3322
3350
  if (typeof props.authentication.auth_method === 'string') {
@@ -3360,13 +3388,13 @@ class ConnectorRest {
3360
3388
 
3361
3389
  // set the invalid token error (optional - default is null)
3362
3390
  if (typeof props.authentication.invalid_token_error === 'number'
3363
- || typeof props.authentication.invalid_token_error === 'string') {
3391
+ || typeof props.authentication.invalid_token_error === 'string') {
3364
3392
  tokenError = Number(props.authentication.invalid_token_error);
3365
3393
  }
3366
3394
 
3367
3395
  // set the token timeout (optional - default is null)
3368
3396
  if (typeof props.authentication.token_timeout === 'number'
3369
- || typeof props.authentication.token_timeout === 'string') {
3397
+ || typeof props.authentication.token_timeout === 'string') {
3370
3398
  tokenTimeout = Number(props.authentication.token_timeout);
3371
3399
  }
3372
3400
 
@@ -3447,19 +3475,19 @@ class ConnectorRest {
3447
3475
  if (props.request) {
3448
3476
  // set the number of redirects (optional - default is 0)
3449
3477
  if (typeof props.request.number_redirects === 'number'
3450
- || typeof props.request.number_redirects === 'string') {
3478
+ || typeof props.request.number_redirects === 'string') {
3451
3479
  numRedirects = Number(props.request.number_redirects);
3452
3480
  }
3453
3481
 
3454
3482
  // set the number of retries (optional - default is 3)
3455
3483
  if (typeof props.request.number_retries === 'number'
3456
- || typeof props.request.number_retries === 'string') {
3484
+ || typeof props.request.number_retries === 'string') {
3457
3485
  numRetries = Number(props.request.number_retries);
3458
3486
  }
3459
3487
 
3460
3488
  // set the request retry error (optional - default is 0)
3461
3489
  if (typeof props.request.limit_retry_error === 'number'
3462
- || typeof props.request.limit_retry_error === 'string') {
3490
+ || typeof props.request.limit_retry_error === 'string') {
3463
3491
  limitRetryError = [Number(props.request.limit_retry_error)];
3464
3492
  } else if (Array.isArray(props.request.limit_retry_error)) {
3465
3493
  limitRetryError = [];
@@ -3467,10 +3495,10 @@ class ConnectorRest {
3467
3495
  if (typeof props.request.limit_retry_error[l] === 'number') {
3468
3496
  limitRetryError.push(Number(props.request.limit_retry_error[l]));
3469
3497
  } else if (typeof props.request.limit_retry_error[l] === 'string'
3470
- && props.request.limit_retry_error[l].indexOf('-') < 0) {
3498
+ && props.request.limit_retry_error[l].indexOf('-') < 0) {
3471
3499
  limitRetryError.push(Number(props.request.limit_retry_error[l]));
3472
3500
  } else if (typeof props.request.limit_retry_error[l] === 'string'
3473
- && props.request.limit_retry_error[l].indexOf('-') >= 0) {
3501
+ && props.request.limit_retry_error[l].indexOf('-') >= 0) {
3474
3502
  const srange = Number(props.request.limit_retry_error[l].split('-')[0]);
3475
3503
  const erange = Number(props.request.limit_retry_error[l].split('-')[1]);
3476
3504
  for (let r = srange; r <= erange; r += 1) {
@@ -3482,7 +3510,7 @@ class ConnectorRest {
3482
3510
 
3483
3511
  // set the request attempt timeout (optional - default is 5000)
3484
3512
  if (typeof props.request.attempt_timeout === 'number'
3485
- || typeof props.request.attempt_timeout === 'string') {
3513
+ || typeof props.request.attempt_timeout === 'string') {
3486
3514
  attemptTimeout = Number(props.request.attempt_timeout);
3487
3515
  }
3488
3516
 
@@ -3904,7 +3932,7 @@ class ConnectorRest {
3904
3932
  }
3905
3933
 
3906
3934
  if (pres !== null && pres.code !== undefined
3907
- && (Number(pres.code) < 200 || Number(pres.code) > 299)) {
3935
+ && (Number(pres.code) < 200 || Number(pres.code) > 299)) {
3908
3936
  let errorObj = null;
3909
3937
 
3910
3938
  if (pres.code === -2) {
@@ -30,7 +30,7 @@ class AdapterPropertyUtil {
30
30
  *
31
31
  * @return {Object} entitySchema - the entity schema object
32
32
  */
33
- getEntitySchemaFromFS(entityName, actionName) {
33
+ getEntitySchemaFromFS(entityName, actionName, choosepath) {
34
34
  const origin = `${this.myid}-propertyUtil-getEntitySchemaFromFS`;
35
35
  log.trace(origin);
36
36
 
@@ -264,6 +264,32 @@ class AdapterPropertyUtil {
264
264
  entitySchema.responseObjects = [];
265
265
  entitySchema.mockresponses = [];
266
266
 
267
+ // if the entitypath is an object instead of a string need to figure out which path to use
268
+ if (actionInfo.entitypath && typeof actionInfo.entitypath === 'object') {
269
+ const ekeys = Object.keys(actionInfo.entitypath);
270
+ if (ekeys.length > 0) {
271
+ // the first one is the default so if we do not have a match that is the one that will be used
272
+ entitySchema.entitypath = actionInfo.entitypath[ekeys[0]];
273
+ for (let ep = 1; ep < ekeys.length; ep += 1) {
274
+ // see if the key matches the choosepath value, if it does set the entitypath
275
+ if (choosepath && ekeys[ep] === choosepath) {
276
+ entitySchema.entitypath = actionInfo.entitypath[ekeys[ep]];
277
+ break;
278
+ }
279
+ }
280
+ } else {
281
+ // add the specific pieces of the error object
282
+ errorObj.type = 'Invalid Action File';
283
+ errorObj.vars = ['missing entity path', actionFile];
284
+
285
+ // log (if not system entity) and throw the error
286
+ if (entityName !== '.system') {
287
+ log.error(`${origin}: Entity ${entityName} action ${actionName} - missing entity path`);
288
+ }
289
+ throw new Error(JSON.stringify(errorObj));
290
+ }
291
+ }
292
+
267
293
  // if info provided, replace the defaults
268
294
  if (actionInfo.querykey) {
269
295
  entitySchema.querykey = actionInfo.querykey;
@@ -399,7 +425,7 @@ class AdapterPropertyUtil {
399
425
  *
400
426
  * @return {Object} entitySchema - the entity schema object
401
427
  */
402
- getEntitySchemaFromDB(dbObj, entityName, actionName, dbUtils, callback) {
428
+ getEntitySchemaFromDB(dbObj, entityName, actionName, choosepath, dbUtils, callback) {
403
429
  const origin = `${this.myid}-propertyUtil-getEntitySchemaFromDB`;
404
430
  log.trace(origin);
405
431
 
@@ -672,6 +698,33 @@ class AdapterPropertyUtil {
672
698
  entitySchema.responseObjects = [];
673
699
  entitySchema.mockresponses = [];
674
700
 
701
+ // if the entitypath is an object instead of a string need to figure out which path to use
702
+ if (actionInfo.entitypath && typeof actionInfo.entitypath === 'object') {
703
+ const ekeys = Object.keys(actionInfo.entitypath);
704
+ if (ekeys.length > 0) {
705
+ // the first one is the default so if we do not have a match that is the one that will be used
706
+ entitySchema.entitypath = actionInfo.entitypath[ekeys[0]];
707
+ for (let ep = 1; ep < ekeys.length; ep += 1) {
708
+ // see if the key matches the choosepath value, if it does set the entitypath
709
+ if (choosepath && ekeys[ep] === choosepath) {
710
+ entitySchema.entitypath = actionInfo.entitypath[ekeys[ep]];
711
+ break;
712
+ }
713
+ }
714
+ } else {
715
+ // add the specific pieces of the error object
716
+ errorObj.type = 'Invalid Action File';
717
+ errorObj.vars = ['missing entity path', entityName];
718
+
719
+ // log (if not system entity) and return the error
720
+ if (entityName !== '.system') {
721
+ log.error(`${origin}: Entity ${entityName} action ${actionName} - missing entity path`);
722
+ errorObj.error = [`${origin}: Entity ${entityName} action ${actionName} - missing entity path`];
723
+ }
724
+ return callback(null, errorObj);
725
+ }
726
+ }
727
+
675
728
  // if info provided, replace the defaults
676
729
  if (actionInfo.querykey) {
677
730
  entitySchema.querykey = actionInfo.querykey;
@@ -796,14 +849,14 @@ class AdapterPropertyUtil {
796
849
  *
797
850
  * @return {Object} entitySchema - the entity schema object
798
851
  */
799
- getEntitySchema(entityName, actionName, dbUtils, callback) {
852
+ getEntitySchema(entityName, actionName, choosepath, dbUtils, callback) {
800
853
  const origin = `${this.myid}-propertyUtil-getEntitySchema`;
801
854
  log.trace(origin);
802
855
 
803
856
  // need to try to get the entity schema from the adapter database
804
857
  try {
805
858
  // call to get the adapter schema from the database
806
- return this.getEntitySchemaFromDB(null, entityName, actionName, dbUtils, (dbresp, dberror) => {
859
+ return this.getEntitySchemaFromDB(null, entityName, actionName, choosepath, dbUtils, (dbresp, dberror) => {
807
860
  // if we got an error back - just means db config not in place
808
861
  if (dberror || !dbresp || (dbresp && Object.keys(dbresp).length === 0)) {
809
862
  log.debug('unable to get adapter config from adapter database');
@@ -816,7 +869,7 @@ class AdapterPropertyUtil {
816
869
  };
817
870
 
818
871
  // need to try to get the entity schema from the iap database
819
- return this.getEntitySchemaFromDB(iapDB, entityName, actionName, dbUtils, (iapdbresp, iapdberror) => {
872
+ return this.getEntitySchemaFromDB(iapDB, entityName, actionName, choosepath, dbUtils, (iapdbresp, iapdberror) => {
820
873
  // if we got an error back - just means db config not in place
821
874
  if (iapdberror || !iapdbresp || (iapdbresp && Object.keys(iapdbresp).length === 0)) {
822
875
  log.debug('unable to get adapter config from iap database');
@@ -824,7 +877,7 @@ class AdapterPropertyUtil {
824
877
  // need to try to get the entity schema from the filesystem
825
878
  log.debug('returning adapter config from file system');
826
879
  try {
827
- return callback(this.getEntitySchemaFromFS(entityName, actionName), null);
880
+ return callback(this.getEntitySchemaFromFS(entityName, actionName, choosepath), null);
828
881
  } catch (exc) {
829
882
  log.error('Exception caught on File System');
830
883
  return callback(null, exc);
@@ -117,6 +117,11 @@ function walkThroughActionFiles(directory) {
117
117
  const actionSchema = JSON.parse(fs.readFileSync(actionSchemaFile, 'utf-8'));
118
118
  const entitydir = `${directory}/entities`;
119
119
 
120
+ // if there is no entity directory - return
121
+ if (!fs.existsSync(directory) || !fs.existsSync(entitydir)) {
122
+ return clean;
123
+ }
124
+
120
125
  // if there is an entity directory
121
126
  if (fs.statSync(directory).isDirectory() && fs.statSync(entitydir).isDirectory()) {
122
127
  const entities = fs.readdirSync(entitydir);
@@ -577,7 +582,7 @@ class RequestHandler {
577
582
  }
578
583
 
579
584
  // Get the entity schema from the file system
580
- return this.propUtil.getEntitySchema(entity, action, this.dbUtil, (entitySchema, entityError) => {
585
+ return this.propUtil.getEntitySchema(entity, action, this.props.choosepath, this.dbUtil, (entitySchema, entityError) => {
581
586
  // verify protocol for call
582
587
  if (entityError) {
583
588
  const errorObj = this.transUtil.checkAndReturn(entityError, origin, 'Issue identifiying request');
@@ -673,7 +678,7 @@ class RequestHandler {
673
678
  let prot = this.props.healthcheck.protocol;
674
679
 
675
680
  // Get the entity schema from the file system
676
- return this.propUtil.getEntitySchema('.system', 'healthcheck', this.dbUtil, (healthSchema, healthError) => {
681
+ return this.propUtil.getEntitySchema('.system', 'healthcheck', this.props.choosepath, this.dbUtil, (healthSchema, healthError) => {
677
682
  if (healthError || !healthSchema || Object.keys(healthSchema).length === 0) {
678
683
  log.debug(`${origin}: Using adapter properties for healthcheck information`);
679
684
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itentialopensource/adapter-utils",
3
- "version": "4.47.0",
3
+ "version": "4.48.1",
4
4
  "description": "Itential Adapter Utility Libraries",
5
5
  "scripts": {
6
6
  "postinstall": "node utils/setup.js",
@@ -32,10 +32,12 @@
32
32
  ]
33
33
  },
34
34
  "entitypath": {
35
- "type": "string",
36
- "description": "the path to use for this action",
37
- "default": "GET",
38
- "pattern": "^({base_path}|\\/)[-a-zA-Z0-9!@$:&%_+.,~#\\/*=:]*({version})?([-a-zA-Z0-9!@$:&%_+.,~#\\/*=:]*({pathv[0-9]+})?)*(\\??[-a-zA-Z0-9!@$:&%_+.,\\(\\)~#\\/*=:]*({username})?[-a-zA-Z0-9!@$:&%_+.,\\(\\)~#\/*=:]*({password})?({query})?)?$",
35
+ "type": [
36
+ "string",
37
+ "object"
38
+ ],
39
+ "description": "the path(s) to use for this action",
40
+ "default": "",
39
41
  "examples": [
40
42
  "/api/devices{pathv1}{query}", "/api/devices{pathv1}/components{pathv2}{query}",
41
43
  "/api/devices", "/api/devices{query}"
@@ -18,6 +18,11 @@
18
18
  "minimum": 1,
19
19
  "maximum": 65535
20
20
  },
21
+ "choosepath": {
22
+ "type": "string",
23
+ "description": "choose the path to use -- requires entityPath choices",
24
+ "default": ""
25
+ },
21
26
  "base_path": {
22
27
  "type": "string",
23
28
  "description": "a base path that is consistent across api calls",
@@ -382,7 +387,8 @@
382
387
  },
383
388
  "query_object": {
384
389
  "type": "object",
385
- "description": "Query object { device: xxxxx } to be placed into the healthcheck, will be converted to query string by the adapter"
390
+ "description": "Query object { device: xxxxx } to be placed into the healthcheck, will be converted to query string by the adapter",
391
+ "default": {}
386
392
  }
387
393
  },
388
394
  "required": [
@@ -462,6 +468,7 @@
462
468
  "priorities": {
463
469
  "type": "array",
464
470
  "description": "define your priorities here",
471
+ "default": [],
465
472
  "items": {
466
473
  "type": "object",
467
474
  "properties": {
@@ -532,6 +539,7 @@
532
539
  "failover_codes": {
533
540
  "type": "array",
534
541
  "description": "An array of codes where it is ok to try another method",
542
+ "default": [],
535
543
  "items": {
536
544
  "type": "integer"
537
545
  }
@@ -549,19 +557,23 @@
549
557
  "properties": {
550
558
  "payload": {
551
559
  "type": "object",
552
- "description": "payload fields that will be appended to the provided payload (excluding GET calls)"
560
+ "description": "payload fields that will be appended to the provided payload (excluding GET calls)",
561
+ "default": {}
553
562
  },
554
563
  "uriOptions": {
555
564
  "type": "object",
556
- "description": "options that will be appended to all GET calls"
565
+ "description": "options that will be appended to all GET calls",
566
+ "default": {}
557
567
  },
558
568
  "addlHeaders": {
559
569
  "type": "object",
560
- "description": "headers that will be appended to the headers for the call"
570
+ "description": "headers that will be appended to the headers for the call",
571
+ "default": {}
561
572
  },
562
573
  "authData": {
563
574
  "type": "object",
564
- "description": "authentication data that will be appended to the payload for authentication calls"
575
+ "description": "authentication data that will be appended to the payload for authentication calls",
576
+ "default": {}
565
577
  }
566
578
  }
567
579
  },