@contentstack/cli-cm-export-to-csv 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/package.json +3 -3
- package/src/commands/cm/export-to-csv.js +11 -11
- package/src/util/config.js +2 -2
- package/src/util/index.js +171 -118
package/LICENSE
CHANGED
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-cm-export-to-csv",
|
|
3
3
|
"description": "Export entities to csv",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.7.0",
|
|
5
5
|
"author": "Abhinav Gupta @abhinav-from-contentstack",
|
|
6
6
|
"bugs": "https://github.com/contentstack/cli/issues",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@contentstack/cli-command": "~1.2.16",
|
|
9
|
-
"@contentstack/cli-utilities": "~1.5.
|
|
9
|
+
"@contentstack/cli-utilities": "~1.5.12",
|
|
10
10
|
"chalk": "^4.1.0",
|
|
11
11
|
"fast-csv": "^4.3.6",
|
|
12
12
|
"inquirer": "8.2.4",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"mkdirp": "^3.0.1"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@oclif/test": "^2.
|
|
17
|
+
"@oclif/test": "^2.5.6",
|
|
18
18
|
"@types/chai": "^4.3.6",
|
|
19
19
|
"@types/mocha": "^10.0.1",
|
|
20
20
|
"chai": "^4.3.8",
|
|
@@ -334,8 +334,8 @@ class ExportToCsvCommand extends Command {
|
|
|
334
334
|
const listOfTokens = configHandler.get('tokens');
|
|
335
335
|
if (managementTokenAlias && listOfTokens[managementTokenAlias]) {
|
|
336
336
|
const checkManagementTokenValidity = await isManagementTokenValid((listOfTokens[managementTokenAlias].apiKey) ,listOfTokens[managementTokenAlias].token);
|
|
337
|
-
if(
|
|
338
|
-
throw checkManagementTokenValidity.
|
|
337
|
+
if(checkManagementTokenValidity.hasOwnProperty('message')) {
|
|
338
|
+
throw checkManagementTokenValidity.valid==='failedToCheck'?checkManagementTokenValidity.message:(`error: Management token or stack API key is invalid. ${checkManagementTokenValidity.message}`);
|
|
339
339
|
}
|
|
340
340
|
apiClient = await managementSDKClient({
|
|
341
341
|
host: this.cmaHost,
|
|
@@ -449,31 +449,31 @@ ExportToCsvCommand.description = `Export entries, taxonomies, terms or organizat
|
|
|
449
449
|
ExportToCsvCommand.examples = [
|
|
450
450
|
'csdx cm:export-to-csv',
|
|
451
451
|
'',
|
|
452
|
-
'Exporting entries to
|
|
452
|
+
'Exporting entries to CSV',
|
|
453
453
|
'csdx cm:export-to-csv --action <entries> --locale <locale> --alias <management-token-alias> --content-type <content-type>',
|
|
454
454
|
'',
|
|
455
|
-
'Exporting entries to
|
|
455
|
+
'Exporting entries to CSV with stack name provided and branch name provided',
|
|
456
456
|
'csdx cm:export-to-csv --action <entries> --locale <locale> --alias <management-token-alias> --content-type <content-type> --stack-name <stack-name> --branch <branch-name>',
|
|
457
457
|
'',
|
|
458
|
-
'Exporting organization users to
|
|
458
|
+
'Exporting organization users to CSV',
|
|
459
459
|
'csdx cm:export-to-csv --action <users> --org <org-uid>',
|
|
460
460
|
'',
|
|
461
|
-
'Exporting organization users to
|
|
461
|
+
'Exporting organization users to CSV with organization name provided',
|
|
462
462
|
'csdx cm:export-to-csv --action <users> --org <org-uid> --org-name <org-name>',
|
|
463
463
|
'',
|
|
464
|
-
'Exporting
|
|
464
|
+
'Exporting organization teams to CSV',
|
|
465
465
|
'csdx cm:export-to-csv --action <teams>',
|
|
466
466
|
'',
|
|
467
|
-
'Exporting
|
|
467
|
+
'Exporting organization teams to CSV with org UID',
|
|
468
468
|
'csdx cm:export-to-csv --action <teams> --org <org-uid>',
|
|
469
469
|
'',
|
|
470
|
-
'Exporting
|
|
470
|
+
'Exporting organization teams to CSV with team UID',
|
|
471
471
|
'csdx cm:export-to-csv --action <teams> --team-uid <team-uid>',
|
|
472
472
|
'',
|
|
473
|
-
'Exporting
|
|
473
|
+
'Exporting organization teams to CSV with org UID and team UID',
|
|
474
474
|
'csdx cm:export-to-csv --action <teams> --org <org-uid> --team-uid <team-uid>',
|
|
475
475
|
'',
|
|
476
|
-
'Exporting
|
|
476
|
+
'Exporting organization teams to CSV with org UID and team UID',
|
|
477
477
|
'csdx cm:export-to-csv --action <teams> --org <org-uid> --team-uid <team-uid> --org-name <org-name>',
|
|
478
478
|
'',
|
|
479
479
|
'Exporting taxonomies and related terms to a .CSV file with the provided taxonomy UID',
|
package/src/util/config.js
CHANGED
|
@@ -2,8 +2,8 @@ module.exports = {
|
|
|
2
2
|
limit:100,
|
|
3
3
|
cancelString: 'Cancel and Exit',
|
|
4
4
|
exportEntries: 'Export entries to a .CSV file',
|
|
5
|
-
exportUsers: "Export organization
|
|
6
|
-
exportTeams: "Export organization
|
|
5
|
+
exportUsers: "Export organization users' data to a .CSV file",
|
|
6
|
+
exportTeams: "Export organization teams' data to a .CSV file",
|
|
7
7
|
exportTaxonomies: 'Export taxonomies to a .CSV file',
|
|
8
8
|
adminError: "Unable to export data. Make sure you're an admin or owner of this organization",
|
|
9
9
|
organizationNameRegex: /\'/,
|
package/src/util/index.js
CHANGED
|
@@ -62,7 +62,6 @@ async function getOrganizations(managementAPIClient) {
|
|
|
62
62
|
try {
|
|
63
63
|
return await getOrganizationList(managementAPIClient, { skip: 0, page: 1, limit: 100 }, []);
|
|
64
64
|
} catch (error) {
|
|
65
|
-
console.log(error);
|
|
66
65
|
throw error;
|
|
67
66
|
}
|
|
68
67
|
}
|
|
@@ -461,7 +460,7 @@ function write(command, entries, fileName, message, delimiter, headers) {
|
|
|
461
460
|
process.chdir(directory);
|
|
462
461
|
}
|
|
463
462
|
// eslint-disable-next-line no-undef
|
|
464
|
-
cliux.print(`Writing ${message} to file: ${process.cwd()}${delimeter}${fileName}`);
|
|
463
|
+
cliux.print(`Writing ${message} to file: "${process.cwd()}${delimeter}${fileName}"`);
|
|
465
464
|
if (headers?.length) fastcsv.writeToPath(fileName, entries, { headers, delimiter });
|
|
466
465
|
else fastcsv.writeToPath(fileName, entries, { headers: true, delimiter });
|
|
467
466
|
}
|
|
@@ -693,54 +692,59 @@ function wait(time) {
|
|
|
693
692
|
}
|
|
694
693
|
|
|
695
694
|
function handleErrorMsg(err) {
|
|
696
|
-
cliux.print(`Error: ${(err?.errorMessage || err?.message)
|
|
695
|
+
cliux.print(`Error: ${(err?.errorMessage || err?.message) ?? messageHandler.parse('CLI_EXPORT_CSV_API_FAILED')}`, {
|
|
696
|
+
color: 'red',
|
|
697
|
+
});
|
|
697
698
|
process.exit(1);
|
|
698
699
|
}
|
|
699
700
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
.
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
const { status, data } = res;
|
|
714
|
-
if (status === 200) {
|
|
715
|
-
return data;
|
|
716
|
-
} else {
|
|
717
|
-
cliux.print(`${data?.error_message || data?.message || data?.errorMessage}`, { color: 'red' });
|
|
718
|
-
process.exit(1);
|
|
719
|
-
}
|
|
720
|
-
})
|
|
721
|
-
.catch((error) => {
|
|
722
|
-
handleErrorMsg(error);
|
|
723
|
-
});
|
|
701
|
+
/**
|
|
702
|
+
* This function does the sdk calls to get all the teams in org
|
|
703
|
+
* @param {object} managementAPIClient
|
|
704
|
+
* @param {object} org
|
|
705
|
+
* @param {object} queryParam
|
|
706
|
+
* @returns
|
|
707
|
+
*/
|
|
708
|
+
async function getAllTeams(managementAPIClient, org, queryParam = {}) {
|
|
709
|
+
try {
|
|
710
|
+
return await managementAPIClient.organization(org.uid).teams().fetchAll(queryParam);
|
|
711
|
+
} catch (error) {
|
|
712
|
+
handleErrorMsg(error);
|
|
713
|
+
}
|
|
724
714
|
}
|
|
725
715
|
|
|
716
|
+
/**
|
|
717
|
+
* This function is used to handle the pagination and call the sdk
|
|
718
|
+
* @param {object} managementAPIClient
|
|
719
|
+
* @param {object} org
|
|
720
|
+
*/
|
|
726
721
|
async function exportOrgTeams(managementAPIClient, org) {
|
|
727
|
-
let
|
|
722
|
+
let allTeamsInOrg = [];
|
|
728
723
|
let skip = 0;
|
|
729
724
|
let limit = config?.limit || 100;
|
|
730
725
|
do {
|
|
731
|
-
const data = await
|
|
726
|
+
const data = await getAllTeams(managementAPIClient, org, {
|
|
727
|
+
skip: skip,
|
|
728
|
+
limit: limit,
|
|
729
|
+
includeUserDetails: true,
|
|
730
|
+
});
|
|
732
731
|
skip += limit;
|
|
733
|
-
|
|
732
|
+
allTeamsInOrg.push(...data.items);
|
|
734
733
|
if (skip >= data?.count) break;
|
|
735
734
|
} while (1);
|
|
736
|
-
|
|
737
|
-
return
|
|
735
|
+
allTeamsInOrg = await cleanTeamsData(allTeamsInOrg, managementAPIClient, org);
|
|
736
|
+
return allTeamsInOrg;
|
|
738
737
|
}
|
|
739
738
|
|
|
739
|
+
/**
|
|
740
|
+
* This function will get all the org level roles
|
|
741
|
+
* @param {object} managementAPIClient
|
|
742
|
+
* @param {object} org
|
|
743
|
+
*/
|
|
740
744
|
async function getOrgRolesForTeams(managementAPIClient, org) {
|
|
741
745
|
let roleMap = {}; // for org level there are two roles only admin and member
|
|
742
746
|
|
|
743
|
-
// SDK call to get the role
|
|
747
|
+
// SDK call to get the role UIDs
|
|
744
748
|
await managementAPIClient
|
|
745
749
|
.organization(org.uid)
|
|
746
750
|
.roles()
|
|
@@ -757,6 +761,12 @@ async function getOrgRolesForTeams(managementAPIClient, org) {
|
|
|
757
761
|
return roleMap;
|
|
758
762
|
}
|
|
759
763
|
|
|
764
|
+
/**
|
|
765
|
+
* Removes the unnecessary fields from the objects in the data and assign org level roles to the team based on role uid
|
|
766
|
+
* @param {array} data
|
|
767
|
+
* @param {object} managementAPIClient
|
|
768
|
+
* @param {object} org
|
|
769
|
+
*/
|
|
760
770
|
async function cleanTeamsData(data, managementAPIClient, org) {
|
|
761
771
|
const roleMap = await getOrgRolesForTeams(managementAPIClient, org);
|
|
762
772
|
const fieldToBeDeleted = [
|
|
@@ -769,18 +779,24 @@ async function cleanTeamsData(data, managementAPIClient, org) {
|
|
|
769
779
|
'createdByUserName',
|
|
770
780
|
'updatedByUserName',
|
|
771
781
|
'organizationUid',
|
|
782
|
+
'urlPath',
|
|
783
|
+
'update',
|
|
784
|
+
'delete',
|
|
785
|
+
'fetch',
|
|
786
|
+
'stackRoleMappings',
|
|
787
|
+
'teamUsers',
|
|
772
788
|
];
|
|
773
789
|
if (data?.length) {
|
|
774
790
|
return data.map((team) => {
|
|
775
791
|
team = omit(team, fieldToBeDeleted);
|
|
776
|
-
|
|
777
|
-
team.organizationRole =
|
|
778
|
-
|
|
779
|
-
if (!team.hasOwnProperty(
|
|
780
|
-
team.description =
|
|
792
|
+
|
|
793
|
+
team.organizationRole = team.organizationRole === roleMap['member'] ? 'member' : 'admin';
|
|
794
|
+
|
|
795
|
+
if (!team.hasOwnProperty('description')) {
|
|
796
|
+
team.description = '';
|
|
781
797
|
}
|
|
782
798
|
team.Total_Members = team?.users?.length || 0;
|
|
783
|
-
|
|
799
|
+
|
|
784
800
|
return team;
|
|
785
801
|
});
|
|
786
802
|
} else {
|
|
@@ -788,6 +804,13 @@ async function cleanTeamsData(data, managementAPIClient, org) {
|
|
|
788
804
|
}
|
|
789
805
|
}
|
|
790
806
|
|
|
807
|
+
/**
|
|
808
|
+
* This function is used to call all the other teams function to export the required files
|
|
809
|
+
* @param {object} managementAPIClient
|
|
810
|
+
* @param {object} organization
|
|
811
|
+
* @param {string} teamUid
|
|
812
|
+
* @param {character} delimiter
|
|
813
|
+
*/
|
|
791
814
|
async function exportTeams(managementAPIClient, organization, teamUid, delimiter) {
|
|
792
815
|
cliux.print(
|
|
793
816
|
`info: Exporting the ${
|
|
@@ -799,7 +822,9 @@ async function exportTeams(managementAPIClient, organization, teamUid, delimiter
|
|
|
799
822
|
);
|
|
800
823
|
const allTeamsData = await exportOrgTeams(managementAPIClient, organization);
|
|
801
824
|
if (!allTeamsData?.length) {
|
|
802
|
-
cliux.print(
|
|
825
|
+
cliux.print(
|
|
826
|
+
`info: The organization ${organization?.name} does not have any teams associated with it. Please verify and provide the correct organization name.`,
|
|
827
|
+
);
|
|
803
828
|
} else {
|
|
804
829
|
const modifiedTeam = cloneDeep(allTeamsData);
|
|
805
830
|
modifiedTeam.forEach((team) => {
|
|
@@ -825,6 +850,13 @@ async function exportTeams(managementAPIClient, organization, teamUid, delimiter
|
|
|
825
850
|
}
|
|
826
851
|
}
|
|
827
852
|
|
|
853
|
+
/**
|
|
854
|
+
* This function is used to get individual team user details and write to file
|
|
855
|
+
* @param {array} allTeamsData
|
|
856
|
+
* @param {object} organization
|
|
857
|
+
* @param {string} teamUid optional
|
|
858
|
+
* @param {character} delimiter
|
|
859
|
+
*/
|
|
828
860
|
async function getTeamsDetail(allTeamsData, organization, teamUid, delimiter) {
|
|
829
861
|
if (!teamUid) {
|
|
830
862
|
const userData = await getTeamsUserDetails(allTeamsData);
|
|
@@ -835,14 +867,12 @@ async function getTeamsDetail(allTeamsData, organization, teamUid, delimiter) {
|
|
|
835
867
|
write(this, userData, fileName, 'Team User details', delimiter);
|
|
836
868
|
} else {
|
|
837
869
|
const team = allTeamsData.filter((team) => team.uid === teamUid)[0];
|
|
838
|
-
|
|
839
870
|
team.users.forEach((user) => {
|
|
840
871
|
user['team-name'] = team.name;
|
|
841
872
|
user['team-uid'] = team.uid;
|
|
842
873
|
delete user['active'];
|
|
843
874
|
delete user['orgInvitationStatus'];
|
|
844
875
|
});
|
|
845
|
-
|
|
846
876
|
const fileName = `${kebabize(
|
|
847
877
|
organization.name.replace(config.organizationNameRegex, ''),
|
|
848
878
|
)}_team_${teamUid}_User_Details_export.csv`;
|
|
@@ -851,16 +881,25 @@ async function getTeamsDetail(allTeamsData, organization, teamUid, delimiter) {
|
|
|
851
881
|
}
|
|
852
882
|
}
|
|
853
883
|
|
|
884
|
+
/**
|
|
885
|
+
* This will export the role mappings of the team, for which stack the team has which role
|
|
886
|
+
* @param {object} managementAPIClient
|
|
887
|
+
* @param {array} allTeamsData Data for all the teams in the stack
|
|
888
|
+
* @param {string} teamUid for a particular team who's data we want
|
|
889
|
+
* @param {character} delimiter
|
|
890
|
+
*/
|
|
854
891
|
async function exportRoleMappings(managementAPIClient, allTeamsData, teamUid, delimiter) {
|
|
855
892
|
let stackRoleWithTeamData = [];
|
|
856
893
|
let flag = false;
|
|
857
894
|
const stackNotAdmin = [];
|
|
858
895
|
if (teamUid) {
|
|
859
|
-
const team = find(allTeamsData,function(teamObject) {
|
|
896
|
+
const team = find(allTeamsData, function (teamObject) {
|
|
897
|
+
return teamObject?.uid === teamUid;
|
|
898
|
+
});
|
|
860
899
|
for (const stack of team?.stackRoleMapping) {
|
|
861
900
|
const roleData = await mapRoleWithTeams(managementAPIClient, stack, team?.name, team?.uid);
|
|
862
901
|
stackRoleWithTeamData.push(...roleData);
|
|
863
|
-
if(roleData[0]['Stack Name']==='') {
|
|
902
|
+
if (roleData[0]['Stack Name'] === '') {
|
|
864
903
|
flag = true;
|
|
865
904
|
stackNotAdmin.push(stack.stackApiKey);
|
|
866
905
|
}
|
|
@@ -870,18 +909,21 @@ async function exportRoleMappings(managementAPIClient, allTeamsData, teamUid, de
|
|
|
870
909
|
for (const stack of team?.stackRoleMapping ?? []) {
|
|
871
910
|
const roleData = await mapRoleWithTeams(managementAPIClient, stack, team?.name, team?.uid);
|
|
872
911
|
stackRoleWithTeamData.push(...roleData);
|
|
873
|
-
if(roleData[0]['Stack Name']==='') {
|
|
912
|
+
if (roleData[0]['Stack Name'] === '') {
|
|
874
913
|
flag = true;
|
|
875
914
|
stackNotAdmin.push(stack.stackApiKey);
|
|
876
915
|
}
|
|
877
916
|
}
|
|
878
917
|
}
|
|
879
918
|
}
|
|
880
|
-
if(stackNotAdmin?.length) {
|
|
881
|
-
cliux.print(
|
|
882
|
-
|
|
919
|
+
if (stackNotAdmin?.length) {
|
|
920
|
+
cliux.print(
|
|
921
|
+
`warning: Admin access denied to the following stacks using the provided API keys. Please get in touch with the stack owner to request access.`,
|
|
922
|
+
{ color: 'yellow' },
|
|
923
|
+
);
|
|
924
|
+
cliux.print(`${stackNotAdmin.join(' , ')}`, { color: 'yellow' });
|
|
883
925
|
}
|
|
884
|
-
if(flag) {
|
|
926
|
+
if (flag) {
|
|
885
927
|
let export_stack_role = [
|
|
886
928
|
{
|
|
887
929
|
type: 'list',
|
|
@@ -889,19 +931,17 @@ async function exportRoleMappings(managementAPIClient, allTeamsData, teamUid, de
|
|
|
889
931
|
message: `Access denied: Please confirm if you still want to continue exporting the data without the { Stack Name, Stack Uid, Role Name } fields.`,
|
|
890
932
|
choices: ['yes', 'no'],
|
|
891
933
|
loop: false,
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
})
|
|
898
|
-
.catch((error) => {
|
|
899
|
-
cliux.print(error, {color:'red'});
|
|
900
|
-
process.exit(1);
|
|
901
|
-
});
|
|
902
|
-
if(exportStackRole.chooseExport === 'no') {
|
|
934
|
+
},
|
|
935
|
+
];
|
|
936
|
+
try {
|
|
937
|
+
const exportStackRole = await inquirer.prompt(export_stack_role);
|
|
938
|
+
if (exportStackRole.chooseExport === 'no') {
|
|
903
939
|
process.exit(1);
|
|
904
|
-
}
|
|
940
|
+
}
|
|
941
|
+
} catch (error) {
|
|
942
|
+
cliux.print(error, { color: 'red' });
|
|
943
|
+
process.exit(1);
|
|
944
|
+
}
|
|
905
945
|
}
|
|
906
946
|
|
|
907
947
|
const fileName = `${kebabize('Stack_Role_Mapping'.replace(config.organizationNameRegex, ''))}${
|
|
@@ -911,13 +951,20 @@ async function exportRoleMappings(managementAPIClient, allTeamsData, teamUid, de
|
|
|
911
951
|
write(this, stackRoleWithTeamData, fileName, 'Team Stack Role details', delimiter);
|
|
912
952
|
}
|
|
913
953
|
|
|
954
|
+
/**
|
|
955
|
+
* Mapping the team stacks with the stack role and returning and array of object
|
|
956
|
+
* @param {object} managementAPIClient
|
|
957
|
+
* @param {array} stackRoleMapping
|
|
958
|
+
* @param {string} teamName
|
|
959
|
+
* @param {string} teamUid
|
|
960
|
+
*/
|
|
914
961
|
async function mapRoleWithTeams(managementAPIClient, stackRoleMapping, teamName, teamUid) {
|
|
915
962
|
const roles = await getRoleData(managementAPIClient, stackRoleMapping.stackApiKey);
|
|
916
963
|
const stackRole = {};
|
|
917
964
|
roles?.items?.forEach((role) => {
|
|
918
965
|
if (!stackRole.hasOwnProperty(role?.uid)) {
|
|
919
966
|
stackRole[role?.uid] = role?.name;
|
|
920
|
-
stackRole[role?.stack?.api_key] = {name: role?.stack?.name, uid: role?.stack?.uid }
|
|
967
|
+
stackRole[role?.stack?.api_key] = { name: role?.stack?.name, uid: role?.stack?.uid };
|
|
921
968
|
}
|
|
922
969
|
});
|
|
923
970
|
const stackRoleMapOfTeam = stackRoleMapping?.roles.map((role) => {
|
|
@@ -933,17 +980,26 @@ async function mapRoleWithTeams(managementAPIClient, stackRoleMapping, teamName,
|
|
|
933
980
|
return stackRoleMapOfTeam;
|
|
934
981
|
}
|
|
935
982
|
|
|
983
|
+
/**
|
|
984
|
+
* Making sdk call to get all the roles in the given stack
|
|
985
|
+
* @param {object} managementAPIClient
|
|
986
|
+
* @param {string} stackApiKey
|
|
987
|
+
*/
|
|
936
988
|
async function getRoleData(managementAPIClient, stackApiKey) {
|
|
937
989
|
try {
|
|
938
990
|
return await managementAPIClient.stack({ api_key: stackApiKey }).role().fetchAll();
|
|
939
991
|
} catch (error) {
|
|
940
|
-
return {}
|
|
992
|
+
return {};
|
|
941
993
|
}
|
|
942
994
|
}
|
|
943
995
|
|
|
944
|
-
|
|
996
|
+
/**
|
|
997
|
+
* Here in the users array we are adding the team-name and team-uid to individual users and returning an array of object of user details only
|
|
998
|
+
* @param {array} teams
|
|
999
|
+
*/
|
|
1000
|
+
async function getTeamsUserDetails(teams) {
|
|
945
1001
|
const allTeamUsers = [];
|
|
946
|
-
|
|
1002
|
+
teams.forEach((team) => {
|
|
947
1003
|
if (team?.users?.length) {
|
|
948
1004
|
team.users.forEach((user) => {
|
|
949
1005
|
user['team-name'] = team.name;
|
|
@@ -1024,7 +1080,7 @@ async function getTaxonomy(payload) {
|
|
|
1024
1080
|
* @returns {*} Promise<any>
|
|
1025
1081
|
*/
|
|
1026
1082
|
async function taxonomySDKHandler(payload, skip) {
|
|
1027
|
-
const { stackAPIClient, taxonomyUID, type } = payload;
|
|
1083
|
+
const { stackAPIClient, taxonomyUID, type, format } = payload;
|
|
1028
1084
|
|
|
1029
1085
|
const queryParams = { include_count: true, limit: payload.limit };
|
|
1030
1086
|
if (skip >= 0) queryParams['skip'] = skip || 0;
|
|
@@ -1036,13 +1092,13 @@ async function taxonomySDKHandler(payload, skip) {
|
|
|
1036
1092
|
.query(queryParams)
|
|
1037
1093
|
.find()
|
|
1038
1094
|
.then((data) => data)
|
|
1039
|
-
.catch((err) =>
|
|
1095
|
+
.catch((err) => handleTaxonomyErrorMsg(err));
|
|
1040
1096
|
case 'taxonomy':
|
|
1041
1097
|
return await stackAPIClient
|
|
1042
1098
|
.taxonomy(taxonomyUID)
|
|
1043
1099
|
.fetch()
|
|
1044
1100
|
.then((data) => data)
|
|
1045
|
-
.catch((err) =>
|
|
1101
|
+
.catch((err) => handleTaxonomyErrorMsg(err));
|
|
1046
1102
|
case 'terms':
|
|
1047
1103
|
queryParams['depth'] = 0;
|
|
1048
1104
|
return await stackAPIClient
|
|
@@ -1051,9 +1107,15 @@ async function taxonomySDKHandler(payload, skip) {
|
|
|
1051
1107
|
.query(queryParams)
|
|
1052
1108
|
.find()
|
|
1053
1109
|
.then((data) => data)
|
|
1054
|
-
.catch((err) =>
|
|
1110
|
+
.catch((err) => handleTaxonomyErrorMsg(err));
|
|
1111
|
+
case 'export-taxonomies':
|
|
1112
|
+
return await stackAPIClient
|
|
1113
|
+
.taxonomy(taxonomyUID)
|
|
1114
|
+
.export({ format })
|
|
1115
|
+
.then((data) => data)
|
|
1116
|
+
.catch((err) => handleTaxonomyErrorMsg(err));
|
|
1055
1117
|
default:
|
|
1056
|
-
|
|
1118
|
+
handleTaxonomyErrorMsg({ errorMessage: 'Invalid module!' });
|
|
1057
1119
|
}
|
|
1058
1120
|
}
|
|
1059
1121
|
|
|
@@ -1096,11 +1158,9 @@ function formatTermsOfTaxonomyData(terms, taxonomyUID) {
|
|
|
1096
1158
|
}
|
|
1097
1159
|
}
|
|
1098
1160
|
|
|
1099
|
-
function
|
|
1100
|
-
if (err?.errorMessage) {
|
|
1101
|
-
|
|
1102
|
-
} else if (err?.message) {
|
|
1103
|
-
const errorMsg = err?.errors?.taxonomy || err?.errors?.term || err?.message;
|
|
1161
|
+
function handleTaxonomyErrorMsg(err) {
|
|
1162
|
+
if (err?.errorMessage || err?.message) {
|
|
1163
|
+
const errorMsg = err?.errorMessage || err?.errors?.taxonomy || err?.errors?.term || err?.message;
|
|
1104
1164
|
cliux.print(`Error: ${errorMsg}`, { color: 'red' });
|
|
1105
1165
|
} else {
|
|
1106
1166
|
console.log(err);
|
|
@@ -1110,60 +1170,53 @@ function handleErrorMsg(err) {
|
|
|
1110
1170
|
}
|
|
1111
1171
|
|
|
1112
1172
|
/**
|
|
1113
|
-
*
|
|
1173
|
+
* Generate a CSV file that can be imported for use with the migration script.
|
|
1114
1174
|
* @param {*} payload api request payload
|
|
1115
1175
|
* @param {*} taxonomies taxonomies data
|
|
1116
1176
|
* @returns
|
|
1117
1177
|
*/
|
|
1118
1178
|
async function createImportableCSV(payload, taxonomies) {
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
const
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
}
|
|
1130
|
-
taxonomiesData.push(sanitizedTaxonomy);
|
|
1131
|
-
payload['taxonomyUID'] = taxonomyUID;
|
|
1132
|
-
const terms = await getAllTermsOfTaxonomy(payload);
|
|
1133
|
-
//fetch all parent terms
|
|
1134
|
-
const parentTerms = terms.filter((term) => term?.parent_uid === null);
|
|
1135
|
-
const termsData = getParentAndChildTerms(parentTerms, terms, headers);
|
|
1136
|
-
taxonomiesData.push(...termsData)
|
|
1179
|
+
let taxonomiesData = [];
|
|
1180
|
+
let headers = [];
|
|
1181
|
+
payload['type'] = 'export-taxonomies';
|
|
1182
|
+
payload['format'] = 'csv';
|
|
1183
|
+
for (const taxonomy of taxonomies) {
|
|
1184
|
+
if (taxonomy?.uid) {
|
|
1185
|
+
payload['taxonomyUID'] = taxonomy?.uid;
|
|
1186
|
+
const data = await taxonomySDKHandler(payload);
|
|
1187
|
+
const taxonomies = await csvParse(data, headers);
|
|
1188
|
+
taxonomiesData.push(...taxonomies);
|
|
1189
|
+
}
|
|
1137
1190
|
}
|
|
1138
|
-
}
|
|
1139
1191
|
|
|
1140
|
-
|
|
1192
|
+
return { taxonomiesData, headers };
|
|
1141
1193
|
}
|
|
1142
1194
|
|
|
1143
1195
|
/**
|
|
1144
|
-
*
|
|
1145
|
-
* @param {*}
|
|
1146
|
-
* @param {*}
|
|
1147
|
-
* @
|
|
1148
|
-
* @param {*} termsData parent and child terms
|
|
1196
|
+
* Parse the CSV data and segregate the headers from the actual data.
|
|
1197
|
+
* @param {*} data taxonomy csv data with headers
|
|
1198
|
+
* @param {*} headers list of csv headers
|
|
1199
|
+
* @returns taxonomy data without headers
|
|
1149
1200
|
*/
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
const
|
|
1153
|
-
const
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
}
|
|
1201
|
+
const csvParse = (data, headers) => {
|
|
1202
|
+
return new Promise((resolve, reject) => {
|
|
1203
|
+
const taxonomies = [];
|
|
1204
|
+
const stream = fastcsv.parseStream(fastcsv.parse());
|
|
1205
|
+
stream.write(data);
|
|
1206
|
+
stream.end();
|
|
1207
|
+
stream
|
|
1208
|
+
.on('data', (data) => {
|
|
1209
|
+
taxonomies.push(data);
|
|
1210
|
+
})
|
|
1211
|
+
.on('error', (err) => reject(err))
|
|
1212
|
+
.on('end', () => {
|
|
1213
|
+
taxonomies[0]?.forEach((header) => {
|
|
1214
|
+
if (!headers.includes(header)) headers.push(header);
|
|
1215
|
+
});
|
|
1216
|
+
resolve(taxonomies.splice(1));
|
|
1217
|
+
});
|
|
1218
|
+
});
|
|
1219
|
+
};
|
|
1167
1220
|
|
|
1168
1221
|
module.exports = {
|
|
1169
1222
|
chooseOrganization: chooseOrganization,
|