@rockcarver/frodo-lib 0.12.1 → 0.12.2-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/CHANGELOG.md +5 -1
  2. package/cjs/api/BaseApi.js +36 -8
  3. package/cjs/api/BaseApi.js.map +1 -1
  4. package/cjs/api/NodeApi.js +190 -0
  5. package/cjs/api/NodeApi.js.map +1 -0
  6. package/cjs/api/NodeApi.test.js.map +1 -0
  7. package/cjs/api/StartupApi.js +21 -8
  8. package/cjs/api/StartupApi.js.map +1 -1
  9. package/cjs/api/StartupApi.test.js.map +1 -0
  10. package/cjs/api/TreeApi.js +28 -161
  11. package/cjs/api/TreeApi.js.map +1 -1
  12. package/cjs/api/TreeApi.test.js.map +1 -0
  13. package/cjs/index.js +15 -5
  14. package/cjs/index.js.map +1 -1
  15. package/cjs/ops/IdpOps.js +1 -1
  16. package/cjs/ops/IdpOps.js.map +1 -1
  17. package/cjs/ops/JourneyOps.js +202 -203
  18. package/cjs/ops/JourneyOps.js.map +1 -1
  19. package/cjs/ops/StartupOps.js +61 -71
  20. package/cjs/ops/StartupOps.js.map +1 -1
  21. package/cjs/ops/utils/Console.js +3 -2
  22. package/cjs/ops/utils/Console.js.map +1 -1
  23. package/esm/api/BaseApi.mjs +35 -7
  24. package/esm/api/NodeApi.mjs +114 -0
  25. package/esm/api/NodeApi.test.mjs +105 -0
  26. package/esm/api/StartupApi.mjs +18 -8
  27. package/esm/api/StartupApi.test.mjs +56 -0
  28. package/esm/api/TreeApi.mjs +27 -99
  29. package/esm/api/TreeApi.test.mjs +175 -0
  30. package/esm/index.mjs +7 -5
  31. package/esm/ops/IdpOps.mjs +1 -1
  32. package/esm/ops/JourneyOps.mjs +165 -154
  33. package/esm/ops/StartupOps.mjs +59 -62
  34. package/esm/ops/utils/Console.mjs +3 -2
  35. package/package.json +7 -4
  36. package/types/api/AuthenticateApi.d.ts +2 -0
  37. package/types/api/AuthenticateApi.d.ts.map +1 -0
  38. package/types/api/BaseApi.d.ts +50 -0
  39. package/types/api/BaseApi.d.ts.map +1 -0
  40. package/types/api/CirclesOfTrustApi.d.ts +24 -0
  41. package/types/api/CirclesOfTrustApi.d.ts.map +1 -0
  42. package/types/api/EmailTemplateApi.d.ts +22 -0
  43. package/types/api/EmailTemplateApi.d.ts.map +1 -0
  44. package/types/api/IdmConfigApi.d.ts +39 -0
  45. package/types/api/IdmConfigApi.d.ts.map +1 -0
  46. package/types/api/LogApi.d.ts +4 -0
  47. package/types/api/LogApi.d.ts.map +1 -0
  48. package/types/api/ManagedObjectApi.d.ts +21 -0
  49. package/types/api/ManagedObjectApi.d.ts.map +1 -0
  50. package/types/api/NodeApi.d.ts +38 -0
  51. package/types/api/NodeApi.d.ts.map +1 -0
  52. package/types/api/OAuth2ClientApi.d.ts +18 -0
  53. package/types/api/OAuth2ClientApi.d.ts.map +1 -0
  54. package/types/api/OAuth2OIDCApi.d.ts +22 -0
  55. package/types/api/OAuth2OIDCApi.d.ts.map +1 -0
  56. package/types/api/OAuth2ProviderApi.d.ts +5 -0
  57. package/types/api/OAuth2ProviderApi.d.ts.map +1 -0
  58. package/types/api/RealmApi.d.ts +30 -0
  59. package/types/api/RealmApi.d.ts.map +1 -0
  60. package/types/api/Saml2Api.d.ts +52 -0
  61. package/types/api/Saml2Api.d.ts.map +1 -0
  62. package/types/api/ScriptApi.d.ts +24 -0
  63. package/types/api/ScriptApi.d.ts.map +1 -0
  64. package/types/api/SecretsApi.d.ts +10 -0
  65. package/types/api/SecretsApi.d.ts.map +1 -0
  66. package/types/api/ServerInfoApi.d.ts +10 -0
  67. package/types/api/ServerInfoApi.d.ts.map +1 -0
  68. package/types/api/SocialIdentityProvidersApi.d.ts +31 -0
  69. package/types/api/SocialIdentityProvidersApi.d.ts.map +1 -0
  70. package/types/api/StartupApi.d.ts +14 -0
  71. package/types/api/StartupApi.d.ts.map +1 -0
  72. package/types/api/ThemeApi.d.ts +54 -0
  73. package/types/api/ThemeApi.d.ts.map +1 -0
  74. package/types/api/TreeApi.d.ts +24 -0
  75. package/types/api/TreeApi.d.ts.map +1 -0
  76. package/types/api/VariablesApi.d.ts +32 -0
  77. package/types/api/VariablesApi.d.ts.map +1 -0
  78. package/types/api/utils/ApiUtils.d.ts +29 -0
  79. package/types/api/utils/ApiUtils.d.ts.map +1 -0
  80. package/types/api/utils/Base64.d.ts +30 -0
  81. package/types/api/utils/Base64.d.ts.map +1 -0
  82. package/types/index.d.ts +26 -0
  83. package/types/index.d.ts.map +1 -0
  84. package/types/ops/AdminOps.d.ts +11 -0
  85. package/types/ops/AdminOps.d.ts.map +1 -0
  86. package/types/ops/AuthenticateOps.d.ts +6 -0
  87. package/types/ops/AuthenticateOps.d.ts.map +1 -0
  88. package/types/ops/CirclesOfTrustOps.d.ts +40 -0
  89. package/types/ops/CirclesOfTrustOps.d.ts.map +1 -0
  90. package/types/ops/ConnectionProfileOps.d.ts +47 -0
  91. package/types/ops/ConnectionProfileOps.d.ts.map +1 -0
  92. package/types/ops/EmailTemplateOps.d.ts +40 -0
  93. package/types/ops/EmailTemplateOps.d.ts.map +1 -0
  94. package/types/ops/IdmOps.d.ts +27 -0
  95. package/types/ops/IdmOps.d.ts.map +1 -0
  96. package/types/ops/IdpOps.d.ts +45 -0
  97. package/types/ops/IdpOps.d.ts.map +1 -0
  98. package/types/ops/JourneyOps.d.ts +145 -0
  99. package/types/ops/JourneyOps.d.ts.map +1 -0
  100. package/types/ops/LogOps.d.ts +5 -0
  101. package/types/ops/LogOps.d.ts.map +1 -0
  102. package/types/ops/ManagedObjectOps.d.ts +14 -0
  103. package/types/ops/ManagedObjectOps.d.ts.map +1 -0
  104. package/types/ops/OAuth2ClientOps.d.ts +24 -0
  105. package/types/ops/OAuth2ClientOps.d.ts.map +1 -0
  106. package/types/ops/OrganizationOps.d.ts +11 -0
  107. package/types/ops/OrganizationOps.d.ts.map +1 -0
  108. package/types/ops/RealmOps.d.ts +22 -0
  109. package/types/ops/RealmOps.d.ts.map +1 -0
  110. package/types/ops/SamlOps.d.ts +51 -0
  111. package/types/ops/SamlOps.d.ts.map +1 -0
  112. package/types/ops/ScriptOps.d.ts +30 -0
  113. package/types/ops/ScriptOps.d.ts.map +1 -0
  114. package/types/ops/SecretsOps.d.ts +63 -0
  115. package/types/ops/SecretsOps.d.ts.map +1 -0
  116. package/types/ops/StartupOps.d.ts +25 -0
  117. package/types/ops/StartupOps.d.ts.map +1 -0
  118. package/types/ops/ThemeOps.d.ts +66 -0
  119. package/types/ops/ThemeOps.d.ts.map +1 -0
  120. package/types/ops/VariablesOps.d.ts +39 -0
  121. package/types/ops/VariablesOps.d.ts.map +1 -0
  122. package/types/ops/utils/Console.d.ts +63 -0
  123. package/types/ops/utils/Console.d.ts.map +1 -0
  124. package/types/ops/utils/DataProtection.d.ts +6 -0
  125. package/types/ops/utils/DataProtection.d.ts.map +1 -0
  126. package/types/ops/utils/ExportImportUtils.d.ts +22 -0
  127. package/types/ops/utils/ExportImportUtils.d.ts.map +1 -0
  128. package/types/ops/utils/OpsUtils.d.ts +27 -0
  129. package/types/ops/utils/OpsUtils.d.ts.map +1 -0
  130. package/types/ops/utils/Wordwrap.d.ts +1 -0
  131. package/types/ops/utils/Wordwrap.d.ts.map +1 -0
  132. package/types/storage/SessionStorage.d.ts +47 -0
  133. package/types/storage/SessionStorage.d.ts.map +1 -0
  134. package/types/storage/StaticStorage.d.ts +14 -0
  135. package/types/storage/StaticStorage.d.ts.map +1 -0
