un-cli 0.0.73 → 0.0.76

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/cmd.txt CHANGED
@@ -1,2 +1,2 @@
1
- update subnetworks --all --desc
1
+ topology --validate --fishnet
2
2
  exit
package/index.html CHANGED
@@ -44,6 +44,8 @@
44
44
  <td><button id = 'btnSQLLogs'>SQL Logs</button></td>
45
45
  <td>Message<input id = 'txtFilter' type = 'text'></td>
46
46
  <td>User<input id = 'txtUser' type = 'text'></td>
47
+ <td>Start Time<input id = 'txtStartTime' type = 'text'></td>
48
+ <td>End Time<input id = 'txtEndTime' type = 'text'></td>
47
49
  </tr>
48
50
 
49
51
  </table>
@@ -87,12 +89,14 @@
87
89
 
88
90
  cmbService = document.getElementById("cmbService")
89
91
  while (cmbService.firstChild) cmbService.removeChild(cmbService.firstChild)
90
-
92
+
93
+ token = await getToken(parameters);
94
+
95
+ //if we logged in successfully
91
96
  const opt = document.createElement("option")
92
97
  opt.textContent = "(All Services)"
93
98
  cmbService.appendChild (opt)
94
99
 
95
- token = await getToken(parameters);
96
100
  const services = await portal.services()
97
101
  const featureServices = services.services.filter(s => s.type == "FeatureServer")
98
102
  featureServices.forEach(s=> {
@@ -127,7 +131,7 @@
127
131
 
128
132
 
129
133
  async function loadTraceLogs () {
130
-
134
+
131
135
  //build table
132
136
  const tblResult = document.getElementById("tblResult");
133
137
  //clear
@@ -141,9 +145,110 @@
141
145
  console.log(`Querying trace logs for ${parameters.service} for the last ${mins} minutes ...`)
142
146
 
143
147
  //page query the admin log
144
- let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102002], "------ Trace Parameters ----", "VERBOSE")
148
+ let allTheMessages = await adminLogQueryWithPaging(mins, parameters.service, [102002], "------ Trace Parameters ----", "VERBOSE")
149
+
150
+ let allMessages = filterMessages (allTheMessages).map(m => {
151
+ const newMessage = Object.assign({}, m);
152
+ delete newMessage.machine;
153
+ delete newMessage.type;
154
+ delete newMessage.code;
155
+ delete newMessage.requestID;
156
+ delete newMessage.process;
157
+ delete newMessage.thread;
158
+ newMessage.elapsedms = parseInt (parseFloat(newMessage.elapsed) * 1000)
159
+ newMessage.time = new Date(newMessage.time).toLocaleString()
160
+ delete newMessage.elapsed
161
+
162
+ try{
163
+
164
+ //Total Trace Time (4.745 seconds)
165
+
166
+ let re = /Total Trace Time \([-+]?([0-9]*\.[0-9]+|[0-9]+) seconds\)/;
167
+ let res = re.exec(m.message)
168
+ if (res && res.length > 1)
169
+ newMessage.traceTime = parseFloat(res[1])*1000
170
+
171
+ let re1 = /Trace Type: .\w.*/;
172
+ let res1 = re1.exec(m.message)
173
+ if (res1 && res1.length > 0)
174
+ newMessage.traceType = res1[0].replace("Trace Type: ","")
145
175
 
146
- await populateMessages(allMessages)
176
+ }
177
+ catch(ex){
178
+ console.error(ex)
179
+ }
180
+
181
+
182
+ return newMessage;
183
+ })
184
+ .sort( (m1,m2) => m2.elapsedms - m1.elapsedms)
185
+
186
+ //clear
187
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
188
+
189
+ const header = document.createElement("tr");
190
+ const cService = document.createElement("th");
191
+ cService.textContent = "Source"
192
+ const cTime = document.createElement("th");
193
+ cTime.textContent = "Time"
194
+ const cUser = document.createElement("th");
195
+ cUser.textContent = "User"
196
+ const cMethod = document.createElement("th");
197
+ cMethod.textContent = "Method"
198
+ const cElapsedMS = document.createElement("th");
199
+ cElapsedMS.textContent = "Elapsed (ms)"
200
+ const cTraceType = document.createElement("th");
201
+ cTraceType.textContent = "Trace Type"
202
+ const cTraceTime = document.createElement("th");
203
+ cTraceTime.textContent = "Trace Time"
204
+ const cLog = document.createElement("th");
205
+ cLog.textContent = "Full Log"
206
+ header.appendChild (cService)
207
+ header.appendChild (cTime)
208
+ header.appendChild (cUser)
209
+ header.appendChild (cMethod)
210
+ header.appendChild (cTraceType)
211
+ header.appendChild (cTraceTime)
212
+ header.appendChild (cElapsedMS)
213
+
214
+ header.appendChild (cLog)
215
+ tblResult.appendChild(header)
216
+ allMessages.forEach(m => {
217
+ const logRow = document.createElement("tr");
218
+ const cService = document.createElement("td");
219
+ cService.textContent = m.source.replace(".MapServer", "")
220
+ const cTime = document.createElement("td");
221
+ cTime.textContent = m.time
222
+ const cUser = document.createElement("td");
223
+ cUser.textContent = m.user
224
+ const cMethod = document.createElement("td");
225
+ cMethod.textContent = m.methodName
226
+ const cElapsedMS = document.createElement("td");
227
+ cElapsedMS.textContent = m.elapsedms
228
+ const cTraceType = document.createElement("td");
229
+ cTraceType.textContent = m.traceType
230
+ const cTraceTime = document.createElement("td");
231
+ cTraceTime.textContent = m.traceTime
232
+
233
+ const cLog = document.createElement("td");
234
+ cLog.textContent = "..."
235
+ cLog.fullLog = m.message;
236
+ cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); alert("Copied to clipboard")})
237
+ logRow.appendChild (cService)
238
+ logRow.appendChild (cTime)
239
+ logRow.appendChild (cUser)
240
+ logRow.appendChild (cMethod)
241
+ logRow.appendChild (cTraceType)
242
+ logRow.appendChild (cTraceTime)
243
+ logRow.appendChild (cElapsedMS)
244
+
245
+ logRow.appendChild (cLog)
246
+ tblResult.appendChild(logRow)
247
+ })
248
+
249
+
250
+
251
+ //await populateMessages(allMessages)
147
252
 
