@rockcarver/frodo-lib 0.12.5 → 0.12.7
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 +32 -8
- package/cjs/api/ApiTypes.js +42 -0
- package/cjs/api/ApiTypes.js.map +1 -0
- package/cjs/api/Saml2Api.js +1 -1
- package/cjs/api/Saml2Api.js.map +1 -1
- package/cjs/index.js +17 -1
- package/cjs/index.js.map +1 -1
- package/cjs/ops/JourneyOps.js +282 -151
- package/cjs/ops/JourneyOps.js.map +1 -1
- package/cjs/ops/NodeOps.js +31 -15
- package/cjs/ops/NodeOps.js.map +1 -1
- package/cjs/ops/OpsTypes.js +34 -0
- package/cjs/ops/OpsTypes.js.map +1 -0
- package/cjs/ops/Saml2Ops.js +3 -0
- package/cjs/ops/Saml2Ops.js.map +1 -1
- package/cjs/ops/utils/Console.js +18 -1
- package/cjs/ops/utils/Console.js.map +1 -1
- package/cjs/ops/utils/ExportImportUtils.js.map +1 -1
- package/cjs/storage/SessionStorage.js +4 -0
- package/cjs/storage/SessionStorage.js.map +1 -1
- package/esm/api/ApiTypes.mjs +33 -0
- package/esm/api/Saml2Api.mjs +1 -1
- package/esm/index.mjs +5 -0
- package/esm/ops/JourneyOps.mjs +208 -119
- package/esm/ops/NodeOps.mjs +28 -15
- package/esm/ops/OpsTypes.mjs +25 -0
- package/esm/ops/Saml2Ops.mjs +1 -1
- package/esm/ops/utils/Console.mjs +16 -1
- package/esm/storage/SessionStorage.mjs +4 -0
- package/package.json +3 -2
- package/types/api/ApiTypes.d.ts +102 -0
- package/types/api/ApiTypes.d.ts.map +1 -0
- package/types/api/Saml2Api.d.ts +1 -1
- package/types/api/Saml2Api.d.ts.map +1 -1
- package/types/index.d.ts +3 -0
- package/types/index.d.ts.map +1 -1
- package/types/ops/JourneyOps.d.ts +83 -87
- package/types/ops/JourneyOps.d.ts.map +1 -1
- package/types/ops/NodeOps.d.ts +10 -0
- package/types/ops/NodeOps.d.ts.map +1 -1
- package/types/ops/OpsTypes.d.ts +78 -0
- package/types/ops/OpsTypes.d.ts.map +1 -0
- package/types/ops/Saml2Ops.d.ts +6 -0
- package/types/ops/Saml2Ops.d.ts.map +1 -1
- package/types/ops/utils/Console.d.ts +9 -1
- package/types/ops/utils/Console.d.ts.map +1 -1
- package/types/ops/utils/ExportImportUtils.d.ts.map +1 -1
- package/types/storage/SessionStorage.d.ts +4 -0
- package/types/storage/SessionStorage.d.ts.map +1 -1
package/esm/ops/JourneyOps.mjs
CHANGED
|
@@ -10,7 +10,7 @@ import { getTrees, getTree, putTree, deleteTree } from '../api/TreeApi';
|
|
|
10
10
|
import { getEmailTemplate, putEmailTemplate } from '../api/EmailTemplateApi';
|
|
11
11
|
import { getScript } from '../api/ScriptApi';
|
|
12
12
|
import * as global from '../storage/StaticStorage';
|
|
13
|
-
import { printMessage, createProgressIndicator, updateProgressIndicator, stopProgressIndicator, createTable } from './utils/Console';
|
|
13
|
+
import { printMessage, createProgressIndicator, updateProgressIndicator, stopProgressIndicator, createTable, debugMessage } from './utils/Console';
|
|
14
14
|
import wordwrap from './utils/Wordwrap';
|
|
15
15
|
import { getProviderByLocationAndId, getProviders, getProviderMetadata, createProvider, findProviders, updateProvider } from '../api/Saml2Api';
|
|
16
16
|
import { createCircleOfTrust, getCirclesOfTrust, updateCircleOfTrust } from '../api/CirclesOfTrustApi';
|
|
@@ -18,12 +18,17 @@ import { decode, encode, encodeBase64Url, isBase64Encoded } from '../api/utils/B
|
|
|
18
18
|
import { getSocialIdentityProviders, putProviderByTypeAndId } from '../api/SocialIdentityProvidersApi';
|
|
19
19
|
import { getThemes, putThemes } from '../api/ThemeApi';
|
|
20
20
|
import { createOrUpdateScript } from './ScriptOps';
|
|
21
|
+
import { JourneyClassification } from './OpsTypes';
|
|
21
22
|
const containerNodes = ['PageNode', 'CustomPageNode'];
|
|
22
23
|
const scriptedNodes = ['ConfigProviderNode', 'ScriptedDecisionNode', 'ClientScriptNode', 'SocialProviderHandlerNode', 'CustomScriptNode'];
|
|
23
24
|
const emailTemplateNodes = ['EmailSuspendNode', 'EmailTemplateNode'];
|
|
24
25
|
const emptyScriptPlaceholder = '[Empty]';
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Create an empty single tree export template
|
|
28
|
+
* @returns {SingleTreeExportInterface} an empty single tree export template
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
export function createSingleTreeExportTemplate() {
|
|
27
32
|
return {
|
|
28
33
|
meta: {},
|
|
29
34
|
innerNodes: {},
|
|
@@ -37,8 +42,12 @@ export function createSingleJourneyExportTemplate() {
|
|
|
37
42
|
tree: {}
|
|
38
43
|
};
|
|
39
44
|
}
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Create an empty multi tree export template
|
|
47
|
+
* @returns {MultiTreeExportInterface} an empty multi tree export template
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
export function createMultiTreeExportTemplate() {
|
|
42
51
|
return {
|
|
43
52
|
meta: {},
|
|
44
53
|
trees: {}
|
|
@@ -126,39 +135,22 @@ async function getSaml2NodeDependencies(nodeObject, allProviders, allCirclesOfTr
|
|
|
126
135
|
};
|
|
127
136
|
return saml2NodeDependencies;
|
|
128
137
|
}
|
|
129
|
-
}
|
|
130
|
-
// const nodeList = Object.entries(treeObject.nodes);
|
|
131
|
-
// const results = await Promise.allSettled(
|
|
132
|
-
// nodeList.map(
|
|
133
|
-
// async ([nodeId, nodeInfo]) => await getNode(nodeId, nodeInfo['nodeType'])
|
|
134
|
-
// )
|
|
135
|
-
// );
|
|
136
|
-
// const nodes = results.filter((r) => r.status === 'fulfilled');
|
|
137
|
-
// nodes.map((f) => {
|
|
138
|
-
// return f.status;
|
|
139
|
-
// });
|
|
140
|
-
// const failedList = results.filter((r) => r.status === 'rejected');
|
|
141
|
-
// return nodes;
|
|
142
|
-
// }
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Export options
|
|
146
|
-
*/
|
|
147
|
-
|
|
148
|
-
|
|
138
|
+
}
|
|
149
139
|
/**
|
|
150
140
|
* Create export data for a tree/journey with all its nodes and dependencies. The export data can be written to a file as is.
|
|
151
141
|
* @param {string} treeId tree id/name
|
|
152
|
-
* @param {
|
|
153
|
-
* @returns {Promise<
|
|
142
|
+
* @param {TreeExportOptions} options export options
|
|
143
|
+
* @returns {Promise<SingleTreeExportInterface>} a promise that resolves to an object containing the tree and all its nodes and dependencies
|
|
154
144
|
*/
|
|
145
|
+
|
|
146
|
+
|
|
155
147
|
export async function exportJourney(treeId, options = {
|
|
156
148
|
useStringArrays: true,
|
|
157
149
|
deps: true,
|
|
158
150
|
verbose: false
|
|
159
151
|
}) {
|
|
160
152
|
const treeObject = await getTree(treeId);
|
|
161
|
-
const exportData =
|
|
153
|
+
const exportData = createSingleTreeExportTemplate();
|
|
162
154
|
const {
|
|
163
155
|
useStringArrays,
|
|
164
156
|
deps,
|
|
@@ -456,7 +448,7 @@ export async function getJourneys() {
|
|
|
456
448
|
* Export journey by id/name to file
|
|
457
449
|
* @param {string} journeyId journey id/name
|
|
458
450
|
* @param {string} file optional export file name
|
|
459
|
-
* @param {
|
|
451
|
+
* @param {TreeExportOptions} options export options
|
|
460
452
|
*/
|
|
461
453
|
|
|
462
454
|
export async function exportJourneyToFile(journeyId, file, options) {
|
|
@@ -484,10 +476,14 @@ export async function exportJourneyToFile(journeyId, file, options) {
|
|
|
484
476
|
/**
|
|
485
477
|
* Export all journeys to file
|
|
486
478
|
* @param {string} file optional export file name
|
|
487
|
-
* @param {
|
|
479
|
+
* @param {TreeExportOptions} options export options
|
|
488
480
|
*/
|
|
489
481
|
|
|
490
|
-
export async function exportJourneysToFile(file, options
|
|
482
|
+
export async function exportJourneysToFile(file, options = {
|
|
483
|
+
deps: false,
|
|
484
|
+
useStringArrays: false,
|
|
485
|
+
verbose: false
|
|
486
|
+
}) {
|
|
491
487
|
let fileName = file;
|
|
492
488
|
|
|
493
489
|
if (!fileName) {
|
|
@@ -495,7 +491,7 @@ export async function exportJourneysToFile(file, options) {
|
|
|
495
491
|
}
|
|
496
492
|
|
|
497
493
|
const trees = (await getTrees()).result;
|
|
498
|
-
const fileData =
|
|
494
|
+
const fileData = createMultiTreeExportTemplate();
|
|
499
495
|
createProgressIndicator(trees.length, 'Exporting journeys...');
|
|
500
496
|
|
|
501
497
|
for (const tree of trees) {
|
|
@@ -515,7 +511,7 @@ export async function exportJourneysToFile(file, options) {
|
|
|
515
511
|
}
|
|
516
512
|
/**
|
|
517
513
|
* Export all journeys to separate files
|
|
518
|
-
* @param {
|
|
514
|
+
* @param {TreeExportOptions} options export options
|
|
519
515
|
*/
|
|
520
516
|
|
|
521
517
|
export async function exportJourneysToFiles(options) {
|
|
@@ -535,15 +531,12 @@ export async function exportJourneysToFiles(options) {
|
|
|
535
531
|
|
|
536
532
|
stopProgressIndicator('Done');
|
|
537
533
|
}
|
|
538
|
-
/**
|
|
539
|
-
* Import options
|
|
540
|
-
*/
|
|
541
|
-
|
|
542
534
|
/**
|
|
543
535
|
* Helper to import a tree with all dependencies from an import data object (typically read from a file)
|
|
544
|
-
* @param {
|
|
545
|
-
* @param {
|
|
536
|
+
* @param {SingleTreeExportInterface} treeObject tree object containing tree and all its dependencies
|
|
537
|
+
* @param {TreeImportOptions} options import options
|
|
546
538
|
*/
|
|
539
|
+
|
|
547
540
|
export async function importJourney(treeObject, options) {
|
|
548
541
|
const {
|
|
549
542
|
reUuid,
|
|
@@ -754,8 +747,29 @@ export async function importJourney(treeObject, options) {
|
|
|
754
747
|
try {
|
|
755
748
|
await putNode(newUuid, nodeType, innerNodeData);
|
|
756
749
|
} catch (nodeImportError) {
|
|
750
|
+
var _nodeImportError$resp, _nodeImportError$resp2, _nodeImportError$resp3;
|
|
751
|
+
|
|
757
752
|
if (nodeImportError.response.status === 400 && nodeImportError.response.data.message === 'Data validation failed for the attribute, Script') {
|
|
758
753
|
throw new Error(`Missing script ${innerNodeData['script']} referenced by inner node ${innerNodeId}${innerNodeId === newUuid ? '' : ` [${newUuid}]`} (${innerNodeData['_type']['_id']}) in journey ${treeId}.`);
|
|
754
|
+
} else if (((_nodeImportError$resp = nodeImportError.response) === null || _nodeImportError$resp === void 0 ? void 0 : _nodeImportError$resp.status) === 400 && ((_nodeImportError$resp2 = nodeImportError.response) === null || _nodeImportError$resp2 === void 0 ? void 0 : (_nodeImportError$resp3 = _nodeImportError$resp2.data) === null || _nodeImportError$resp3 === void 0 ? void 0 : _nodeImportError$resp3.message) === 'Invalid attribute specified.') {
|
|
755
|
+
const {
|
|
756
|
+
validAttributes
|
|
757
|
+
} = nodeImportError.response.data.detail;
|
|
758
|
+
validAttributes.push('_id');
|
|
759
|
+
|
|
760
|
+
for (const attribute of Object.keys(innerNodeData)) {
|
|
761
|
+
if (!validAttributes.includes(attribute)) {
|
|
762
|
+
if (verbose) printMessage(`\n - Removing invalid attribute: ${attribute}`, 'warn', false);
|
|
763
|
+
delete innerNodeData[attribute];
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
try {
|
|
768
|
+
await putNode(newUuid, nodeType, innerNodeData);
|
|
769
|
+
} catch (nodeImportError2) {
|
|
770
|
+
printMessage(nodeImportError2.response.data, 'error');
|
|
771
|
+
throw new Error(`Error importing node ${innerNodeId}${innerNodeId === newUuid ? '' : ` [${newUuid}]`} in journey ${treeId}`);
|
|
772
|
+
}
|
|
759
773
|
} else {
|
|
760
774
|
printMessage(nodeImportError.response.data, 'error');
|
|
761
775
|
throw new Error(`Error importing inner node ${innerNodeId}${innerNodeId === newUuid ? '' : ` [${newUuid}]`} in journey ${treeId}`);
|
|
@@ -795,7 +809,7 @@ export async function importJourney(treeObject, options) {
|
|
|
795
809
|
// and the node's identityResource is the same as the tree's identityResource
|
|
796
810
|
// change it to the current realm managed user identityResource otherwise leave it alone.
|
|
797
811
|
|
|
798
|
-
if (nodeData
|
|
812
|
+
if (nodeData.identityResource && nodeData.identityResource.endsWith('user') && nodeData.identityResource === treeObject.tree.identityResource) {
|
|
799
813
|
nodeData['identityResource'] = `managed/${getRealmManagedUser()}`;
|
|
800
814
|
if (verbose) printMessage(`\n - identityResource: ${nodeData['identityResource']}`, 'info', false);
|
|
801
815
|
}
|
|
@@ -803,8 +817,29 @@ export async function importJourney(treeObject, options) {
|
|
|
803
817
|
try {
|
|
804
818
|
await putNode(newUuid, nodeType, nodeData);
|
|
805
819
|
} catch (nodeImportError) {
|
|
820
|
+
var _nodeImportError$resp4, _nodeImportError$resp5, _nodeImportError$resp6;
|
|
821
|
+
|
|
806
822
|
if (nodeImportError.response.status === 400 && nodeImportError.response.data.message === 'Data validation failed for the attribute, Script') {
|
|
807
823
|
throw new Error(`Missing script ${nodeData['script']} referenced by node ${nodeId}${nodeId === newUuid ? '' : ` [${newUuid}]`} (${nodeData['_type']['_id']}) in journey ${treeId}.`);
|
|
824
|
+
} else if (((_nodeImportError$resp4 = nodeImportError.response) === null || _nodeImportError$resp4 === void 0 ? void 0 : _nodeImportError$resp4.status) === 400 && ((_nodeImportError$resp5 = nodeImportError.response) === null || _nodeImportError$resp5 === void 0 ? void 0 : (_nodeImportError$resp6 = _nodeImportError$resp5.data) === null || _nodeImportError$resp6 === void 0 ? void 0 : _nodeImportError$resp6.message) === 'Invalid attribute specified.') {
|
|
825
|
+
const {
|
|
826
|
+
validAttributes
|
|
827
|
+
} = nodeImportError.response.data.detail;
|
|
828
|
+
validAttributes.push('_id');
|
|
829
|
+
|
|
830
|
+
for (const attribute of Object.keys(nodeData)) {
|
|
831
|
+
if (!validAttributes.includes(attribute)) {
|
|
832
|
+
if (verbose) printMessage(`\n - Removing invalid attribute: ${attribute}`, 'warn', false);
|
|
833
|
+
delete nodeData[attribute];
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
try {
|
|
838
|
+
await putNode(newUuid, nodeType, nodeData);
|
|
839
|
+
} catch (nodeImportError2) {
|
|
840
|
+
printMessage(nodeImportError2.response.data, 'error');
|
|
841
|
+
throw new Error(`Error importing node ${nodeId}${nodeId === newUuid ? '' : ` [${newUuid}]`} in journey ${treeId}`);
|
|
842
|
+
}
|
|
808
843
|
} else {
|
|
809
844
|
printMessage(nodeImportError.response.data, 'error');
|
|
810
845
|
throw new Error(`Error importing node ${nodeId}${nodeId === newUuid ? '' : ` [${newUuid}]`} in journey ${treeId}`);
|
|
@@ -831,7 +866,7 @@ export async function importJourney(treeObject, options) {
|
|
|
831
866
|
// Set the identityResource for the tree to the selected resource.
|
|
832
867
|
|
|
833
868
|
|
|
834
|
-
if (treeObject.tree.identityResource && treeObject.tree['identityResource'].endsWith('user')) {
|
|
869
|
+
if (treeObject.tree.identityResource && treeObject.tree['identityResource'].endsWith('user') || storage.session.getDeploymentType() === global.CLOUD_DEPLOYMENT_TYPE_KEY || storage.session.getDeploymentType() === global.FORGEOPS_DEPLOYMENT_TYPE_KEY) {
|
|
835
870
|
treeObject.tree.identityResource = `managed/${getRealmManagedUser()}`;
|
|
836
871
|
if (verbose) printMessage(` - identityResource: ${treeObject.tree.identityResource}`, 'info', false);
|
|
837
872
|
}
|
|
@@ -852,7 +887,7 @@ export async function importJourney(treeObject, options) {
|
|
|
852
887
|
|
|
853
888
|
for (const attribute of Object.keys(treeObject.tree)) {
|
|
854
889
|
if (!validAttributes.includes(attribute)) {
|
|
855
|
-
if (verbose) printMessage(`\n - Removing invalid attribute: ${attribute}`, '
|
|
890
|
+
if (verbose) printMessage(`\n - Removing invalid attribute: ${attribute}`, 'warn', false);
|
|
856
891
|
delete treeObject.tree[attribute];
|
|
857
892
|
}
|
|
858
893
|
}
|
|
@@ -868,7 +903,7 @@ export async function importJourney(treeObject, options) {
|
|
|
868
903
|
var _importError$response9, _importError$response10;
|
|
869
904
|
|
|
870
905
|
printMessage(((_importError$response9 = importError.response) === null || _importError$response9 === void 0 ? void 0 : _importError$response9.data) || importError, 'error');
|
|
871
|
-
|
|
906
|
+
debugMessage(((_importError$response10 = importError.response) === null || _importError$response10 === void 0 ? void 0 : _importError$response10.data) || importError);
|
|
872
907
|
throw new Error(`\nError importing journey flow ${treeId}`);
|
|
873
908
|
}
|
|
874
909
|
}
|
|
@@ -940,7 +975,7 @@ async function resolveDependencies(installedJorneys, journeyMap, unresolvedJourn
|
|
|
940
975
|
* Import a journey from file
|
|
941
976
|
* @param {string} journeyId journey id/name
|
|
942
977
|
* @param {string} file import file name
|
|
943
|
-
* @param {
|
|
978
|
+
* @param {TreeImportOptions} options import options
|
|
944
979
|
*/
|
|
945
980
|
|
|
946
981
|
|
|
@@ -996,7 +1031,7 @@ export async function importJourneyFromFile(journeyId, file, options) {
|
|
|
996
1031
|
/**
|
|
997
1032
|
* Import first journey from file
|
|
998
1033
|
* @param {string} file import file name
|
|
999
|
-
* @param {
|
|
1034
|
+
* @param {TreeImportOptions} options import options
|
|
1000
1035
|
*/
|
|
1001
1036
|
|
|
1002
1037
|
export async function importFirstJourneyFromFile(file, options) {
|
|
@@ -1061,7 +1096,7 @@ export async function importFirstJourneyFromFile(file, options) {
|
|
|
1061
1096
|
/**
|
|
1062
1097
|
* Helper to import multiple trees from a tree map
|
|
1063
1098
|
* @param {Object} treesMap map of trees object
|
|
1064
|
-
* @param {
|
|
1099
|
+
* @param {TreeImportOptions} options import options
|
|
1065
1100
|
*/
|
|
1066
1101
|
|
|
1067
1102
|
async function importAllJourneys(treesMap, options) {
|
|
@@ -1098,7 +1133,7 @@ async function importAllJourneys(treesMap, options) {
|
|
|
1098
1133
|
/**
|
|
1099
1134
|
* Import all journeys from file
|
|
1100
1135
|
* @param {string} file import file name
|
|
1101
|
-
* @param {
|
|
1136
|
+
* @param {TreeImportOptions} options import options
|
|
1102
1137
|
*/
|
|
1103
1138
|
|
|
1104
1139
|
|
|
@@ -1111,7 +1146,7 @@ export async function importJourneysFromFile(file, options) {
|
|
|
1111
1146
|
}
|
|
1112
1147
|
/**
|
|
1113
1148
|
* Import all journeys from separate files
|
|
1114
|
-
* @param {
|
|
1149
|
+
* @param {TreeImportOptions} options import options
|
|
1115
1150
|
*/
|
|
1116
1151
|
|
|
1117
1152
|
export async function importJourneysFromFiles(options) {
|
|
@@ -1129,94 +1164,148 @@ export async function importJourneysFromFiles(options) {
|
|
|
1129
1164
|
importAllJourneys(allJourneysData.trees, options);
|
|
1130
1165
|
}
|
|
1131
1166
|
/**
|
|
1132
|
-
*
|
|
1133
|
-
*
|
|
1167
|
+
* Get the node reference obbject for a node object. Node reference objects
|
|
1168
|
+
* are used in a tree flow definition and within page nodes to reference
|
|
1169
|
+
* nodes. Among other things, node references contain all the non-configuration
|
|
1170
|
+
* meta data that exists for readaility, like the x/y coordinates of the node
|
|
1171
|
+
* and the display name chosen by the tree designer. The dislay name is the
|
|
1172
|
+
* only intuitive link between the graphical representation of the tree and
|
|
1173
|
+
* the node configurations that make up the tree.
|
|
1174
|
+
* @param nodeObj node object to retrieve the node reference object for
|
|
1175
|
+
* @param singleTreeExport tree export with or without dependencies
|
|
1176
|
+
* @returns {NodeRefSkeletonInterface | InnerNodeRefSkeletonInterface} node reference object
|
|
1134
1177
|
*/
|
|
1135
1178
|
|
|
1136
|
-
export function
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
for (const nodeData of Object.values(journeyData.innerNodes)) {
|
|
1150
|
-
if (nodeTypeMap[nodeData['_type']['_id']]) {
|
|
1151
|
-
nodeTypeMap[nodeData['_type']['_id']] += 1;
|
|
1152
|
-
} else {
|
|
1153
|
-
nodeTypeMap[nodeData['_type']['_id']] = 1;
|
|
1179
|
+
export function getNodeRef(nodeObj, singleTreeExport) {
|
|
1180
|
+
if (singleTreeExport.tree.nodes[nodeObj._id]) {
|
|
1181
|
+
return singleTreeExport.tree.nodes[nodeObj._id];
|
|
1182
|
+
} else {
|
|
1183
|
+
for (const node of Object.values(singleTreeExport.nodes)) {
|
|
1184
|
+
if (containerNodes.includes(node._type._id)) {
|
|
1185
|
+
for (const nodeRef of node.nodes) {
|
|
1186
|
+
if (nodeRef._id === nodeObj._id) {
|
|
1187
|
+
return nodeRef;
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1154
1191
|
}
|
|
1155
1192
|
}
|
|
1156
1193
|
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1194
|
+
return undefined;
|
|
1195
|
+
}
|
|
1196
|
+
/**
|
|
1197
|
+
* Default tree export resolver used to resolve a tree id/name to a full export
|
|
1198
|
+
* w/o dependencies of that tree from a platform instance.
|
|
1199
|
+
* @param {string} treeId id/name of the tree to resolve
|
|
1200
|
+
* @returns {TreeExportResolverInterface} tree export
|
|
1201
|
+
*/
|
|
1160
1202
|
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1203
|
+
export const onlineTreeExportResolver = async function (treeId) {
|
|
1204
|
+
debugMessage(`onlineTreeExportResolver(${treeId})`);
|
|
1205
|
+
return await exportJourney(treeId, {
|
|
1206
|
+
deps: false,
|
|
1207
|
+
useStringArrays: false,
|
|
1208
|
+
verbose: false
|
|
1209
|
+
});
|
|
1210
|
+
};
|
|
1211
|
+
/**
|
|
1212
|
+
* Tree export resolver used to resolve a tree id/name to a full export
|
|
1213
|
+
* of that tree from individual `treename.journey.json` export files.
|
|
1214
|
+
* @param {string} treeId id/name of the tree to resolve
|
|
1215
|
+
* @returns {TreeExportResolverInterface} tree export
|
|
1216
|
+
*/
|
|
1164
1217
|
|
|
1165
|
-
|
|
1218
|
+
export const fileByIdTreeExportResolver = async function (treeId) {
|
|
1219
|
+
debugMessage(`fileByIdTreeExportResolver(${treeId})`);
|
|
1220
|
+
let treeExport = createSingleTreeExportTemplate();
|
|
1221
|
+
const file = getTypedFilename(`${treeId}`, 'journey');
|
|
1222
|
+
debugMessage(`fileByIdTreeExportResolver: resolving '${treeId}' to ${file}`);
|
|
1166
1223
|
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
printMessage(`- [${String(count)['brightCyan']}] ${name}`, 'data');
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1224
|
+
try {
|
|
1225
|
+
var _jsonData$tree;
|
|
1172
1226
|
|
|
1173
|
-
|
|
1174
|
-
printMessage('\nThemes:', 'data');
|
|
1227
|
+
const jsonData = JSON.parse(fs.readFileSync(file, 'utf8')); // did we resolve the tree we were asked to resolved?
|
|
1175
1228
|
|
|
1176
|
-
|
|
1177
|
-
|
|
1229
|
+
if (((_jsonData$tree = jsonData.tree) === null || _jsonData$tree === void 0 ? void 0 : _jsonData$tree._id) === treeId) {
|
|
1230
|
+
treeExport = jsonData;
|
|
1231
|
+
} // check if this is a file with multiple trees and get journey by id
|
|
1232
|
+
else if (jsonData.trees && jsonData.trees[treeId]) {
|
|
1233
|
+
treeExport = jsonData.trees[treeId];
|
|
1178
1234
|
}
|
|
1235
|
+
} catch (error) {//
|
|
1179
1236
|
}
|
|
1180
1237
|
|
|
1181
|
-
|
|
1182
|
-
|
|
1238
|
+
return treeExport;
|
|
1239
|
+
};
|
|
1240
|
+
/**
|
|
1241
|
+
* Factory that creates a tree export resolver used to resolve a tree id
|
|
1242
|
+
* to a full export of that tree from a multi-tree export file.
|
|
1243
|
+
* @param {string} file multi-tree export file
|
|
1244
|
+
* @returns {TreeExportResolverInterface} tree export resolver
|
|
1245
|
+
*/
|
|
1246
|
+
|
|
1247
|
+
export function createFileParamTreeExportResolver(file) {
|
|
1248
|
+
const fileParamTreeExportResolver = async function (treeId) {
|
|
1249
|
+
debugMessage(`fileParamTreeExportResolver(${treeId})`);
|
|
1250
|
+
let treeExport = createSingleTreeExportTemplate();
|
|
1183
1251
|
|
|
1184
|
-
|
|
1185
|
-
|
|
1252
|
+
try {
|
|
1253
|
+
var _jsonData$tree2;
|
|
1254
|
+
|
|
1255
|
+
const jsonData = JSON.parse(fs.readFileSync(file, 'utf8')); // did we resolve the tree we were asked to resolved?
|
|
1256
|
+
|
|
1257
|
+
if (((_jsonData$tree2 = jsonData.tree) === null || _jsonData$tree2 === void 0 ? void 0 : _jsonData$tree2._id) === treeId) {
|
|
1258
|
+
treeExport = jsonData;
|
|
1259
|
+
} // check if this is a file with multiple trees and get journey by id
|
|
1260
|
+
else if (jsonData.trees && jsonData.trees[treeId]) {
|
|
1261
|
+
treeExport = jsonData.trees[treeId];
|
|
1262
|
+
} // fall back to fileByIdTreeExportResolver
|
|
1263
|
+
else {
|
|
1264
|
+
treeExport = await fileByIdTreeExportResolver(treeId);
|
|
1265
|
+
}
|
|
1266
|
+
} catch (error) {//
|
|
1186
1267
|
}
|
|
1187
|
-
}
|
|
1188
1268
|
|
|
1189
|
-
|
|
1190
|
-
|
|
1269
|
+
return treeExport;
|
|
1270
|
+
};
|
|
1191
1271
|
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1272
|
+
debugMessage('fileParamTreeExportResolver:');
|
|
1273
|
+
debugMessage(fileParamTreeExportResolver);
|
|
1274
|
+
return fileParamTreeExportResolver;
|
|
1275
|
+
}
|
|
1276
|
+
/**
|
|
1277
|
+
* Get tree dependencies (all descendent inner trees)
|
|
1278
|
+
* @param {SingleTreeExportInterface} treeExport single tree export
|
|
1279
|
+
* @param {string[]} resolvedTreeIds list of tree ids wich have already been resolved
|
|
1280
|
+
* @param {TreeExportResolverInterface} resolveTreeExport tree export resolver callback function
|
|
1281
|
+
* @returns {Promise<TreeDependencyMapInterface>} a promise that resolves to a tree dependency map
|
|
1282
|
+
*/
|
|
1196
1283
|
|
|
1197
|
-
|
|
1198
|
-
|
|
1284
|
+
export async function getTreeDescendents(treeExport, resolveTreeExport = onlineTreeExportResolver, resolvedTreeIds = []) {
|
|
1285
|
+
debugMessage(`getTreeDependencies(${treeExport.tree._id}, [${resolvedTreeIds.join(', ')}])`);
|
|
1199
1286
|
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
}
|
|
1287
|
+
if (!resolvedTreeIds.includes(treeExport.tree._id)) {
|
|
1288
|
+
resolvedTreeIds.push(treeExport.tree._id);
|
|
1203
1289
|
}
|
|
1204
1290
|
|
|
1205
|
-
|
|
1206
|
-
|
|
1291
|
+
const treeDependencyMap = {
|
|
1292
|
+
[treeExport.tree._id]: []
|
|
1293
|
+
};
|
|
1294
|
+
const dependencies = [];
|
|
1207
1295
|
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1296
|
+
for (const [nodeId, node] of Object.entries(treeExport.tree.nodes)) {
|
|
1297
|
+
const innerTreeId = treeExport.nodes[nodeId].tree;
|
|
1212
1298
|
|
|
1213
|
-
|
|
1214
|
-
|
|
1299
|
+
if (node.nodeType === 'InnerTreeEvaluatorNode' && !resolvedTreeIds.includes(innerTreeId)) {
|
|
1300
|
+
const innerTreeExport = await resolveTreeExport(innerTreeId);
|
|
1301
|
+
debugMessage(`resolved inner tree: ${innerTreeExport.tree._id}`); // resolvedTreeIds.push(innerTreeId);
|
|
1215
1302
|
|
|
1216
|
-
|
|
1217
|
-
printMessage(`- ${cotData['_id']}`, 'data');
|
|
1303
|
+
dependencies.push(await getTreeDescendents(innerTreeExport, resolveTreeExport, resolvedTreeIds));
|
|
1218
1304
|
}
|
|
1219
1305
|
}
|
|
1306
|
+
|
|
1307
|
+
treeDependencyMap[treeExport.tree._id] = dependencies;
|
|
1308
|
+
return treeDependencyMap;
|
|
1220
1309
|
}
|
|
1221
1310
|
/**
|
|
1222
1311
|
* Find all node configuration objects that are no longer referenced by any tree
|
|
@@ -1322,7 +1411,7 @@ export async function removeOrphanedNodes(orphanedNodes) {
|
|
|
1322
1411
|
}
|
|
1323
1412
|
/**
|
|
1324
1413
|
* Analyze if a journey contains any custom nodes considering the detected or the overridden version.
|
|
1325
|
-
* @param {
|
|
1414
|
+
* @param {SingleTreeExportInterface} journey Journey/tree configuration object
|
|
1326
1415
|
* @returns {boolean} True if the journey/tree contains any custom nodes, false otherwise.
|
|
1327
1416
|
*/
|
|
1328
1417
|
|
|
@@ -1339,7 +1428,7 @@ export function isCustomJourney(journey) {
|
|
|
1339
1428
|
}
|
|
1340
1429
|
/**
|
|
1341
1430
|
* Analyze if a journey contains any premium nodes considering the detected or the overridden version.
|
|
1342
|
-
* @param {
|
|
1431
|
+
* @param {SingleTreeExportInterface} journey Journey/tree configuration object
|
|
1343
1432
|
* @returns {boolean} True if the journey/tree contains any custom nodes, false otherwise.
|
|
1344
1433
|
*/
|
|
1345
1434
|
|
|
@@ -1356,7 +1445,7 @@ export function isPremiumJourney(journey) {
|
|
|
1356
1445
|
}
|
|
1357
1446
|
/**
|
|
1358
1447
|
* Analyze if a journey contains any cloud-only nodes considering the detected or the overridden version.
|
|
1359
|
-
* @param {
|
|
1448
|
+
* @param {SingleTreeExportInterface} journey Journey/tree configuration object
|
|
1360
1449
|
* @returns {boolean} True if the journey/tree contains any cloud-only nodes, false otherwise.
|
|
1361
1450
|
*/
|
|
1362
1451
|
|
|
@@ -1376,8 +1465,8 @@ export function isCloudOnlyJourney(journey) {
|
|
|
1376
1465
|
* - standard: can run on any instance of a ForgeRock platform
|
|
1377
1466
|
* - cloud: utilize nodes, which are exclusively available in the ForgeRock Identity Cloud
|
|
1378
1467
|
* - premium: utilizes nodes, which come at a premium
|
|
1379
|
-
* @param {
|
|
1380
|
-
* @returns {
|
|
1468
|
+
* @param {SingleTreeExportInterface} journey journey export data
|
|
1469
|
+
* @returns {JourneyClassification[]} an array of one or multiple classifications
|
|
1381
1470
|
*/
|
|
1382
1471
|
|
|
1383
1472
|
export function getJourneyClassification(journey) {
|
|
@@ -1387,14 +1476,14 @@ export function getJourneyClassification(journey) {
|
|
|
1387
1476
|
const cloud = isCloudOnlyJourney(journey);
|
|
1388
1477
|
|
|
1389
1478
|
if (custom) {
|
|
1390
|
-
classifications.push(
|
|
1479
|
+
classifications.push(JourneyClassification.CUSTOM);
|
|
1391
1480
|
} else if (cloud) {
|
|
1392
|
-
classifications.push(
|
|
1481
|
+
classifications.push(JourneyClassification.CLOUD);
|
|
1393
1482
|
} else {
|
|
1394
|
-
classifications.push(
|
|
1483
|
+
classifications.push(JourneyClassification.STANDARD);
|
|
1395
1484
|
}
|
|
1396
1485
|
|
|
1397
|
-
if (premium) classifications.push(
|
|
1486
|
+
if (premium) classifications.push(JourneyClassification.PREMIUM);
|
|
1398
1487
|
return classifications;
|
|
1399
1488
|
}
|
|
1400
1489
|
/**
|
package/esm/ops/NodeOps.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { getTrees } from '../api/TreeApi';
|
|
|
5
5
|
import { printMessage, createProgressIndicator, updateProgressIndicator, stopProgressIndicator } from './utils/Console';
|
|
6
6
|
import { getProviderByLocationAndId, getProviderMetadata } from '../api/Saml2Api';
|
|
7
7
|
import { encodeBase64Url } from '../api/utils/Base64';
|
|
8
|
+
import { NodeClassification } from './OpsTypes';
|
|
8
9
|
const containerNodes = ['PageNode', 'CustomPageNode'];
|
|
9
10
|
const scriptedNodes = ['ConfigProviderNode', 'ScriptedDecisionNode', 'ClientScriptNode', 'SocialProviderHandlerNode', 'CustomScriptNode'];
|
|
10
11
|
const emailTemplateNodes = ['EmailSuspendNode', 'EmailTemplateNode'];
|
|
@@ -91,21 +92,7 @@ async function getSaml2NodeDependencies(nodeObject, allProviders, allCirclesOfTr
|
|
|
91
92
|
};
|
|
92
93
|
return saml2NodeDependencies;
|
|
93
94
|
}
|
|
94
|
-
}
|
|
95
|
-
// const nodeList = Object.entries(treeObject.nodes);
|
|
96
|
-
// const results = await Promise.allSettled(
|
|
97
|
-
// nodeList.map(
|
|
98
|
-
// async ([nodeId, nodeInfo]) => await getNode(nodeId, nodeInfo['nodeType'])
|
|
99
|
-
// )
|
|
100
|
-
// );
|
|
101
|
-
// const nodes = results.filter((r) => r.status === 'fulfilled');
|
|
102
|
-
// nodes.map((f) => {
|
|
103
|
-
// return f.status;
|
|
104
|
-
// });
|
|
105
|
-
// const failedList = results.filter((r) => r.status === 'rejected');
|
|
106
|
-
// return nodes;
|
|
107
|
-
// }
|
|
108
|
-
|
|
95
|
+
}
|
|
109
96
|
/**
|
|
110
97
|
* Find all node configuration objects that are no longer referenced by any tree
|
|
111
98
|
* @returns {Promise<unknown[]>} a promise that resolves to an array of orphaned nodes
|
|
@@ -291,4 +278,30 @@ export function isCustomNode(nodeType) {
|
|
|
291
278
|
|
|
292
279
|
return !ootbNodeTypes.includes(nodeType) && !isPremiumNode(nodeType) && !isCloudOnlyNode(nodeType);
|
|
293
280
|
}
|
|
281
|
+
/**
|
|
282
|
+
* Get a node's classifications, which can be one or multiple of:
|
|
283
|
+
* - standard: can run on any instance of a ForgeRock platform
|
|
284
|
+
* - cloud: utilize nodes, which are exclusively available in the ForgeRock Identity Cloud
|
|
285
|
+
* - premium: utilizes nodes, which come at a premium
|
|
286
|
+
* @param {string} nodeType Node type
|
|
287
|
+
* @returns {NodeClassification[]} an array of one or multiple classifications
|
|
288
|
+
*/
|
|
289
|
+
|
|
290
|
+
export function getNodeClassification(nodeType) {
|
|
291
|
+
const classifications = [];
|
|
292
|
+
const premium = isPremiumNode(nodeType);
|
|
293
|
+
const custom = isCustomNode(nodeType);
|
|
294
|
+
const cloud = isCloudOnlyNode(nodeType);
|
|
295
|
+
|
|
296
|
+
if (custom) {
|
|
297
|
+
classifications.push(NodeClassification.CUSTOM);
|
|
298
|
+
} else if (cloud) {
|
|
299
|
+
classifications.push(NodeClassification.CLOUD);
|
|
300
|
+
} else {
|
|
301
|
+
classifications.push(NodeClassification.STANDARD);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (premium) classifications.push(NodeClassification.PREMIUM);
|
|
305
|
+
return classifications;
|
|
306
|
+
}
|
|
294
307
|
//# sourceMappingURL=NodeOps.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tree export options
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Tree import options
|
|
7
|
+
*/
|
|
8
|
+
export let NodeClassification;
|
|
9
|
+
|
|
10
|
+
(function (NodeClassification) {
|
|
11
|
+
NodeClassification["STANDARD"] = "standard";
|
|
12
|
+
NodeClassification["CUSTOM"] = "custom";
|
|
13
|
+
NodeClassification["CLOUD"] = "cloud";
|
|
14
|
+
NodeClassification["PREMIUM"] = "premium";
|
|
15
|
+
})(NodeClassification || (NodeClassification = {}));
|
|
16
|
+
|
|
17
|
+
export let JourneyClassification;
|
|
18
|
+
|
|
19
|
+
(function (JourneyClassification) {
|
|
20
|
+
JourneyClassification["STANDARD"] = "standard";
|
|
21
|
+
JourneyClassification["CUSTOM"] = "custom";
|
|
22
|
+
JourneyClassification["CLOUD"] = "cloud";
|
|
23
|
+
JourneyClassification["PREMIUM"] = "premium";
|
|
24
|
+
})(JourneyClassification || (JourneyClassification = {}));
|
|
25
|
+
//# sourceMappingURL=OpsTypes.js.map
|
package/esm/ops/Saml2Ops.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { getProviders, findProviders, getProviderByLocationAndId, getProviderMet
|
|
|
6
6
|
import { getScript } from '../api/ScriptApi';
|
|
7
7
|
import { convertBase64TextToArray, convertBase64UrlTextToArray, convertTextArrayToBase64, convertTextArrayToBase64Url, getRealmString, getTypedFilename, saveJsonToFile, saveTextToFile, validateImport } from './utils/ExportImportUtils';
|
|
8
8
|
import { createOrUpdateScript } from './ScriptOps';
|
|
9
|
-
const roleMap = {
|
|
9
|
+
export const roleMap = {
|
|
10
10
|
identityProvider: 'IDP',
|
|
11
11
|
serviceProvider: 'SP',
|
|
12
12
|
attributeQueryProvider: 'AttrQuery',
|