@@ -1,12 +1,11 @@
1
- /* eslint-disable no-param-reassign */
2
1
  import fs from 'fs';
3
- import yesno from 'yesno';
4
2
  import { v4 as uuidv4 } from 'uuid';
5
3
  import _ from 'lodash';
6
4
  import { convertBase64TextToArray, getTypedFilename, saveJsonToFile, getRealmString, convertTextArrayToBase64, convertTextArrayToBase64Url } from './utils/ExportImportUtils';
7
5
  import { getRealmManagedUser, replaceAll } from './utils/OpsUtils';
8
6
  import storage from '../storage/SessionStorage';
9
- import { getNode, putNode, deleteNode, getTrees, getTree, putTree, getNodeTypes, getNodesByType, deleteTree } from '../api/TreeApi';
7
+ import { getNode, putNode, deleteNode, getNodeTypes, getNodesByType } from '../api/NodeApi';
8
+ import { getTrees, getTree, putTree, deleteTree } from '../api/TreeApi';
10
9
  import { getEmailTemplate, putEmailTemplate } from '../api/EmailTemplateApi';
11
10
  import { getScript } from '../api/ScriptApi';
12
11
  import * as global from '../storage/StaticStorage';
@@ -21,9 +20,10 @@ import { createOrUpdateScript } from './ScriptOps';
21
20
  const containerNodes = ['PageNode', 'CustomPageNode'];
22
21
  const scriptedNodes = ['ConfigProviderNode', 'ScriptedDecisionNode', 'ClientScriptNode', 'SocialProviderHandlerNode', 'CustomScriptNode'];
23
22
  const emailTemplateNodes = ['EmailSuspendNode', 'EmailTemplateNode'];
24
- const emptyScriptPlaceholder = '[Empty]'; // use a function vs a template variable to avoid problems in loops
23
+ const emptyScriptPlaceholder = '[Empty]';
25
24
 
