@itentialopensource/adapter-utils 5.0.5 → 5.1.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.
package/CHANGELOG.md CHANGED
@@ -1,4 +1,14 @@
1
1
 
2
+ ## 5.1.0 [08-04-2023]
3
+
4
+ * Changes to choosepath logic
5
+
6
+ Closes ADAPT-2828
7
+
8
+ See merge request itentialopensource/adapter-utils!267
9
+
10
+ ---
11
+
2
12
  ## 5.0.5 [07-24-2023]
3
13
 
4
14
  * Fix throttle bug on connectivity issue
package/error.json CHANGED
@@ -90,6 +90,12 @@
90
90
  "displayString": "Invalid schema file: $VARIABLE$ in $VARIABLE$",
91
91
  "recommendation": "Verify the action file"
92
92
  },
93
+ {
94
+ "key": "Action Not Available",
95
+ "icode": "AD.305",
96
+ "displayString": "This action is $VARIABLE$ version $VARIABLE$",
97
+ "recommendation": "Run against an appropriate version if possible"
98
+ },
93
99
  {
94
100
  "key": "Query Not Translated",
95
101
  "icode": "AD.310",
@@ -10,12 +10,234 @@ const path = require('path');
10
10
  // The crypto libraries
11
11
  const cryptoJS = require('crypto-js');
12
12
 
13
+ let id = null;
14
+
15
+ /**
16
+ * @summary Determines the order of version in the list of items
17
+ * Allowed formats:
18
+ * #, #.#, #.#.#, etc
19
+ * v#, v#.#, v#.#.#, etc
20
+ * ver#, ver#.#, ver#.#.#, etc
21
+ *
22
+ * @function itemOrder
23
+ *
24
+ * @param {String} firstItem - the firstItem (required)
25
+ * @param {String} secondItem - the secondItem (required)
26
+ *
27
+ * @return {Number} -1 if firstItem is first; 0 if secondItem is first; 1 if equal
28
+ */
29
+ function itemOrder(firstItem, secondItem) {
30
+ const origin = `${id}-propertyUtil-itemOrder`;
31
+ log.trace(origin);
32
+ let myFirst = firstItem;
33
+ let mySecond = secondItem;
34
+
35
+ // strip off 'v' or 'ver' so can handle like other . seperated things
36
+ if (myFirst) {
37
+ if (myFirst.toUpperCase().startsWith('VER')) {
38
+ myFirst = myFirst.substring(3);
39
+ }
40
+ if (myFirst.toUpperCase().startsWith('V')) {
41
+ myFirst = myFirst.substring(1);
42
+ }
43
+ }
44
+ if (mySecond) {
45
+ if (mySecond.toUpperCase().startsWith('VER')) {
46
+ mySecond = mySecond.substring(3);
47
+ }
48
+ if (mySecond.toUpperCase().startsWith('V')) {
49
+ mySecond = mySecond.substring(1);
50
+ }
51
+ }
52
+
53
+ // split the items based on versioning '.'
54
+ const firstParts = myFirst.split('.');
55
+ const secondParts = mySecond.split('.');
56
+
57
+ // like string compare in case not just #s but issue with different size #s (2 > 10)
58
+ // pad in front with leading 0 (assume number want same digits)
59
+ while (firstParts[0].length < secondParts[0].length) {
60
+ firstParts[0] = `0${firstParts[0]}`;
61
+ }
62
+ while (secondParts[0].length < firstParts[0].length) {
63
+ secondParts[0] = `0${secondParts[0]}`;
64
+ }
65
+
66
+ // if first is less
67
+ if (firstParts[0] < secondParts[0]) {
68
+ return -1;
69
+ }
70
+ // if second is less
71
+ if (firstParts[0] > secondParts[0]) {
72
+ return 0;
73
+ }
74
+ // can not continue if firstPart is length 1
75
+ if (firstParts.length === 1) {
76
+ // both length 1 and equal value
77
+ if (secondParts.length === 1) {
78
+ return 1;
79
+ }
80
+ // second one longer length (first 3; second 3.3) - so first is less
81
+ return -1;
82
+ }
83
+ // can not continue if secondPart is length 1
84
+ if (secondParts.length === 1) {
85
+ // first one longer length (first 3.3; second 3) - so second is less
86
+ return 0;
87
+ }
88
+
89
+ // both have to be at least length 2 and equal first
90
+ // remove the first item for each
91
+ firstParts.shift();
92
+ secondParts.shift();
93
+
94
+ // recursive call - putting back together remaining parts
95
+ return itemOrder(firstParts.join('.'), secondParts.join('.'));
96
+ }
97
+
98
+ /**
99
+ * @summary Goes through the available paths and returns the appropriate one
100
+ *
101
+ * @function returnPath
102
+ *
103
+ * @param {String} value - the text to encrypt (required)
104
+ * @param {Object} eInfo - the encryption information (optional)
105
+ *
106
+ * @return {String} the path to use in the call
107
+ */
108
+ function returnPath(actionInfo, entityName, actionName, choosePath, startV, endV) {
109
+ const origin = `${id}-propertyUtil-returnPath`;
110
+ log.trace(origin);
111
+
112
+ // create the generic part of an error object
113
+ const errorObj = {
114
+ origin
115
+ };
116
+
117
+ // if there is no entitypath - throw error
118
+ if (!actionInfo.entitypath) {
119
+ // add the specific pieces of the error object
120
+ errorObj.type = 'Invalid Action File';
121
+ errorObj.vars = ['missing entity path for action', entityName];
122
+
123
+ // log (if not system entity) and return the error
124
+ if (entityName !== '.system') {
125
+ log.warn(`${origin}: Entity ${entityName} action ${actionName} - missing entity path`);
126
+ errorObj.error = [`${origin}: Entity ${entityName} action ${actionName} - missing entity path`];
127
+ }
128
+
129
+ throw new Error(JSON.stringify(errorObj));
130
+ }
131
+
132
+ // if entitypath is not a string or an object - throw error
133
+ if ((typeof actionInfo.entitypath !== 'string' && typeof actionInfo.entitypath !== 'object') || Array.isArray(actionInfo.entitypath)) {
134
+ // add the specific pieces of the error object
135
+ errorObj.type = 'Invalid Action File';
136
+ errorObj.vars = ['invalid entity path for action', entityName];
137
+
138
+ // log (if not system entity) and return the error
139
+ if (entityName !== '.system') {
140
+ log.warn(`${origin}: Entity ${entityName} action ${actionName} - invalid entity path`);
141
+ errorObj.error = [`${origin}: Entity ${entityName} action ${actionName} - invalid entity path`];
142
+ }
143
+
144
+ throw new Error(JSON.stringify(errorObj));
145
+ }
146
+
147
+ // if choosepath & it is before start - return error
148
+ if (choosePath && startV && itemOrder(startV, choosePath) === 0) {
149
+ // add the specific pieces of the error object
150
+ errorObj.type = 'Action Not Available';
151
+ errorObj.vars = ['not available until', startV];
152
+
153
+ // log (if not system entity) and return the error
154
+ if (entityName !== '.system') {
155
+ log.warn(`${origin}: Entity ${entityName} action ${actionName} - not available until version ${startV}`);
156
+ errorObj.error = [`${origin}: Entity ${entityName} action ${actionName} - not available until version ${startV}`];
157
+ }
158
+
159
+ throw new Error(JSON.stringify(errorObj));
160
+ }
161
+
162
+ // if choosepath & it is after end - return error
163
+ if (choosePath && endV && itemOrder(choosePath, endV) === 0) {
164
+ // add the specific pieces of the error object
165
+ errorObj.type = 'Action Not Available';
166
+ errorObj.vars = ['end of life in', endV];
167
+
168
+ // log (if not system entity) and return the error
169
+ if (entityName !== '.system') {
170
+ log.warn(`${origin}: Entity ${entityName} action ${actionName} - end of life in version ${endV}`);
171
+ errorObj.error = [`${origin}: Entity ${entityName} action ${actionName} - end of life in version ${endV}`];
172
+ }
173
+
174
+ throw new Error(JSON.stringify(errorObj));
175
+ }
176
+
177
+ // if the entitypath is a string - return it
178
+ if (typeof actionInfo.entitypath === 'string') {
179
+ // return the path we have
180
+ return actionInfo.entitypath;
181
+ }
182
+
183
+ // if the entitypath is an object instead of a string need to figure out which path to use
184
+ const ekeys = Object.keys(actionInfo.entitypath);
185
+
186
+ // if entitypath is object with no fields - throw error
187
+ if (ekeys.length === 0) {
188
+ // add the specific pieces of the error object
189
+ errorObj.type = 'Invalid Action File';
190
+ errorObj.vars = ['missing entity path for action', entityName];
191
+
192
+ // log (if not system entity) and return the error
193
+ if (entityName !== '.system') {
194
+ log.warn(`${origin}: Entity ${entityName} action ${actionName} - missing entity path`);
195
+ errorObj.error = [`${origin}: Entity ${entityName} action ${actionName} - missing entity path`];
196
+ }
197
+
198
+ throw new Error(JSON.stringify(errorObj));
199
+ }
200
+
201
+ // if nothing for me to base choice on
202
+ if (!choosePath) {
203
+ // the first one is the default so return it
204
+ return actionInfo.entitypath[ekeys[0]];
205
+ }
206
+
207
+ // initialization
208
+ let foundPath = '';
209
+ let beforePath = ekeys[0];
210
+
211
+ // go through the paths for an exact match
212
+ for (let ep = 0; ep < ekeys.length; ep += 1) {
213
+ // see if the key matches the choosepath value, if it does set the entitypath
214
+ if (choosePath && ekeys[ep] === choosePath) {
215
+ foundPath = actionInfo.entitypath[ekeys[ep]];
216
+ break;
217
+ }
218
+
219
+ // see if path key is before choosePath but after current beforePath (in between) - reset beforePath
220
+ if (itemOrder(choosePath, ekeys[ep]) === 0 && itemOrder(beforePath, ekeys[ep]) === -1) {
221
+ beforePath = ekeys[ep];
222
+ }
223
+ }
224
+
225
+ // if exact match was found
226
+ if (foundPath) {
227
+ return foundPath;
228
+ }
229
+
230
+ // if no exact then use the beforePath
231
+ return actionInfo.entitypath[beforePath];
232
+ }
233
+
13
234
  class AdapterPropertyUtil {
14
235
  /**
15
236
  * Adapter Translator Utility
16
237
  * @constructor
17
238
  */
18
239
  constructor(prongId, directory) {
240
+ id = prongId;
19
241
  this.myid = prongId;
20
242
  this.baseDir = directory;
21
243
  }
@@ -265,31 +487,8 @@ class AdapterPropertyUtil {
265
487
  entitySchema.responseObjects = [];
266
488
  entitySchema.mockresponses = [];
267
489
 
268
- // if the entitypath is an object instead of a string need to figure out which path to use
269
- if (actionInfo.entitypath && typeof actionInfo.entitypath === 'object') {
270
- const ekeys = Object.keys(actionInfo.entitypath);
271
- if (ekeys.length > 0) {
272
- // the first one is the default so if we do not have a match that is the one that will be used
273
- entitySchema.entitypath = actionInfo.entitypath[ekeys[0]];
274
- for (let ep = 1; ep < ekeys.length; ep += 1) {
275
- // see if the key matches the choosepath value, if it does set the entitypath
276
- if (choosepath && ekeys[ep] === choosepath) {
277
- entitySchema.entitypath = actionInfo.entitypath[ekeys[ep]];
278
- break;
279
- }
280
- }
281
- } else {
282
- // add the specific pieces of the error object
283
- errorObj.type = 'Invalid Action File';
284
- errorObj.vars = ['missing entity path', actionFile];
285
-
286
- // log (if not system entity) and throw the error
287
- if (entityName !== '.system') {
288
- log.error(`${origin}: Entity ${entityName} action ${actionName} - missing entity path`);
289
- }
290
- throw new Error(JSON.stringify(errorObj));
291
- }
292
- }
490
+ // Determine the path to use for this call
491
+ entitySchema.entitypath = returnPath(actionInfo, entityName, actionName, choosepath, actionInfo.startVersion, actionInfo.endVersion);
293
492
 
294
493
  // if info provided, replace the defaults
295
494
  if (actionInfo.querykey) {
@@ -705,32 +904,8 @@ class AdapterPropertyUtil {
705
904
  entitySchema.responseObjects = [];
706
905
  entitySchema.mockresponses = [];
707
906
 
708
- // if the entitypath is an object instead of a string need to figure out which path to use
709
- if (actionInfo.entitypath && typeof actionInfo.entitypath === 'object') {
710
- const ekeys = Object.keys(actionInfo.entitypath);
711
- if (ekeys.length > 0) {
712
- // the first one is the default so if we do not have a match that is the one that will be used
713
- entitySchema.entitypath = actionInfo.entitypath[ekeys[0]];
714
- for (let ep = 1; ep < ekeys.length; ep += 1) {
715
- // see if the key matches the choosepath value, if it does set the entitypath
716
- if (choosepath && ekeys[ep] === choosepath) {
717
- entitySchema.entitypath = actionInfo.entitypath[ekeys[ep]];
718
- break;
719
- }
720
- }
721
- } else {
722
- // add the specific pieces of the error object
723
- errorObj.type = 'Invalid Action File';
724
- errorObj.vars = ['missing entity path', entityName];
725
-
726
- // log (if not system entity) and return the error
727
- if (entityName !== '.system') {
728
- log.warn(`${origin}: Entity ${entityName} action ${actionName} - missing entity path`);
729
- errorObj.error = [`${origin}: Entity ${entityName} action ${actionName} - missing entity path`];
730
- }
731
- return callback(null, errorObj);
732
- }
733
- }
907
+ // Determine the path to use for this call
908
+ entitySchema.entitypath = returnPath(actionInfo, entityName, actionName, choosepath, actionInfo.startVersion, actionInfo.endVersion);
734
909
 
735
910
  // if info provided, replace the defaults
736
911
  if (actionInfo.querykey) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itentialopensource/adapter-utils",
3
- "version": "5.0.5",
3
+ "version": "5.1.0",
4
4
  "description": "Itential Adapter Utility Libraries",
5
5
  "scripts": {
6
6
  "postinstall": "node utils/setup.js",
Binary file
@@ -250,14 +250,6 @@
250
250
  "description": "This property turns on logging of Authentication Information and should only be true when debugging authentication and connectivity",
251
251
  "default": false
252
252
  },
253
- "sensitive": {
254
- "type": "array",
255
- "description": "List of sensitive keys to search and hide values from being logged",
256
- "default": [],
257
- "items": {
258
- "type": "string"
259
- }
260
- },
261
253
  "client_id": {
262
254
  "type": "string",
263
255
  "description": "The client id for OAuth requests - can also use username depending on schema",
@@ -273,6 +265,14 @@
273
265
  "description": "The grant type for OAuth requests - can also provide in schema",
274
266
  "default": ""
275
267
  },
268
+ "sensitive": {
269
+ "type": "array",
270
+ "description": "List of sensitive keys to search and hide values from being logged",
271
+ "default": [],
272
+ "items": {
273
+ "type": "string"
274
+ }
275
+ },
276
276
  "sso": {
277
277
  "type": "object",
278
278
  "properties": {
@@ -300,6 +300,36 @@
300
300
  "maximum": 65535
301
301
  }
302
302
  }
303
+ },
304
+ "multiStepAuthCalls": {
305
+ "type": "array",
306
+ "items": {
307
+ "type": "object",
308
+ "properties": {
309
+ "name": {
310
+ "type": "string",
311
+ "description": "Id of the step call",
312
+ "examples": [
313
+ "getAccessToken"
314
+ ]
315
+ },
316
+ "requestFields": {
317
+ "type": "object",
318
+ "description": "The fields set in step request"
319
+ },
320
+ "responseFields": {
321
+ "type": "object",
322
+ "description": "The fields from the step result"
323
+ },
324
+ "successfullResponseCode": {
325
+ "type": "integer",
326
+ "description": "Expected response code for given step, if not set any successfull http response is accepted",
327
+ "examples": [
328
+ 200
329
+ ]
330
+ }
331
+ }
332
+ }
303
333
  }
304
334
  },
305
335
  "required": [
@@ -404,6 +434,11 @@
404
434
  "type": "object",
405
435
  "description": "Query object { device: xxxxx } to be placed into the healthcheck, will be converted to query string by the adapter",
406
436
  "default": {}
437
+ },
438
+ "addlHeaders": {
439
+ "type": "object",
440
+ "description": "headers that will be appended to the headers for the call",
441
+ "default": {}
407
442
  }
408
443
  },
409
444
  "required": [
@@ -919,21 +954,21 @@
919
954
  "type": "object",
920
955
  "description": "The json object with query parameters of the call to getDevice",
921
956
  "additionalProperties": {
922
- "type": "string"
957
+ "type": ["string", "number"]
923
958
  }
924
959
  },
925
960
  "body": {
926
961
  "type": "object",
927
962
  "description": "The json object with body of the call to getDevice",
928
963
  "additionalProperties": {
929
- "type": "string"
964
+ "type": ["string", "number"]
930
965
  }
931
966
  },
932
967
  "headers": {
933
968
  "type": "object",
934
969
  "description": "The json object with headers of the call to getDevice",
935
970
  "additionalProperties": {
936
- "type": "string"
971
+ "type": ["string", "number"]
937
972
  }
938
973
  },
939
974
  "handleFailure": {
@@ -949,7 +984,7 @@
949
984
  "type": "object",
950
985
  "description": "The json object with response fields of the call to getDevice",
951
986
  "additionalProperties": {
952
- "type": "string"
987
+ "type": ["string", "number"]
953
988
  },
954
989
  "properties": {}
955
990
  },
@@ -962,7 +997,7 @@
962
997
  "type": "object",
963
998
  "description": "The json object with response fields of the call to getDevice",
964
999
  "additionalProperties": {
965
- "type": "string"
1000
+ "type": ["string", "number"]
966
1001
  },
967
1002
  "properties": {
968
1003
  "name": {
@@ -1015,21 +1050,21 @@
1015
1050
  "type": "object",
1016
1051
  "description": "The json object with query parameters of the call to getDevicesFiltered",
1017
1052
  "additionalProperties": {
1018
- "type": "string"
1053
+ "type": ["string", "number"]
1019
1054
  }
1020
1055
  },
1021
1056
  "body": {
1022
1057
  "type": "object",
1023
1058
  "description": "The json object with body of the call to getDevicesFiltered",
1024
1059
  "additionalProperties": {
1025
- "type": "string"
1060
+ "type": ["string", "number"]
1026
1061
  }
1027
1062
  },
1028
1063
  "headers": {
1029
1064
  "type": "object",
1030
1065
  "description": "The json object with headers of the call to getDevicesFiltered",
1031
1066
  "additionalProperties": {
1032
- "type": "string"
1067
+ "type": ["string", "number"]
1033
1068
  }
1034
1069
  },
1035
1070
  "handleFailure": {
@@ -1045,7 +1080,7 @@
1045
1080
  "type": "object",
1046
1081
  "description": "The json object with response fields of the call to getDevice",
1047
1082
  "additionalProperties": {
1048
- "type": "string"
1083
+ "type": ["string", "number"]
1049
1084
  },
1050
1085
  "properties": {}
1051
1086
  },
@@ -1058,7 +1093,7 @@
1058
1093
  "type": "object",
1059
1094
  "description": "The json object with response fields of the call to getDevicesFiltered",
1060
1095
  "additionalProperties": {
1061
- "type": "string"
1096
+ "type": ["string", "number"]
1062
1097
  },
1063
1098
  "properties": {
1064
1099
  "name": {
@@ -1111,21 +1146,21 @@
1111
1146
  "type": "object",
1112
1147
  "description": "The json object with query parameters of the call to isAlive",
1113
1148
  "additionalProperties": {
1114
- "type": "string"
1149
+ "type": ["string", "number"]
1115
1150
  }
1116
1151
  },
1117
1152
  "body": {
1118
1153
  "type": "object",
1119
1154
  "description": "The json object with body of the call to isAlive",
1120
1155
  "additionalProperties": {
1121
- "type": "string"
1156
+ "type": ["string", "number"]
1122
1157
  }
1123
1158
  },
1124
1159
  "headers": {
1125
1160
  "type": "object",
1126
1161
  "description": "The json object with headers of the call to isAlive",
1127
1162
  "additionalProperties": {
1128
- "type": "string"
1163
+ "type": ["string", "number"]
1129
1164
  }
1130
1165
  },
1131
1166
  "handleFailure": {
@@ -1141,7 +1176,7 @@
1141
1176
  "type": "object",
1142
1177
  "description": "The json object with response fields of the call to getDevice",
1143
1178
  "additionalProperties": {
1144
- "type": "string"
1179
+ "type": ["string", "number"]
1145
1180
  },
1146
1181
  "properties": {}
1147
1182
  },
@@ -1154,7 +1189,7 @@
1154
1189
  "type": "object",
1155
1190
  "description": "The json object with response fields of the call to isAlive",
1156
1191
  "additionalProperties": {
1157
- "type": "string"
1192
+ "type": ["string", "number"]
1158
1193
  },
1159
1194
  "properties": {
1160
1195
  "status": {
@@ -1192,21 +1227,21 @@
1192
1227
  "type": "object",
1193
1228
  "description": "The json object with query parameters of the call to getConfig",
1194
1229
  "additionalProperties": {
1195
- "type": "string"
1230
+ "type": ["string", "number"]
1196
1231
  }
1197
1232
  },
1198
1233
  "body": {
1199
1234
  "type": "object",
1200
1235
  "description": "The json object with body of the call to getConfig",
1201
1236
  "additionalProperties": {
1202
- "type": "string"
1237
+ "type": ["string", "number"]
1203
1238
  }
1204
1239
  },
1205
1240
  "headers": {
1206
1241
  "type": "object",
1207
1242
  "description": "The json object with headers of the call to getConfig",
1208
1243
  "additionalProperties": {
1209
- "type": "string"
1244
+ "type": ["string", "number"]
1210
1245
  }
1211
1246
  },
1212
1247
  "handleFailure": {
@@ -1222,7 +1257,7 @@
1222
1257
  "type": "object",
1223
1258
  "description": "The json object with response fields of the call to getDevice",
1224
1259
  "additionalProperties": {
1225
- "type": "string"
1260
+ "type": ["string", "number"]
1226
1261
  },
1227
1262
  "properties": {}
1228
1263
  },
@@ -1235,7 +1270,7 @@
1235
1270
  "type": "object",
1236
1271
  "description": "The json object with response fields of the call to getConfig",
1237
1272
  "additionalProperties": {
1238
- "type": "string"
1273
+ "type": ["string", "number"]
1239
1274
  },
1240
1275
  "properties": {}
1241
1276
  }
@@ -1262,21 +1297,21 @@
1262
1297
  "type": "object",
1263
1298
  "description": "The json object with query parameters of the call to getCount",
1264
1299
  "additionalProperties": {
1265
- "type": "string"
1300
+ "type": ["string", "number"]
1266
1301
  }
1267
1302
  },
1268
1303
  "body": {
1269
1304
  "type": "object",
1270
1305
  "description": "The json object with body of the call to getCount",
1271
1306
  "additionalProperties": {
1272
- "type": "string"
1307
+ "type": ["string", "number"]
1273
1308
  }
1274
1309
  },
1275
1310
  "headers": {
1276
1311
  "type": "object",
1277
1312
  "description": "The json object with headers of the call to getCount",
1278
1313
  "additionalProperties": {
1279
- "type": "string"
1314
+ "type": ["string", "number"]
1280
1315
  }
1281
1316
  },
1282
1317
  "handleFailure": {
@@ -1292,7 +1327,7 @@
1292
1327
  "type": "object",
1293
1328
  "description": "The json object with response fields of the call to getDevice",
1294
1329
  "additionalProperties": {
1295
- "type": "string"
1330
+ "type": ["string", "number"]
1296
1331
  },
1297
1332
  "properties": {}
1298
1333
  },
@@ -1305,7 +1340,7 @@
1305
1340
  "type": "object",
1306
1341
  "description": "The json object with response fields of the call to getConfig",
1307
1342
  "additionalProperties": {
1308
- "type": "string"
1343
+ "type": ["string", "number"]
1309
1344
  },
1310
1345
  "properties": {}
1311
1346
  }
@@ -1379,21 +1414,21 @@
1379
1414
  "type": "object",
1380
1415
  "description": "The json object with query parameters of the call to getDevice",
1381
1416
  "additionalProperties": {
1382
- "type": "string"
1417
+ "type": ["string", "number"]
1383
1418
  }
1384
1419
  },
1385
1420
  "body": {
1386
1421
  "type": "object",
1387
1422
  "description": "The json object with body of the call to getDevice",
1388
1423
  "additionalProperties": {
1389
- "type": "string"
1424
+ "type": ["string", "number"]
1390
1425
  }
1391
1426
  },
1392
1427
  "headers": {
1393
1428
  "type": "object",
1394
1429
  "description": "The json object with headers of the call to getDevice",
1395
1430
  "additionalProperties": {
1396
- "type": "string"
1431
+ "type": ["string", "number"]
1397
1432
  }
1398
1433
  },
1399
1434
  "handleFailure": {
@@ -1409,7 +1444,7 @@
1409
1444
  "type": "object",
1410
1445
  "description": "The json object with response fields of the call to getDevice",
1411
1446
  "additionalProperties": {
1412
- "type": "string"
1447
+ "type": ["string", "number"]
1413
1448
  },
1414
1449
  "properties": {}
1415
1450
  },
@@ -1422,7 +1457,7 @@
1422
1457
  "type": "object",
1423
1458
  "description": "The json object with response fields of the call to getDevice",
1424
1459
  "additionalProperties": {
1425
- "type": "string"
1460
+ "type": ["string", "number"]
1426
1461
  }
1427
1462
  }
1428
1463
  }