148
253
 
149
254
  }
@@ -206,31 +311,114 @@ async function loadUpdateSubnetworkLogs () {
206
311
 
207
312
 
208
313
  console.log(`Querying subnetwork logs for ${parameters.service} for the last ${mins} minutes ...`)
209
- let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "---- Subnetwork Parameters ----", "VERBOSE")
314
+ let allTheMessages = await adminLogQueryWithPaging(mins, parameters.service, [102003], "---- Subnetwork Parameters ----", "VERBOSE")
210
315
 
316
+
211
317
 
212
- //update subnetwork missing elapsed populate it
213
- allMessages = allMessages.map( m => {
214
- try{
318
+ let allMessages = filterMessages (allTheMessages).map(m => {
319
+
320
+ const newMessage = Object.assign({}, m);
321
+ try{
322
+
323
+ delete newMessage.machine;
324
+ delete newMessage.type;
325
+ delete newMessage.code;
326
+ delete newMessage.requestID;
327
+ delete newMessage.process;
328
+ delete newMessage.thread;
329
+
330
+
331
+ let re = /Total \([-+]?([0-9]*\.[0-9]+|[0-9]+) seconds\)/;
332
+ let res = re.exec(m.message)
333
+ if (res && res.length > 0)
334
+ newMessage.elapsed = res[1]
335
+
336
+ re = /Total update subnetwork time \([-+]?([0-9]*\.[0-9]+|[0-9]+) seconds\)/;
337
+ res = re.exec(m.message)
338
+ if (res && res.length > 0)
339
+ newMessage.elapsed = res[1]
215
340
 
216
- let re = /Total \([-+]?([0-9]*\.[0-9]+|[0-9]+) seconds\)/;
217
- let res = re.exec(m.message)
218
- if (res && res.length > 1)
219
- m.elapsed = res[1]
220
-
221
- re = /Total update subnetwork time \([-+]?([0-9]*\.[0-9]+|[0-9]+) seconds\)/;
222
- res = re.exec(m.message)
223
- if (res && res.length > 1)
224
- m.elapsed = res[1]
225
-
226
- return m;
341
+
342
+ let re1 = /Subnetwork name: .*/;
343
+ let res1 = re1.exec(m.message)
344
+ if (res1 && res1.length > 0)
345
+ newMessage.subnetworkName = res1[0].replace("Subnetwork name: ","")
346
+
347
+
348
+ newMessage.elapsedms = parseInt (parseFloat(newMessage.elapsed) * 1000)
349
+ newMessage.time = new Date(newMessage.time).toLocaleString()
350
+ delete newMessage.elapsed
351
+
352
+
227
353
  }
228
354
  catch(ex){
229
- return m;
355
+ console.error(ex)
230
356
  }
357
+ finally {
358
+ return newMessage;
359
+ }
360
+
361
+ })
362
+ .sort( (m1,m2) => m2.elapsedms - m1.elapsedms)
363
+
364
+ //clear
365
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
366
+
367
+ const header = document.createElement("tr");
368
+ const cService = document.createElement("th");
369
+ cService.textContent = "Source"
370
+ const cTime = document.createElement("th");
371
+ cTime.textContent = "Time"
372
+ const cUser = document.createElement("th");
373
+ cUser.textContent = "User"
374
+ const cMethod = document.createElement("th");
375
+ cMethod.textContent = "Method"
376
+ const cElapsedMS = document.createElement("th");
377
+ cElapsedMS.textContent = "Elapsed (ms)"
378
+ const cSubnetworkName = document.createElement("th");
379
+ cSubnetworkName.textContent = "Subnetwork Name"
380
+ const cLog = document.createElement("th");
381
+ cLog.textContent = "Full Log"
382
+ header.appendChild (cService)
383
+ header.appendChild (cTime)
384
+ header.appendChild (cUser)
385
+ header.appendChild (cMethod)
386
+ header.appendChild (cSubnetworkName)
387
+ header.appendChild (cElapsedMS)
388
+
389
+ header.appendChild (cLog)
390
+ tblResult.appendChild(header)
391
+ allMessages.forEach(m => {
392
+ const logRow = document.createElement("tr");
393
+ const cService = document.createElement("td");
394
+ cService.textContent = m.source.replace(".MapServer", "")
395
+ const cTime = document.createElement("td");
396
+ cTime.textContent = m.time
397
+ const cUser = document.createElement("td");
398
+ cUser.textContent = m.user
399
+ const cMethod = document.createElement("td");
400
+ cMethod.textContent = m.methodName
401
+ const cElapsedMS = document.createElement("td");
402
+ cElapsedMS.textContent = m.elapsedms
403
+ const cSubnetworkName = document.createElement("td");
404
+ cSubnetworkName.textContent = m.subnetworkName
405
+
406
+ const cLog = document.createElement("td");
407
+ cLog.textContent = "..."
408
+ cLog.fullLog = m.message;
409
+ cLog.addEventListener("click", e=> {navigator.clipboard.writeText(e.target.fullLog); alert("Copied to clipboard")})
410
+ logRow.appendChild (cService)
411
+ logRow.appendChild (cTime)
412
+ logRow.appendChild (cUser)
413
+ logRow.appendChild (cMethod)
414
+ logRow.appendChild (cSubnetworkName)
415
+ logRow.appendChild (cElapsedMS)
416
+
417
+ logRow.appendChild (cLog)
418
+ tblResult.appendChild(logRow)
231
419
  })
232
- await populateMessages(allMessages)
233
420
 
421
+
234
422
 
235
423
  }
236
424
 
@@ -390,16 +578,16 @@ async function loadAttributeRules () {
390
578
  }
391
579
  async function loadSQLLogs () {
392
580
 
393
- //build table
394
- const tblResult = document.getElementById("tblResult");
395
- //clear
396
- while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
397
-
581
+ //build table
582
+ const tblResult = document.getElementById("tblResult");
583
+ //clear
584
+ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
585
+
398
586
 
399
- parameters.service = cmbService.options[cmbService.selectedIndex].text
400
-
401
-
402
- let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
587
+ parameters.service = cmbService.options[cmbService.selectedIndex].text
588
+
589
+
590
+ let mins = document.getElementById("txtAge").value //query logs for the last 30 minutes
403
591
 
404
592
 
405
593
  console.log(`Querying cursor sql logs for ${parameters.service} for the last ${mins} minutes ...`)
@@ -407,30 +595,7 @@ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
407
595
  //startTime is the most recent
408
596
  //endTime is the oldest
409
597
 
410
-
411
-
412
- /*
413
- const topLogCount = 100;
414
- const startTime = Date.now()
415
- const endTime = Date.now() - mins*60*1000
416
- let services = [theService + ".MapServer"]
417
- if (theService == "(All Services)")
418
- services = "*"
419
- let result= await adminLog.query([code], services, topLogCount, startTime ,endTime , "DEBUG")
420
- let jsonRes = await result.json()
421
- let allMessages = [].concat(jsonRes.logMessages)
422
- allMessages = allMessages.filter(m => m.message.indexOf("EndCursor;") > -1)
423
- while (jsonRes.hasMore)
424
- {
425
- //start paging
426
- logger.info(`Aggregating messages... total so far ${allMessages.length} entries but more left, pulling logs between ${new Date(jsonRes.endTime)} and ${new Date(endTime)}`)
427
- result= await adminLog.query([102023], services, pageSize, jsonRes.endTime, endTime, "DEBUG")
428
- jsonRes = await result.json()
429
-
430
- allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf("EndCursor;") > -1))
431
- }
432
- */
433
-
598
+
434
599
  //page query the admin log
435
600
  let allMessages = await adminLogQueryWithPaging(mins, parameters.service, [102023], "EndCursor;", "DEBUG")
436
601
 
@@ -534,7 +699,7 @@ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
534
699
  const cLog = document.createElement("td");
535
700
  const cLogText = document.createElement("input")
536
701
  cLogText.type = "text"
537
- cLogText.style = "width:500px"
702
+ cLogText.style = "width:800px"
538
703
  cLogText.value = m.message.substr( m.message.indexOf("SQL: ") + 5, m.message.length)
539
704
  cLogText.readOnly= true;
540
705
  cLog.appendChild(cLogText)
@@ -555,12 +720,6 @@ while(tblResult.firstChild) tblResult.removeChild(tblResult.firstChild)
555
720
 
556
721
  })
557
722
 
558
-
559
-
560
-
561
-
562
-
563
-
564
723
  //await populateMessages(allMessages)
565
724
 
566
725
 
@@ -693,8 +852,16 @@ function numberWithCommas(x) {
693
852
  let adminLog = new AdminLog(token, portal.serverUrl)
694
853
  tblResult.appendChild(prg);
695
854
  tblResult.appendChild(btn)
696
- const startTime = Date.now()
697
- const endTime = Date.now() - mins*60*1000
855
+ let startTime = Date.now()
856
+ const txtStartTime = document.getElementById("txtStartTime")
857
+ if (txtStartTime.value != "")
858
+ startTime = new Date(txtStartTime.value).getTime()
859
+
860
+ let endTime = startTime - mins*60*1000
861
+ const txtEndTime = document.getElementById("txtEndTime")
862
+ if (txtEndTime.value != "")
863
+ endTime = new Date(txtEndTime.value).getTime()
864
+
698
865
  let services = [theService + ".MapServer"]
699
866
  if (theService == "(All Services)")
700
867
  services = "*"
@@ -718,27 +885,8 @@ function numberWithCommas(x) {
718
885
  }
719
886
 
720
887
 
721
- /*
722
- const topLogCount = 100;f
723
- const startTime = Date.now()
724
- const endTime = Date.now() - mins*60*1000
725
- let services = [theService + ".MapServer"]
726
- if (theService == "(All Services)")
727
- services = "*"
728
- let result= await adminLog.query([code], services, topLogCount, startTime ,endTime , "DEBUG")
729
- let jsonRes = await result.json()
730
- let allMessages = [].concat(jsonRes.logMessages)
731
- allMessages = allMessages.filter(m => m.message.indexOf("EndCursor;") > -1)
732
- while (jsonRes.hasMore)
733
- {
734
- //start paging
735
- logger.info(`Aggregating messages... total so far ${allMessages.length} entries but more left, pulling logs between ${new Date(jsonRes.endTime)} and ${new Date(endTime)}`)
736
- result= await adminLog.query([102023], services, pageSize, jsonRes.endTime, endTime, "DEBUG")
737
- jsonRes = await result.json()
738
-
739
- allMessages = allMessages.concat(jsonRes.logMessages.filter(m => m.message.indexOf("EndCursor;") > -1))
740
- }
741
- */
888
+
889
+
742
890
  </script>
743
891
  </body>
744
892
  </html>
package/index.mjs CHANGED
@@ -7,7 +7,7 @@ import { AdminLog } from "./adminlog.mjs"
7
7
  import logger from "./logger.mjs"
8
8
  import fetch from "node-fetch"
9
9
  //update version
10
- let version = "0.0.73";
10
+ let version = "0.0.75";
11
11
  const GENERATE_TOKEN_TIME_MIN = 30;
12
12
 
13
13
  let rl = null;
@@ -86,7 +86,7 @@ async function regenerateToken(parameters) {
86
86
  async function connect(parameters) {
87
87
  try{
88
88
  //print the parameters
89
- logger.info(parameters);
89
+ logger.info(JSON.stringify(parameters));
90
90
  //connect to portal
91
91
 
92
92
  const token = await getToken(parameters);
@@ -175,6 +175,8 @@ const inputs = {
175
175
  "export subnetworks --all [--folder]": "Export all subnetworks with ACK --folder where exported files are saved",
176
176
  "export subnetworks --new [--folder]": "Export all subnetworks with ACK that haven't been exported --folder where exported files are saved",
177
177
  "export subnetworks --deleted": "Export all subnetworks with ACK that are deleted ",
178
+ "updateisconnected": "Run update is connected ",
179
+
178
180
  "count": "Lists the number of rows in all feature layers.",
179
181
  "count --system": "Lists the number of rows in system layers.",
180
182
  "connect --service": "Connects to the another service",
@@ -277,6 +279,16 @@ const inputs = {
277
279
  result.duration = numberWithCommas(Math.round(timeEnable)) + " ms"
278
280
  console.table(result)
279
281
  },
282
+
283
+ "^updateisconnected$": async () => {
284
+ const fromDate = new Date();
285
+ logger.info("Updating is connected ...");
286
+ const result = await un.updateIsConnected()
287
+ const toDate = new Date();
288
+ const timeEnable = toDate.getTime() - fromDate.getTime();
289
+ result.duration = numberWithCommas(Math.round(timeEnable)) + " ms"
290
+ console.table(result)
291
+ },
280
292
  "^evaluate$": async () => {
281
293
  const fromDate = new Date();
282
294
  logger.info("Building Evaluation Blocks ...");
@@ -304,10 +316,12 @@ const inputs = {
304
316
  //progress
305
317
  //timeouts
306
318
  //in case failure you don't lose everything
307
- "^topology --validate -fn$": async () => {
319
+ "^topology --validate --fishnet$": async () => {
308
320
  logger.info("Validating Network topology ...");
309
321
 
310
- const fullExtent = un.featureServiceJson.fullExtent;
322
+ const fullExtent = un.layerDefinition.extent;
323
+ //console.log(`add_env(${ JSON.stringify(fullExtent)})`)
324
+
311
325
  /*
312
326
  fullExtent.xmin = 0;
313
327
  fullExtent.xmax = 100;
@@ -316,13 +330,14 @@ const inputs = {
316
330
  https://desktop.arcgis.com/en/arcmap/10.3/tools/cartography-toolbox/create-cartographic-partitions.htm
317
331
  */
318
332
  //fish net
319
- const grids = 4;
333
+ const grids = 5; //divide the grid 5 x 5
320
334
  const dx = (fullExtent.xmax - fullExtent.xmin) / grids;
321
335
  const dy = (fullExtent.ymax - fullExtent.ymin) / grids;
322
-
323
- const extents = [];
336
+
337
+ const fishnet = [];
324
338
  for (let i =0; i < grids; i ++) {
325
-
339
+ const row = [];
340
+
326
341
  for (let j = 0; j < grids; j++) {
327
342
  const extent = {
328
343
  "xmin": fullExtent.xmin + j*dx,
@@ -331,24 +346,47 @@ const inputs = {
331
346
  "ymax": fullExtent.ymin + i*dy + dy,
332
347
  "spatialReference": fullExtent.spatialReference
333
348
  }
334
- extents.push(extent);
349
+ row.push({"content": " ", "extent": extent});
350
+
335
351
  }
352
+ fishnet.push(row);
336
353
  }
337
354
 
338
- extents.forEach(async e => {
339
- const fromDate = new Date();
340
355
 
341
- const result = await un.validateNetworkTopology("sde.DEFAULT", e)
342
- const toDate = new Date();
343
- const timeEnable = toDate.getTime() - fromDate.getTime();
344
- const duration = numberWithCommas(Math.round(timeEnable)) + " ms"
345
- console.clear()
346
- logger.info("Validating extent " + e.xmin)
347
- console.table({duration})
348
356
 
349
- })
350
-
351
-
357
+ for (let i = 0; i < fishnet.length; i ++) {
358
+
359
+ for (let j = 0 ; j < fishnet[i].length; j++) {
360
+
361
+ fishnet[i][j].content = '⚙️'
362
+ const e = fishnet[i][j].extent
363
+
364
+ try {
365
+
366
+
367
+ const fromDate = new Date();
368
+ console.log("Validating Extent " + JSON.stringify(e));
369
+ printFishnet(fishnet)
370
+
371
+ const result = await un.validateNetworkTopology( e)
372
+ const toDate = new Date();
373
+ const timeEnable = toDate.getTime() - fromDate.getTime();
374
+ const duration = numberWithCommas(Math.round(timeEnable)) + " ms"
375
+ result.duration = duration
376
+ console.table(result)
377
+ //console.log(`add_env(${ JSON.stringify(e)})`)
378
+ fishnet[i][j].content = '✔️'
379
+
380
+ }
381
+ catch(ex){
382
+ console.log(JSON.stringify(ex))
383
+ }
384
+
385
+ }
386
+
387
+ }
388
+ console.log("Done")
389
+
352
390
  },
353
391
 
354
392
  "^topology --validate$": async () => {
@@ -464,6 +502,8 @@ const inputs = {
464
502
  "^export subnetworks --all --folder .*$|^export subnetworks --all$" : async input => {
465
503
 
466
504
  let subnetworks
505
+ let sort = "asc";
506
+ if (input.indexOf("--desc") > 0) sort = "desc"
467
507
  //create folder
468
508
  const file = input.match(/--folder .*/gm)
469
509
  let inputDir = "Exported"
@@ -471,11 +511,17 @@ const inputs = {
471
511
  inputDir = file[0].replace("--folder ", "")
472
512
  //create directory if doesn't exists
473
513
  if (!fs.existsSync(inputDir)) fs.mkdirSync(inputDir)
474
-
514
+ let exportedSubnetworks = [];
515
+
475
516
  do {
476
517
 
518
+ let exportedSubnetworksWhereClause = ""
519
+
520
+ if (exportedSubnetworks.length > 0 )
521
+ exportedSubnetworksWhereClause = " AND SUBNETWORKNAME NOT IN (" + exportedSubnetworks.join(",") + ")"
522
+
477
523
  logger.info("Querying all subnetworks that are clean.");
478
- subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty=0","domainnetworkname,tiername,subnetworkname");
524
+ subnetworks = await un.queryDistinct(500002, "domainnetworkname,tiername,subnetworkname", "isdirty=0 " + exportedSubnetworksWhereClause,`domainnetworkname ${sort},tiername ${sort},subnetworkname ${sort}`);
479
525
  logger.info(`Discovered ${subnetworks.features.length} subnetworks that can be exported.`);
480
526
  for (let i = 0; i < subnetworks.features.length; i++) {
481
527
  const f = subnetworks.features[i]
@@ -485,10 +531,10 @@ const inputs = {
485
531
  const fromDate = new Date();
486
532
 
487
533
  const subnetworkResult = await un.exportSubnetworks(v(f.attributes,"domainNetworkName"), v(f.attributes,"tierName"), v(f.attributes,"subnetworkName"),false);
488
-
489
-
534
+
490
535
  //code
491
-
536
+ exportedSubnetworks.push("'" + v(f.attributes,"subnetworkName") + "'")
537
+
492
538
  const toDate = new Date();
493
539
  const timeEnable = toDate.getTime() - fromDate.getTime();
494
540
  subnetworkResult.duration = numberWithCommas(timeEnable) + " ms"
@@ -498,6 +544,7 @@ const inputs = {
498
544
  logger.info("Export subnetwork failed " + JSON.stringify(subnetworkResult))
499
545
  continue;
500
546
  }
547
+
501
548
 
502
549
  //fetch the json and write it to disk
503
550
  const subContent = await fetch(subnetworkResult.url);
@@ -512,7 +559,7 @@ const inputs = {
512
559
 
513
560
  }
514
561
  }
515
- while (subnetworks.features.length > 0)
562
+ while (subnetworks?.features?.length > 0)
516
563
 
517
564
  },
518
565
 
@@ -565,9 +612,13 @@ const inputs = {
565
612
  },
566
613
  "^trace --subnetwork": async input => {
567
614
  //get subnetwork name
615
+ try {
568
616
 
617
+
569
618
  const fromDate = new Date();
570
-
619
+ const inputDir= "Exported"
620
+ let full = true;
621
+ // if (input.indexOf("--full") > 0) full = true
571
622
 
572
623
  const inputParam = input.match(/--subnetwork .*/gm)
573
624
  let subnetworkName = null;
@@ -585,8 +636,44 @@ const inputs = {
585
636
  const newResult = {}
586
637
  newResult.duration = numberWithCommas(Math.round(timeRun)) + " ms"
587
638
  newResult.elementsCount = result.traceResults.elements.length;
588
- console.table(newResult)
639
+ const traceRes = {}
640
+ logger.info("Grouping trace results...")
641
+ result.traceResults.elements.forEach(e => {
642
+ const layerid = un.getLayerIdfromSourceId(e.networkSourceId).layerId
643
+ if (!traceRes["l" + layerid])
644
+ traceRes["l" + layerid] = []
645
+ traceRes["l" + layerid].push(e.objectId)
646
+
647
+ })
648
+ console.table(newResult)
589
649
 
650
+ //if the trace is full turn around the pull all features
651
+ if (full){
652
+
653
+ //loop through all layers and query
654
+ logger.info("Removing duplicates")
655
+
656
+ console.log(traceRes)
657
+
658
+ //send all queries async
659
+ const allQueries = []
660
+ Object.keys(traceRes).forEach (k => {
661
+ traceRes[k] = [...new Set(traceRes[k])]
662
+ allQueries.push(un.query(k.replace("l",""), "", k, traceRes[k]))
663
+ })
664
+ logger.info(`${Object.keys(traceRes)} queries sent, waiting for response..`)
665
+ const result = await Promise.all(allQueries)
666
+ logger.info("All queries returned.")
667
+ fs.writeFileSync(`${inputDir}/traceout${subnetworkName}.json`, JSON.stringify(result))
668
+ logger.info(`Result written to file ${inputDir}/traceout${subnetworkName}.json`)
669
+
670
+ //logger.info(JSON.stringify(result))
671
+
672
+ }
673
+ }
674
+ catch(ex){
675
+ logger.error(JSON.stringify(ex))
676
+ }
590
677
  },
591
678
  "^export subnetworks --deleted$" : async input => {
592
679
 
@@ -1346,3 +1433,27 @@ export async function run (){
1346
1433
 
1347
1434
 
1348
1435
 
1436
+ function printFishnet(fishnet) {
1437
+
1438
+ //y is flipped x is ok
1439
+ //i = 0 that is i = fishnet.length -1
1440
+ for (let i =0; i < fishnet.length ; i++){
1441
+
1442
+ for (let j = 0; j < fishnet[i].length;j++)
1443
+ process.stdout.write("+------");
1444
+
1445
+ process.stdout.write("+\n")
1446
+
1447
+ for (let j = 0; j < fishnet[i].length;j++)
1448
+ process.stdout.write(`| ${fishnet[fishnet.length - 1 - i][j].content} `);
1449
+
1450
+ process.stdout.write("|\n")
1451
+ }
1452
+
1453
+
1454
+ for (let j = 0; j < fishnet.length;j++)
1455
+ process.stdout.write("+------");
1456
+
1457
+ process.stdout.write("+\n\n")
1458
+
1459
+ }
package/makerequest.mjs CHANGED
@@ -28,25 +28,28 @@ export function makeRequest (opts) {
28
28
 
29
29
  let f;
30
30
  try {
31
- const nodeFetch = await import ("node-fetch");
31
+
32
+ let nodeFetch = await import ("node-fetch");
32
33
  f = nodeFetch.default;
33
34
  }
34
35
  catch(ex) {
35
36
  f = fetch;
36
37
  }
37
-
38
-
38
+
39
+ let jsonRes
40
+
39
41
  const result = await f(opts.url, {
40
42
  "method" : opts.method,
41
43
  "headers": headers,
42
44
  "body": params
43
45
  });
44
46
 
45
- const jsonRes = await result.json();
46
-
47
+ jsonRes = await result.json();
48
+
47
49
  if (typeof jsonRes !== "object")
48
50
  jsonRes = JSON.parse(jsonRes);
49
51
 
52
+
50
53
  resolve(jsonRes);
51
54
 
52
55
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "un-cli",
3
- "version": "0.0.73",
3
+ "version": "0.0.76",
4
4
  "description": "Command line interface for working with ArcGIS Utility Network Extension",
5
5
  "main": "index.mjs",
6
6
  "bin": {
package/un.mjs CHANGED
File without changes
@@ -21,12 +21,14 @@ export class UtilityNetwork {
21
21
  this.featureServiceUrl = featureServiceUrl;
22
22
  this.token = token;
23
23
  this.gdbVersion = gdbVersion;
24
+ this.sourceMapping = {}
24
25
  }
25
26
 
26
27
  ///first function one should call after creating an instance of a utility network
27
28
  load ()
28
29
  {
29
30
  let thisObj = this;
31
+
30
32
  return new Promise (function (resolve, reject)
31
33
  {
32
34
  //run async mode
@@ -68,7 +70,30 @@ export class UtilityNetwork {
68
70
 
69
71
  thisObj.dataElement = undataElement.layerDataElements[0].dataElement;
70
72
  thisObj.layerDefinition = unLayerDef
71
- thisObj.subnetLineLayerId = thisObj.getSubnetLineLayerId();
73
+ thisObj.subnetLineLayerId = thisObj.getSubnetLineLayerId();
74
+
75
+ //build out source mapping hash
76
+ let domainNetworks = thisObj.dataElement.domainNetworks;
77
+ let layerObj = undefined;
78
+
79
+ for (let i = 0; i < domainNetworks.length; i ++)
80
+ {
81
+ let domainNetwork = domainNetworks[i];
82
+ for (let j = 0; j < domainNetwork.junctionSources.length; j ++)
83
+ {
84
+ layerObj = {type: domainNetwork.junctionSources[j].shapeType, layerId: domainNetwork.junctionSources[j].layerId}
85
+ layerObj.type = layerObj.type.replace("esriGeometry", "").toLowerCase();
86
+ thisObj.sourceMapping["s" + domainNetwork.junctionSources[j].sourceId] = layerObj
87
+ }
88
+
89
+ for (let j = 0; j < domainNetwork.edgeSources.length; j ++)
90
+ {
91
+ layerObj = {type: domainNetwork.edgeSources[j].shapeType, layerId: domainNetwork.edgeSources[j].layerId}
92
+ layerObj.type = layerObj.type.replace("esriGeometry", "").toLowerCase();
93
+ thisObj.sourceMapping["s" + domainNetwork.edgeSources[j].sourceId] = layerObj
94
+ }
95
+ }
96
+
72
97
  resolve(thisObj);
73
98
  }
74
99
  else
@@ -333,16 +358,49 @@ export class UtilityNetwork {
333
358
  if (objectids != undefined)
334
359
  queryJson.objectIds = objectids;
335
360
  queryJson.layerId = layerId
336
- return new Promise((resolve, reject) => {
361
+ return new Promise(async(resolve, reject) => {
362
+
363
+
364
+
365
+ let rowsJson;
366
+ let allRowsJson;
367
+ let recordOffset = 0;
368
+
369
+ try {
370
+
371
+ do {
372
+ queryJson.resultOffset = recordOffset;
373
+ rowsJson = await makeRequest({method: 'POST', params: queryJson, url: this.featureServiceUrl + "/" + layerId + "/query"}) ;
374
+ recordOffset = recordOffset + resultRecordCount + 1;
375
+ rowsJson.obj = obj;
376
+
377
+ if (!allRowsJson)
378
+ allRowsJson = rowsJson
379
+ else
380
+ allRowsJson?.features.push(...rowsJson?.features)
381
+ //page the result until done
382
+ }
383
+ while(rowsJson?.exceededTransferLimit == true)
384
+
385
+ resolve(allRowsJson);
386
+ }
387
+ catch(ex){
388
+ reject("failed to query" + JSON.stringify(ex))
389
+ }
337
390
 
338
- makeRequest({method: 'POST', params: queryJson, url: this.featureServiceUrl + "/" + layerId + "/query"}).then(rowsJson=> {
339
- rowsJson.obj = obj;
340
- resolve(rowsJson);
341
- }).catch(rej => reject("failed to query"));
342
391
 
392
+
393
+
343
394
  });
344
395
 
345
-
396
+
397
+
398
+ // }
399
+ // while(jsonRes?.exceededTransferLimit == true)
400
+ // if (!allJsonRes)
401
+ // allJsonRes = jsonRes
402
+ // else
403
+ // allJsonRes?.features.push(...jsonRes?.features)
346
404
  }
347
405
  //get the terminal configuration using the id
348
406
  getTerminalConfiguration(terminalConfigurationId)
@@ -538,8 +596,10 @@ export class UtilityNetwork {
538
596
  //get layer id from Source Id used to map sourceid to layer id
539
597
  getLayerIdfromSourceId(sourceId)
540
598
  {
599
+
600
+ return this.sourceMapping["s" + sourceId]
601
+ /*
541
602
  let domainNetworks = this.dataElement.domainNetworks;
542
- let layerObj = undefined;
543
603
 
544
604
  for (let i = 0; i < domainNetworks.length; i ++)
545
605
  {
@@ -561,6 +621,7 @@ export class UtilityNetwork {
561
621
 
562
622
  if (layerObj != undefined)
563
623
  layerObj.type = layerObj.type.replace("esriGeometry", "").toLowerCase();
624
+ */
564
625
 
565
626
  return layerObj;
566
627
  }
@@ -958,6 +1019,27 @@ export class UtilityNetwork {
958
1019
 
959
1020
 
960
1021
 
1022
+ updateIsConnected(async=false) {
1023
+
1024
+ let thisObj = this;
1025
+ let ar = thisObj.featureServiceUrl.split("/");
1026
+ ar[ar.length-1]="UtilityNetworkServer";
1027
+ let updateisconnectedURL = ar.join("/") + "/updateIsConnected"
1028
+
1029
+ let payload = {
1030
+ f: "json",
1031
+ token: this.token,
1032
+ async: async
1033
+ }
1034
+ let un = this;
1035
+
1036
+ return makeRequest({method:'POST', params: payload, url: updateisconnectedURL })
1037
+
1038
+
1039
+
1040
+ }
1041
+
1042
+
961
1043
  updateSubnetworks(domainNetworkName, tierName, subnetworkName, async=false) {
962
1044
 
963
1045
  let thisObj = this;