26
- function getSingleTreeFileDataTemplate() {
25
+ // use a function vs a template variable to avoid problems in loops
26
+ function createSingleTreeExportTemplate() {
27
27
  return {
28
28
  meta: {},
29
29
  innerNodes: {},
@@ -36,10 +36,10 @@ function getSingleTreeFileDataTemplate() {
36
36
  circlesOfTrust: {},
37
37
  tree: {}
38
38
  };
39
- } // use a function vs a template variable to avoid problems in loops
40
-
39
+ }
41
40
 
42
- function getMultipleTreesFileDataTemplate() {
41
+ // use a function vs a template variable to avoid problems in loops
42
+ function createMultipleTreesExportTemplate() {
43
43
  return {
44
44
  meta: {},
45
45
  trees: {}
@@ -113,18 +113,39 @@ async function getSaml2NodeDependencies(nodeObject, allProviders, allCirclesOfTr
113
113
  };
114
114
  return saml2NodeDependencies;
115
115
  });
116
- }
116
+ } // export async function getTreeNodes(treeObject) {
117
+ // const nodeList = Object.entries(treeObject.nodes);
118
+ // const results = await Promise.allSettled(
119
+ // nodeList.map(
120
+ // async ([nodeId, nodeInfo]) => await getNode(nodeId, nodeInfo['nodeType'])
121
+ // )
122
+ // );
123
+ // const nodes = results.filter((r) => r.status === 'fulfilled');
124
+ // nodes.map((f) => {
125
+ // return f.status;
126
+ // });
127
+ // const failedList = results.filter((r) => r.status === 'rejected');
128
+ // return nodes;
129
+ // }
130
+
117
131
  /**
118
- * Helper method to create export data for a tree with all its
119
- * dependencies. The export data can be written to a file as is
120
- * (but it doesn't contain meta data).
121
- * @param {Object} treeObject tree object
122
- * @param {Object} exportData export data
123
- * @param {Object} options options object
132
+ * Export options
124
133
  */
125
134
 
126
135
 
127
- async function exportTree(treeObject, exportData, options) {
136
+ /**
137
+ * Create export data for a tree with all its nodes and dependencies. The export data can be written to a file as is.
138
+ * @param {string} treeId tree id/name
139
+ * @param {ExportOptions} options export options
140
+ * @returns {Promise<SingleTreeExportTemplate>} a promise that resolves to an object containing the tree and all its nodes and dependencies
141
+ */
142
+ export async function exportTree(treeId, options = {
143
+ useStringArrays: true,
144
+ deps: true,
145
+ verbose: false
146
+ }) {
147
+ const treeObject = await getTree(treeId);
148
+ const exportData = createSingleTreeExportTemplate();
128
149
  const {
129
150
  useStringArrays,
130
151
  deps,
@@ -151,7 +172,7 @@ async function exportTree(treeObject, exportData, options) {
151
172
  const themes = []; // get all the nodes
152
173
 
153
174
  for (const [nodeId, nodeInfo] of Object.entries(treeObject.nodes)) {
154
- nodePromises.push(getNode(nodeId, nodeInfo['nodeType']).then(response => response.data));
175
+ nodePromises.push(getNode(nodeId, nodeInfo['nodeType']));
155
176
  }
156
177
 
157
178
  if (verbose && nodePromises.length > 0) printMessage(' - Nodes:');
@@ -216,7 +237,7 @@ async function exportTree(treeObject, exportData, options) {
216
237
 
217
238
  if (containerNodes.includes(nodeType)) {
218
239
  for (const innerNode of nodeObject.nodes) {
219
- innerNodePromises.push(getNode(innerNode._id, innerNode.nodeType).then(response => response.data));
240
+ innerNodePromises.push(getNode(innerNode._id, innerNode.nodeType));
220
241
  } // frodo supports themes in platform deployments
221
242
 
222
243
 
@@ -375,15 +396,16 @@ async function exportTree(treeObject, exportData, options) {
375
396
  });
376
397
  });
377
398
  }
399
+
400
+ return exportData;
378
401
  }
379
402
  /**
380
403
  * Export journey by id/name to file
381
- * @param {String} journeyId journey id/name
382
- * @param {String} file optional export file name
383
- * @param {Object} options reUuid:boolean: re-uuid all node objects, verbose:boolean: verbose output, deps:boolean: include dependencies
404
+ * @param {string} journeyId journey id/name
405
+ * @param {string} file optional export file name
406
+ * @param {ExportOptions} options export options
384
407
  */
385
408
 
386
-
387
409
  export async function exportJourneyToFile(journeyId, file, options) {
388
410
  const {
389
411
  verbose
@@ -395,26 +417,21 @@ export async function exportJourneyToFile(journeyId, file, options) {
395
417
  }
396
418
 
397
419
  if (!verbose) createProgressIndicator(undefined, `${journeyId}`, 'indeterminate');
398
- await getTree(journeyId).then(async response => {
399
- const treeData = response.data;
400
- const fileData = getSingleTreeFileDataTemplate();
401
420
 
402
- try {
403
- await exportTree(treeData, fileData, options);
404
- if (verbose) createProgressIndicator(undefined, `${journeyId}`, 'indeterminate');
405
- saveJsonToFile(fileData, fileName);
406
- stopProgressIndicator(`Exported ${journeyId.brightCyan} to ${fileName.brightCyan}.`, 'success');
407
- } catch (error) {
408
- if (verbose) createProgressIndicator(undefined, `${journeyId}`, 'indeterminate');
409
- stopProgressIndicator(`Error exporting journey ${journeyId}: ${error}`, 'fail');
410
- }
411
- }).catch(err => {
412
- stopProgressIndicator(err.message, 'fail');
413
- });
421
+ try {
422
+ const fileData = await exportTree(journeyId, options);
423
+ if (verbose) createProgressIndicator(undefined, `${journeyId}`, 'indeterminate');
424
+ saveJsonToFile(fileData, fileName);
425
+ stopProgressIndicator(`Exported ${journeyId['brightCyan']} to ${fileName['brightCyan']}.`, 'success');
426
+ } catch (error) {
427
+ if (verbose) createProgressIndicator(undefined, `${journeyId}`, 'indeterminate');
428
+ stopProgressIndicator(`Error exporting journey ${journeyId}: ${error}`, 'fail');
429
+ }
414
430
  }
415
431
  /**
416
432
  * Export all journeys to file
417
- * @param {String} file optional export file name
433
+ * @param {string} file optional export file name
434
+ * @param {ExportOptions} options export options
418
435
  */
419
436
 
420
437
  export async function exportJourneysToFile(file, options) {
@@ -424,20 +441,16 @@ export async function exportJourneysToFile(file, options) {
424
441
  fileName = getTypedFilename(`all${getRealmString()}Journeys`, 'journeys');
425
442
  }
426
443
 
427
- const trees = (await getTrees()).data.result;
428
- const fileData = getMultipleTreesFileDataTemplate();
444
+ const trees = await getTrees();
445
+ const fileData = createMultipleTreesExportTemplate();
429
446
  createProgressIndicator(trees.length, 'Exporting journeys...');
430
447
 
431
448
  for (const tree of trees) {
432
449
  updateProgressIndicator(`${tree._id}`);
433
450
 
434
451
  try {
435
- // eslint-disable-next-line no-await-in-loop
436
- const treeData = (await getTree(tree._id)).data;
437
- const exportData = getSingleTreeFileDataTemplate();
438
- delete exportData.meta; // eslint-disable-next-line no-await-in-loop
439
-
440
- await exportTree(treeData, exportData, options);
452
+ const exportData = await exportTree(tree._id, options);
453
+ delete exportData.meta;
441
454
  fileData.trees[tree._id] = exportData;
442
455
  } catch (error) {
443
456
  printMessage(`Error exporting journey ${tree._id}: ${error}`, 'error');
@@ -449,59 +462,39 @@ export async function exportJourneysToFile(file, options) {
449
462
  }
450
463
  /**
451
464
  * Export all journeys to separate files
465
+ * @param {ExportOptions} options export options
452
466
  */
453
467
 
454
468
  export async function exportJourneysToFiles(options) {
455
- const trees = (await getTrees()).data.result;
469
+ const trees = await getTrees();
456
470
  createProgressIndicator(trees.length, 'Exporting journeys...');
457
471
 
458
472
  for (const tree of trees) {
459
473
  updateProgressIndicator(`${tree._id}`);
460
- const fileName = getTypedFilename(`${tree._id}`, 'journey'); // eslint-disable-next-line no-await-in-loop
474
+ const fileName = getTypedFilename(`${tree._id}`, 'journey');
461
475
 
462
- const treeData = (await getTree(tree._id)).data;
463
- const exportData = getSingleTreeFileDataTemplate(); // eslint-disable-next-line no-await-in-loop
464
-
465
- await exportTree(treeData, exportData, options);
466
- saveJsonToFile(exportData, fileName);
476
+ try {
477
+ const exportData = await exportTree(tree._id, options);
478
+ saveJsonToFile(exportData, fileName);
479
+ } catch (error) {// do we need to report status here?
480
+ }
467
481
  }
468
482
 
469
483
  stopProgressIndicator('Done');
470
484
  }
471
485
  /**
472
- * Get data for journey by id/name
473
- * @param {String} journeyId journey id/name
474
- * @returns {Object} object containing all journey data
486
+ * Import options
475
487
  */
476
488
 
477
- export async function getJourneyData(journeyId) {
478
- createProgressIndicator(undefined, `${journeyId}`, 'indeterminate');
479
- const journeyData = getSingleTreeFileDataTemplate();
480
- const treeData = (await getTree(journeyId).catch(err => {
481
- stopProgressIndicator(null, 'success');
482
- printMessage(err, 'error');
483
- }))['data'];
484
- updateProgressIndicator();
485
- await exportTree(treeData, journeyData, {
486
- useStringArrays: true
487
- });
488
- stopProgressIndicator(null, 'success');
489
- return journeyData;
490
- }
491
489
  /**
492
490
  * Helper to import a tree with all dependencies from an import data object (typically read from a file)
493
- * @param {Object} treeObject tree object containing tree and all its dependencies
494
- * @param {Object} options reUuid:boolean: re-uuid all node objects, verbose:boolean: verbose output
491
+ * @param {SingleTreeExportTemplate} treeObject tree object containing tree and all its dependencies
492
+ * @param {ImportOptions} options import options
495
493
  */
496
-
497
- async function importTree(treeObject, options) {
498
- const {
499
- reUuid
500
- } = options;
501
- const {
502
- deps
503
- } = options;
494
+ export async function importTree(treeObject, options) {
504
495
  const {
496
+ reUuid,
497
+ deps,
505
498
  verbose
506
499
  } = options;
507
500
  if (verbose) printMessage(`\n- ${treeObject.tree._id}\n`, 'info', false);
@@ -555,8 +548,8 @@ async function importTree(treeObject, options) {
555
548
  const themes = {};
556
549
 
557
550
  for (const theme of treeObject.themes) {
558
- if (verbose) printMessage(` - ${theme._id} (${theme.name})`, 'info');
559
- themes[theme._id] = theme;
551
+ if (verbose) printMessage(` - ${theme['_id']} (${theme['name']})`, 'info');
552
+ themes[theme['_id']] = theme;
560
553
  }
561
554
 
562
555
  try {
@@ -775,7 +768,7 @@ async function importTree(treeObject, options) {
775
768
  // Set the identityResource for the tree to the selected resource.
776
769
 
777
770
 
778
- if (treeObject.tree.identityResource && treeObject.tree.identityResource.endsWith('user')) {
771
+ if (treeObject.tree.identityResource && treeObject.tree['identityResource'].endsWith('user')) {
779
772
  treeObject.tree.identityResource = `managed/${getRealmManagedUser()}`;
780
773
  if (verbose) printMessage(` - identityResource: ${treeObject.tree.identityResource}`, 'info', false);
781
774
  }
@@ -820,7 +813,6 @@ async function importTree(treeObject, options) {
820
813
  * @param {int} index Depth of recursion
821
814
  */
822
815
 
823
-
824
816
  async function resolveDependencies(installedJorneys, journeyMap, unresolvedJourneys, resolvedJourneys, index = -1) {
825
817
  let before = -1;
826
818
  let after = index;
@@ -877,9 +869,9 @@ async function resolveDependencies(installedJorneys, journeyMap, unresolvedJourn
877
869
  }
878
870
  /**
879
871
  * Import a journey from file
880
- * @param {String} journeyId journey id/name
881
- * @param {String} file import file name
882
- * @param {boolean} options reUuid:boolean: re-uuid all node objects, verbose:boolean: verbose output
872
+ * @param {string} journeyId journey id/name
873
+ * @param {string} file import file name
874
+ * @param {ImportOptions} options import options
883
875
  */
884
876
 
885
877
 
@@ -900,7 +892,7 @@ export async function importJourneyFromFile(journeyId, file, options) {
900
892
 
901
893
  if (journeyData && journeyId === journeyData.tree._id) {
902
894
  // attempt dependency resolution for single tree import
903
- const installedJourneys = (await getTrees()).data.result.map(x => x._id);
895
+ const installedJourneys = (await getTrees()).map(x => x._id);
904
896
  const unresolvedJourneys = {};
905
897
  const resolvedJourneys = [];
906
898
  createProgressIndicator(undefined, 'Resolving dependencies', 'indeterminate');
@@ -934,8 +926,8 @@ export async function importJourneyFromFile(journeyId, file, options) {
934
926
  }
935
927
  /**
936
928
  * Import first journey from file
937
- * @param {String} file import file name
938
- * @param {boolean} options reUuid:boolean: re-uuid all node objects, verbose:boolean: verbose output
929
+ * @param {string} file import file name
930
+ * @param {ImportOptions} options import options
939
931
  */
940
932
 
941
933
  export async function importFirstJourneyFromFile(file, options) {
@@ -965,7 +957,7 @@ export async function importFirstJourneyFromFile(file, options) {
965
957
 
966
958
  if (journeyData && journeyId) {
967
959
  // attempt dependency resolution for single tree import
968
- const installedJourneys = (await getTrees()).data.result.map(x => x._id);
960
+ const installedJourneys = (await getTrees()).map(x => x._id);
969
961
  const unresolvedJourneys = {};
970
962
  const resolvedJourneys = [];
971
963
  createProgressIndicator(undefined, 'Resolving dependencies', 'indeterminate');
@@ -1000,11 +992,11 @@ export async function importFirstJourneyFromFile(file, options) {
1000
992
  /**
1001
993
  * Helper to import multiple trees from a tree map
1002
994
  * @param {Object} treesMap map of trees object
1003
- * @param {boolean} options reUuid:boolean: re-uuid all node objects, verbose:boolean: verbose output
995
+ * @param {ImportOptions} options import options
1004
996
  */
1005
997
 
1006
998
  async function importAllTrees(treesMap, options) {
1007
- const installedJourneys = (await getTrees()).data.result.map(x => x._id);
999
+ const installedJourneys = (await getTrees()).map(x => x._id);
1008
1000
  const unresolvedJourneys = {};
1009
1001
  const resolvedJourneys = [];
1010
1002
  createProgressIndicator(undefined, 'Resolving dependencies', 'indeterminate');
@@ -1036,8 +1028,8 @@ async function importAllTrees(treesMap, options) {
1036
1028
  }
1037
1029
  /**
1038
1030
  * Import all journeys from file
1039
- * @param {*} file import file name
1040
- * @param {boolean} options reUuid:boolean: re-uuid all node objects, verbose:boolean: verbose output
1031
+ * @param {string} file import file name
1032
+ * @param {ImportOptions} options import options
1041
1033
  */
1042
1034
 
1043
1035
 
@@ -1050,7 +1042,7 @@ export async function importJourneysFromFile(file, options) {
1050
1042
  }
1051
1043
  /**
1052
1044
  * Import all journeys from separate files
1053
- * @param {boolean} options reUuid:boolean: re-uuid all node objects, verbose:boolean: verbose output
1045
+ * @param {ImportOptions} options import options
1054
1046
  */
1055
1047
 
1056
1048
  export async function importJourneysFromFiles(options) {
@@ -1107,23 +1099,50 @@ export function describeTree(treeData) {
1107
1099
  treeMap['nodeTypes'] = nodeTypeMap;
1108
1100
  treeMap['scripts'] = scriptsMap;
1109
1101
  treeMap['emailTemplates'] = emailTemplatesMap;
1102
+ printMessage(`\nJourney: ${treeMap['treeName']}`, 'data');
1103
+ printMessage('========');
1104
+ printMessage('\nNodes:', 'data');
1105
+
1106
+ if (Object.entries(treeMap['nodeTypes']).length) {
1107
+ for (const [name, count] of Object.entries(treeMap['nodeTypes'])) {
1108
+ printMessage(`- ${name}: ${count}`, 'data');
1109
+ }
1110
+ }
1111
+
1112
+ if (Object.entries(treeMap['scripts']).length) {
1113
+ printMessage('\nScripts:', 'data');
1114
+
1115
+ for (const [name, desc] of Object.entries(treeMap['scripts'])) {
1116
+ printMessage(`- ${name}: ${desc}`, 'data');
1117
+ }
1118
+ }
1119
+
1120
+ if (Object.entries(treeMap['emailTemplates']).length) {
1121
+ printMessage('\nEmail Templates:', 'data');
1122
+
1123
+ for (const [id] of Object.entries(treeMap['emailTemplates'])) {
1124
+ printMessage(`- ${id}`, 'data');
1125
+ }
1126
+ }
1127
+
1110
1128
  return treeMap;
1111
1129
  }
1112
1130
  /**
1113
1131
  * Find all node configuration objects that are no longer referenced by any tree
1132
+ * @returns {Promise<unknown[]>} a promise that resolves to an array of orphaned nodes
1114
1133
  */
1115
1134
 
1116
- async function findOrphanedNodes() {
1135
+ export async function findOrphanedNodes() {
1117
1136
  const allNodes = [];
1118
1137
  const orphanedNodes = [];
1119
1138
  let types = [];
1120
- const allJourneys = (await getTrees()).data.result;
1139
+ const allJourneys = await getTrees();
1121
1140
  let errorMessage = '';
1122
1141
  const errorTypes = [];
1123
1142
  createProgressIndicator(undefined, `Counting total nodes...`, 'indeterminate');
1124
1143
 
1125
1144
  try {
1126
- types = (await getNodeTypes()).data.result;
1145
+ types = await getNodeTypes();
1127
1146
  } catch (error) {
1128
1147
  printMessage('Error retrieving all available node types:', 'error');
1129
1148
  printMessage(error.response.data, 'error');
@@ -1133,7 +1152,7 @@ async function findOrphanedNodes() {
1133
1152
  for (const type of types) {
1134
1153
  try {
1135
1154
  // eslint-disable-next-line no-await-in-loop, no-loop-func
1136
- (await getNodesByType(type._id)).data.result.forEach(node => {
1155
+ (await getNodesByType(type._id)).forEach(node => {
1137
1156
  allNodes.push(node);
1138
1157
  updateProgressIndicator(`${allNodes.length} total nodes${errorMessage}`);
1139
1158
  });
@@ -1162,7 +1181,7 @@ async function findOrphanedNodes() {
1162
1181
 
1163
1182
  if (containerNodes.includes(node.nodeType)) {
1164
1183
  // eslint-disable-next-line no-await-in-loop
1165
- const containerNode = (await getNode(nodeId, node.nodeType)).data;
1184
+ const containerNode = await getNode(nodeId, node.nodeType);
1166
1185
  containerNode.nodes.forEach(n => {
1167
1186
  activeNodes.push(n._id);
1168
1187
  updateProgressIndicator(`${activeNodes.length} active nodes`);
@@ -1182,41 +1201,27 @@ async function findOrphanedNodes() {
1182
1201
  /**
1183
1202
  * Remove orphaned nodes
1184
1203
  * @param {[Object]} orphanedNodes Pass in an array of orphaned node configuration objects to remove
1204
+ * @returns {Promise<unknown[]>} a promise that resolves to an array nodes that encountered errors deleting
1185
1205
  */
1186
1206
 
1187
-
1188
- async function removeOrphanedNodes(orphanedNodes) {
1207
+ export async function removeOrphanedNodes(orphanedNodes) {
1208
+ const errorNodes = [];
1189
1209
  createProgressIndicator(orphanedNodes.length, 'Removing orphaned nodes...');
1190
1210
 
1191
1211
  for (const node of orphanedNodes) {
1192
- updateProgressIndicator(`Removing ${node._id}...`); // eslint-disable-next-line no-await-in-loop
1212
+ updateProgressIndicator(`Removing ${node['_id']}...`);
1193
1213
 
1194
- await deleteNode(node._id, node._type._id).catch(deleteError => {
1195
- printMessage(`${deleteError}`, 'error');
1196
- });
1214
+ try {
1215
+ // eslint-disable-next-line no-await-in-loop
1216
+ await deleteNode(node['_id'], node['_type']['_id']);
1217
+ } catch (deleteError) {
1218
+ errorNodes.push(node);
1219
+ printMessage(` ${deleteError}`, 'error');
1220
+ }
1197
1221
  }
1198
1222
 
1199
1223
  stopProgressIndicator(`Removed ${orphanedNodes.length} orphaned nodes.`);
1200
- }
1201
- /**
1202
- * Prune orphaned nodes
1203
- */
1204
-
1205
-
1206
- export async function prune() {
1207
- const orphanedNodes = await findOrphanedNodes();
1208
-
1209
- if (orphanedNodes.length > 0) {
1210
- const ok = await yesno({
1211
- question: 'Prune (permanently delete) orphaned nodes? (y|n):'
1212
- });
1213
-
1214
- if (ok) {
1215
- await removeOrphanedNodes(orphanedNodes);
1216
- }
1217
- } else {
1218
- printMessage('No orphaned nodes found.');
1219
- }
1224
+ return errorNodes;
1220
1225
  }
1221
1226
  const OOTB_NODE_TYPES_7 = ['AcceptTermsAndConditionsNode', 'AccountActiveDecisionNode', 'AccountLockoutNode', 'AgentDataStoreDecisionNode', 'AnonymousSessionUpgradeNode', 'AnonymousUserNode', 'AttributeCollectorNode', 'AttributePresentDecisionNode', 'AttributeValueDecisionNode', 'AuthLevelDecisionNode', 'ChoiceCollectorNode', 'ConsentNode', 'CookiePresenceDecisionNode', 'CreateObjectNode', 'CreatePasswordNode', 'DataStoreDecisionNode', 'DeviceGeoFencingNode', 'DeviceLocationMatchNode', 'DeviceMatchNode', 'DeviceProfileCollectorNode', 'DeviceSaveNode', 'DeviceTamperingVerificationNode', 'DisplayUserNameNode', 'EmailSuspendNode', 'EmailTemplateNode', 'IdentifyExistingUserNode', 'IncrementLoginCountNode', 'InnerTreeEvaluatorNode', 'IotAuthenticationNode', 'IotRegistrationNode', 'KbaCreateNode', 'KbaDecisionNode', 'KbaVerifyNode', 'LdapDecisionNode', 'LoginCountDecisionNode', 'MessageNode', 'MetadataNode', 'MeterNode', 'ModifyAuthLevelNode', 'OneTimePasswordCollectorDecisionNode', 'OneTimePasswordGeneratorNode', 'OneTimePasswordSmsSenderNode', 'OneTimePasswordSmtpSenderNode', 'PageNode', 'PasswordCollectorNode', 'PatchObjectNode', 'PersistentCookieDecisionNode', 'PollingWaitNode', 'ProfileCompletenessDecisionNode', 'ProvisionDynamicAccountNode', 'ProvisionIdmAccountNode', 'PushAuthenticationSenderNode', 'PushResultVerifierNode', 'QueryFilterDecisionNode', 'RecoveryCodeCollectorDecisionNode', 'RecoveryCodeDisplayNode', 'RegisterLogoutWebhookNode', 'RemoveSessionPropertiesNode', 'RequiredAttributesDecisionNode', 'RetryLimitDecisionNode', 'ScriptedDecisionNode', 'SelectIdPNode', 'SessionDataNode', 'SetFailureUrlNode', 'SetPersistentCookieNode', 'SetSessionPropertiesNode', 'SetSuccessUrlNode', 'SocialFacebookNode', 'SocialGoogleNode', 'SocialNode', 'SocialOAuthIgnoreProfileNode', 'SocialOpenIdConnectNode', 'SocialProviderHandlerNode', 'TermsAndConditionsDecisionNode', 'TimeSinceDecisionNode', 'TimerStartNode', 'TimerStopNode', 'UsernameCollectorNode', 'ValidatedPasswordNode', 'ValidatedUsernameNode', 'WebAuthnAuthenticationNode', 'WebAuthnDeviceStorageNode', 'WebAuthnRegistrationNode', 'ZeroPageLoginNode', 'product-CertificateCollectorNode', 'product-CertificateUserExtractorNode', 'product-CertificateValidationNode', 'product-KerberosNode', 'product-ReCaptchaNode', 'product-Saml2Node', 'product-WriteFederationInformationNode'];
1222
1227
  const OOTB_NODE_TYPES_7_1 = ['PushRegistrationNode', 'GetAuthenticatorAppNode', 'MultiFactorRegistrationOptionsNode', 'OptOutMultiFactorAuthenticationNode'].concat(OOTB_NODE_TYPES_7);
@@ -1229,10 +1234,9 @@ const OOTB_NODE_TYPES_6 = ['AbstractSocialAuthLoginNode', 'AccountLockoutNode',
1229
1234
  * @returns {boolean} True if the journey/tree contains any custom nodes, false otherwise.
1230
1235
  */
1231
1236
 
1232
- async function isCustom(journey) {
1237
+ export async function isCustom(journey) {
1233
1238
  let ootbNodeTypes = [];
1234
- const nodeList = journey.nodes; // console.log(nodeList);
1235
- // console.log(storage.session.getAmVersion());
1239
+ const nodeList = journey.nodes;
1236
1240
 
1237
1241
  switch (storage.session.getAmVersion()) {
1238
1242
  case '7.1.0':
@@ -1240,7 +1244,6 @@ async function isCustom(journey) {
1240
1244
  break;
1241
1245
 
1242
1246
  case '7.2.0':
1243
- // console.log("here");
1244
1247
  ootbNodeTypes = OOTB_NODE_TYPES_7_2.slice(0);
1245
1248
  break;
1246
1249
 
@@ -1286,7 +1289,7 @@ async function isCustom(journey) {
1286
1289
 
1287
1290
  if (containerNodes.includes(nodeList[node].nodeType)) {
1288
1291
  results.push( // eslint-disable-next-line no-await-in-loop
1289
- (await getNode(node, nodeList[node].nodeType))['data']);
1292
+ await getNode(node, nodeList[node].nodeType));
1290
1293
  }
1291
1294
  }
1292
1295
  }
@@ -1313,12 +1316,11 @@ async function isCustom(journey) {
1313
1316
  * @param {boolean} analyze Analyze journeys/trees for custom nodes (expensive)
1314
1317
  */
1315
1318
 
1316
-
1317
1319
  export async function listJourneys(long = false, analyze = false) {
1318
1320
  let journeys = [];
1319
1321
 
1320
1322
  try {
1321
- journeys = (await getTrees()).data.result;
1323
+ journeys = await getTrees();
1322
1324
  } catch (error) {
1323
1325
  printMessage(`${error.message}`, 'error');
1324
1326
  printMessage(error.response.data, 'error');
@@ -1351,11 +1353,11 @@ export async function listJourneys(long = false, analyze = false) {
1351
1353
  }
1352
1354
  /**
1353
1355
  * Delete a journey
1354
- * @param {String} journeyId journey id/name
1356
+ * @param {string} journeyId journey id/name
1355
1357
  * @param {Object} options deep=true also delete all the nodes and inner nodes, verbose=true print verbose info
1356
1358
  */
1357
1359
 
1358
- export async function deleteJourney(journeyId, options, spinner = true) {
1360
+ export async function deleteJourney(journeyId, options, progress = true) {
1359
1361
  const {
1360
1362
  deep
1361
1363
  } = options;
@@ -1365,29 +1367,29 @@ export async function deleteJourney(journeyId, options, spinner = true) {
1365
1367
  const status = {
1366
1368
  nodes: {}
1367
1369
  };
1368
- if (spinner) createProgressIndicator(undefined, `Deleting ${journeyId}...`, 'indeterminate');
1369
- if (spinner && verbose) stopProgressIndicator();
1370
+ if (progress) createProgressIndicator(undefined, `Deleting ${journeyId}...`, 'indeterminate');
1371
+ if (progress && verbose) stopProgressIndicator();
1370
1372
  return deleteTree(journeyId).then(async deleteTreeResponse => {
1371
1373
  status['status'] = 'success';
1372
1374
  const nodePromises = [];
1373
1375
  if (verbose) printMessage(`Deleted ${journeyId} (tree)`, 'info');
1374
1376
 
1375
1377
  if (deep) {
1376
- for (const [nodeId, nodeObject] of Object.entries(deleteTreeResponse.data.nodes)) {
1378
+ for (const [nodeId, nodeObject] of Object.entries(deleteTreeResponse.nodes)) {
1377
1379
  // delete inner nodes (nodes inside container nodes)
1378
1380
  if (containerNodes.includes(nodeObject['nodeType'])) {
1379
1381
  try {
1380
1382
  // eslint-disable-next-line no-await-in-loop
1381
- const pageNode = (await getNode(nodeId, nodeObject['nodeType'])).data;
1383
+ const containerNode = await getNode(nodeId, nodeObject['nodeType']);
1382
1384
  if (verbose) printMessage(`Read ${nodeId} (${nodeObject['nodeType']}) from ${journeyId}`, 'info');
1383
1385
 
1384
- for (const innerNodeObject of pageNode.nodes) {
1386
+ for (const innerNodeObject of containerNode.nodes) {
1385
1387
  nodePromises.push(deleteNode(innerNodeObject._id, innerNodeObject.nodeType).then(response2 => {
1386
1388
  status.nodes[innerNodeObject._id] = {
1387
1389
  status: 'success'
1388
1390
  };
1389
1391
  if (verbose) printMessage(`Deleted ${innerNodeObject._id} (${innerNodeObject.nodeType}) from ${journeyId}`, 'info');
1390
- return response2.data;
1392
+ return response2;
1391
1393
  }).catch(error => {
1392
1394
  status.nodes[innerNodeObject._id] = {
1393
1395
  status: 'error',
@@ -1398,18 +1400,27 @@ export async function deleteJourney(journeyId, options, spinner = true) {
1398
1400
  } // finally delete the container node
1399
1401
 
1400
1402
 
1401
- nodePromises.push(deleteNode(nodeId, nodeObject['nodeType']).then(response2 => {
1402
- status.nodes[nodeId] = {
1403
+ nodePromises.push(deleteNode(containerNode._id, containerNode['_type']['_id']).then(response2 => {
1404
+ status.nodes[containerNode._id] = {
1403
1405
  status: 'success'
1404
1406
  };
1405
- if (verbose) printMessage(`Deleted ${nodeId} (${nodeObject['nodeType']}) from ${journeyId}`, 'info');
1406
- return response2.data;
1407
+ if (verbose) printMessage(`Deleted ${containerNode._id} (${containerNode['_type']['_id']}) from ${journeyId}`, 'info');
1408
+ return response2;
1407
1409
  }).catch(error => {
1408
- status.nodes[nodeId] = {
1409
- status: 'error',
1410
- error
1411
- };
1412
- if (verbose) printMessage(`Error deleting container node ${nodeId} (${nodeObject['nodeType']}) from ${journeyId}: ${error}`, 'error');
1410
+ var _error$response, _error$response$data;
1411
+
1412
+ if ((error === null || error === void 0 ? void 0 : (_error$response = error.response) === null || _error$response === void 0 ? void 0 : (_error$response$data = _error$response.data) === null || _error$response$data === void 0 ? void 0 : _error$response$data.code) === 500 && error.response.data.message === 'Unable to read SMS config: Node did not exist') {
1413
+ status.nodes[containerNode._id] = {
1414
+ status: 'success'
1415
+ };
1416
+ if (verbose) printMessage(`Deleted ${containerNode._id} (${containerNode['_type']['_id']}) from ${journeyId}`, 'info');
1417
+ } else {
1418
+ status.nodes[containerNode._id] = {
1419
+ status: 'error',
1420
+ error
1421
+ };
1422
+ if (verbose) printMessage(`Error deleting container node ${containerNode._id} (${containerNode['_type']['_id']}) from ${journeyId}: ${error.response.data.message}`, 'error');
1423
+ }
1413
1424
  }));
1414
1425
  } catch (error) {
1415
1426
  if (verbose) printMessage(`Error getting container node ${nodeId} (${nodeObject['nodeType']}) from ${journeyId}: ${error}`, 'error');
@@ -1421,7 +1432,7 @@ export async function deleteJourney(journeyId, options, spinner = true) {
1421
1432
  status: 'success'
1422
1433
  };
1423
1434
  if (verbose) printMessage(`Deleted ${nodeId} (${nodeObject['nodeType']}) from ${journeyId}`, 'info');
1424
- return response.data;
1435
+ return response;
1425
1436
  }).catch(error => {
1426
1437
  status.nodes[nodeId] = {
1427
1438
  status: 'error',
@@ -1436,7 +1447,7 @@ export async function deleteJourney(journeyId, options, spinner = true) {
1436
1447
 
1437
1448
  await Promise.allSettled(nodePromises); // report status
1438
1449
 
1439
- if (spinner) {
1450
+ if (progress) {
1440
1451
  let nodeCount = 0;
1441
1452
  let errorCount = 0;
1442
1453
 
@@ -1471,7 +1482,7 @@ export async function deleteJourneys(options) {
1471
1482
  verbose
1472
1483
  } = options;
1473
1484
  const status = {};
1474
- const trees = (await getTrees()).data.result;
1485
+ const trees = await getTrees();
1475
1486
  createProgressIndicator(trees.length, 'Deleting journeys...');
1476
1487
 
1477
1488
  for (const tree of trees) {