@contentstack/cli-cm-export-to-csv 2.0.0-beta.1 → 2.0.0-beta.2
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/lib/base-command.d.ts +40 -0
- package/lib/base-command.js +48 -0
- package/lib/commands/cm/export-to-csv.d.ts +52 -0
- package/lib/commands/cm/export-to-csv.js +581 -0
- package/lib/config/index.d.ts +9 -0
- package/lib/config/index.js +11 -0
- package/lib/index.d.ts +13 -0
- package/lib/index.js +19 -0
- package/lib/messages/index.d.ts +56 -0
- package/lib/messages/index.js +74 -0
- package/lib/types/index.d.ts +591 -0
- package/lib/types/index.js +8 -0
- package/lib/utils/api-client.d.ts +81 -0
- package/lib/utils/api-client.js +523 -0
- package/lib/utils/csv-writer.d.ts +24 -0
- package/lib/utils/csv-writer.js +70 -0
- package/lib/utils/data-transform.d.ts +66 -0
- package/lib/utils/data-transform.js +348 -0
- package/lib/utils/error-handler.d.ts +35 -0
- package/lib/utils/error-handler.js +111 -0
- package/lib/utils/index.d.ts +10 -0
- package/lib/utils/index.js +73 -0
- package/lib/utils/interactive.d.ts +41 -0
- package/lib/utils/interactive.js +336 -0
- package/lib/utils/teams-export.d.ts +24 -0
- package/lib/utils/teams-export.js +173 -0
- package/oclif.manifest.json +171 -0
- package/package.json +5 -5
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Interactive prompt utilities.
|
|
4
|
+
* Migrated from: packages/contentstack-export-to-csv/src/util/index.js
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.startupQuestions = startupQuestions;
|
|
8
|
+
exports.chooseOrganization = chooseOrganization;
|
|
9
|
+
exports.chooseStack = chooseStack;
|
|
10
|
+
exports.chooseBranch = chooseBranch;
|
|
11
|
+
exports.chooseContentType = chooseContentType;
|
|
12
|
+
exports.chooseInMemContentTypes = chooseInMemContentTypes;
|
|
13
|
+
exports.chooseLanguage = chooseLanguage;
|
|
14
|
+
exports.chooseFallbackOptions = chooseFallbackOptions;
|
|
15
|
+
exports.promptContinueExport = promptContinueExport;
|
|
16
|
+
const tslib_1 = require("tslib");
|
|
17
|
+
const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
|
|
18
|
+
// @ts-ignore - no types available
|
|
19
|
+
const inquirer_checkbox_plus_prompt_1 = tslib_1.__importDefault(require("inquirer-checkbox-plus-prompt"));
|
|
20
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
21
|
+
const messages_1 = require("../messages");
|
|
22
|
+
const error_handler_1 = require("./error-handler");
|
|
23
|
+
const api_client_1 = require("./api-client");
|
|
24
|
+
// Register checkbox-plus prompt type
|
|
25
|
+
inquirer_1.default.registerPrompt('checkbox-plus', inquirer_checkbox_plus_prompt_1.default);
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Startup Questions
|
|
28
|
+
// ============================================================================
|
|
29
|
+
/**
|
|
30
|
+
* Display startup questions to choose an action.
|
|
31
|
+
*/
|
|
32
|
+
function startupQuestions() {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const actions = [
|
|
35
|
+
{
|
|
36
|
+
type: 'list',
|
|
37
|
+
name: 'action',
|
|
38
|
+
message: 'Choose Action',
|
|
39
|
+
choices: [messages_1.messages.ACTION_EXPORT_ENTRIES, messages_1.messages.ACTION_EXPORT_USERS, messages_1.messages.ACTION_EXPORT_TEAMS, messages_1.messages.ACTION_EXPORT_TAXONOMIES, 'Exit'],
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
inquirer_1.default
|
|
43
|
+
.prompt(actions)
|
|
44
|
+
.then((answers) => {
|
|
45
|
+
if (answers.action === 'Exit')
|
|
46
|
+
(0, error_handler_1.exitProgram)();
|
|
47
|
+
resolve(answers.action);
|
|
48
|
+
})
|
|
49
|
+
.catch(reject);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
// ============================================================================
|
|
53
|
+
// Organization Prompts
|
|
54
|
+
// ============================================================================
|
|
55
|
+
/**
|
|
56
|
+
* Prompt user to choose an organization.
|
|
57
|
+
*/
|
|
58
|
+
function chooseOrganization(managementAPIClient, action) {
|
|
59
|
+
return new Promise(async (resolve, reject) => {
|
|
60
|
+
try {
|
|
61
|
+
let organizations;
|
|
62
|
+
if (action === messages_1.messages.ACTION_EXPORT_USERS || action === messages_1.messages.ACTION_EXPORT_TEAMS || action === 'teams') {
|
|
63
|
+
organizations = await (0, api_client_1.getOrganizationsWhereUserIsAdmin)(managementAPIClient);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
organizations = await (0, api_client_1.getOrganizations)(managementAPIClient);
|
|
67
|
+
}
|
|
68
|
+
const orgList = Object.keys(organizations);
|
|
69
|
+
orgList.push(messages_1.messages.ACTION_CANCEL);
|
|
70
|
+
const _chooseOrganization = [
|
|
71
|
+
{
|
|
72
|
+
type: 'list',
|
|
73
|
+
name: 'chosenOrg',
|
|
74
|
+
message: 'Choose an Organization',
|
|
75
|
+
choices: orgList,
|
|
76
|
+
loop: false,
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
inquirer_1.default
|
|
80
|
+
.prompt(_chooseOrganization)
|
|
81
|
+
.then((answers) => {
|
|
82
|
+
const chosenOrg = answers.chosenOrg;
|
|
83
|
+
if (chosenOrg === messages_1.messages.ACTION_CANCEL)
|
|
84
|
+
(0, error_handler_1.exitProgram)();
|
|
85
|
+
resolve({ name: chosenOrg, uid: organizations[chosenOrg] });
|
|
86
|
+
})
|
|
87
|
+
.catch(reject);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
reject(error);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
// ============================================================================
|
|
95
|
+
// Stack Prompts
|
|
96
|
+
// ============================================================================
|
|
97
|
+
/**
|
|
98
|
+
* Prompt user to choose a stack.
|
|
99
|
+
*/
|
|
100
|
+
function chooseStack(managementAPIClient, orgUid, stackApiKey) {
|
|
101
|
+
return new Promise(async (resolve, reject) => {
|
|
102
|
+
try {
|
|
103
|
+
const stacks = await (0, api_client_1.getStacks)(managementAPIClient, orgUid);
|
|
104
|
+
if (stackApiKey) {
|
|
105
|
+
const stackName = Object.keys(stacks).find((key) => stacks[key] === stackApiKey);
|
|
106
|
+
if (stackName) {
|
|
107
|
+
resolve({ name: stackName, apiKey: stackApiKey });
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
throw new Error('Could not find stack');
|
|
111
|
+
}
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const stackList = Object.keys(stacks);
|
|
115
|
+
stackList.push(messages_1.messages.ACTION_CANCEL);
|
|
116
|
+
const _chooseStack = [
|
|
117
|
+
{
|
|
118
|
+
type: 'list',
|
|
119
|
+
name: 'chosenStack',
|
|
120
|
+
message: 'Choose a Stack',
|
|
121
|
+
choices: stackList,
|
|
122
|
+
},
|
|
123
|
+
];
|
|
124
|
+
inquirer_1.default
|
|
125
|
+
.prompt(_chooseStack)
|
|
126
|
+
.then((answers) => {
|
|
127
|
+
const chosenStack = answers.chosenStack;
|
|
128
|
+
if (chosenStack === messages_1.messages.ACTION_CANCEL)
|
|
129
|
+
(0, error_handler_1.exitProgram)();
|
|
130
|
+
resolve({ name: chosenStack, apiKey: stacks[chosenStack] });
|
|
131
|
+
})
|
|
132
|
+
.catch(reject);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
reject(error);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// Branch Prompts
|
|
141
|
+
// ============================================================================
|
|
142
|
+
/**
|
|
143
|
+
* Prompt user to choose a branch.
|
|
144
|
+
*/
|
|
145
|
+
async function chooseBranch(branchList) {
|
|
146
|
+
try {
|
|
147
|
+
const branchesArray = branchList.map((branch) => branch.uid);
|
|
148
|
+
const _chooseBranch = [
|
|
149
|
+
{
|
|
150
|
+
type: 'list',
|
|
151
|
+
name: 'branch',
|
|
152
|
+
message: 'Choose a Branch',
|
|
153
|
+
choices: branchesArray,
|
|
154
|
+
},
|
|
155
|
+
];
|
|
156
|
+
const answers = await inquirer_1.default.prompt(_chooseBranch);
|
|
157
|
+
return { branch: answers.branch };
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
cli_utilities_1.cliux.error(err);
|
|
161
|
+
throw err;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// ============================================================================
|
|
165
|
+
// Content Type Prompts
|
|
166
|
+
// ============================================================================
|
|
167
|
+
/**
|
|
168
|
+
* Prompt user to choose content types (basic checkbox).
|
|
169
|
+
*/
|
|
170
|
+
function chooseContentType(stackAPIClient, skip) {
|
|
171
|
+
return new Promise(async (resolve, reject) => {
|
|
172
|
+
const { getContentTypes } = await Promise.resolve().then(() => tslib_1.__importStar(require('./api-client')));
|
|
173
|
+
const contentTypes = await getContentTypes(stackAPIClient, skip);
|
|
174
|
+
const contentTypesList = Object.values(contentTypes);
|
|
175
|
+
const _chooseContentType = [
|
|
176
|
+
{
|
|
177
|
+
type: 'checkbox',
|
|
178
|
+
message: 'Choose Content Type (Press Space to select the content types) ',
|
|
179
|
+
choices: contentTypesList,
|
|
180
|
+
name: 'chosenContentTypes',
|
|
181
|
+
loop: false,
|
|
182
|
+
},
|
|
183
|
+
];
|
|
184
|
+
inquirer_1.default
|
|
185
|
+
.prompt(_chooseContentType)
|
|
186
|
+
.then((answers) => resolve(answers.chosenContentTypes))
|
|
187
|
+
.catch(reject);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Prompt user to choose content types (searchable multi-select).
|
|
192
|
+
*/
|
|
193
|
+
function chooseInMemContentTypes(contentTypesList) {
|
|
194
|
+
return new Promise((resolve, reject) => {
|
|
195
|
+
const source = (_answersSoFar, input) => {
|
|
196
|
+
input = input || '';
|
|
197
|
+
const inputArray = input.split(' ');
|
|
198
|
+
return new Promise((resolveSource) => {
|
|
199
|
+
const contentTypes = contentTypesList.filter((contentType) => {
|
|
200
|
+
let shouldInclude = true;
|
|
201
|
+
inputArray.forEach((inputChunk) => {
|
|
202
|
+
// if any term to filter by doesn't exist, exclude
|
|
203
|
+
if (!contentType.toLowerCase().includes(inputChunk.toLowerCase())) {
|
|
204
|
+
shouldInclude = false;
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
return shouldInclude;
|
|
208
|
+
});
|
|
209
|
+
resolveSource(contentTypes);
|
|
210
|
+
});
|
|
211
|
+
};
|
|
212
|
+
const _chooseContentType = [
|
|
213
|
+
{
|
|
214
|
+
type: 'checkbox-plus',
|
|
215
|
+
message: 'Choose Content Type (Press Space to select the content types)',
|
|
216
|
+
choices: contentTypesList,
|
|
217
|
+
name: 'chosenContentTypes',
|
|
218
|
+
loop: false,
|
|
219
|
+
highlight: true,
|
|
220
|
+
searchable: true,
|
|
221
|
+
source,
|
|
222
|
+
},
|
|
223
|
+
];
|
|
224
|
+
inquirer_1.default
|
|
225
|
+
.prompt(_chooseContentType)
|
|
226
|
+
.then((answers) => {
|
|
227
|
+
const chosenContentTypes = answers.chosenContentTypes;
|
|
228
|
+
if (chosenContentTypes.length === 0) {
|
|
229
|
+
reject('Please select atleast one content type.');
|
|
230
|
+
}
|
|
231
|
+
resolve(chosenContentTypes);
|
|
232
|
+
})
|
|
233
|
+
.catch(reject);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
// ============================================================================
|
|
237
|
+
// Language Prompts
|
|
238
|
+
// ============================================================================
|
|
239
|
+
/**
|
|
240
|
+
* Prompt user to choose a language/locale.
|
|
241
|
+
*/
|
|
242
|
+
function chooseLanguage(stackAPIClient) {
|
|
243
|
+
return new Promise(async (resolve, reject) => {
|
|
244
|
+
const languages = await (0, api_client_1.getLanguages)(stackAPIClient);
|
|
245
|
+
const languagesList = Object.keys(languages);
|
|
246
|
+
languagesList.push(messages_1.messages.ACTION_CANCEL);
|
|
247
|
+
const _chooseLanguage = [
|
|
248
|
+
{
|
|
249
|
+
type: 'list',
|
|
250
|
+
message: 'Choose Language',
|
|
251
|
+
choices: languagesList,
|
|
252
|
+
name: 'chosenLanguage',
|
|
253
|
+
},
|
|
254
|
+
];
|
|
255
|
+
inquirer_1.default
|
|
256
|
+
.prompt(_chooseLanguage)
|
|
257
|
+
.then((answers) => {
|
|
258
|
+
const chosenLanguage = answers.chosenLanguage;
|
|
259
|
+
if (chosenLanguage === messages_1.messages.ACTION_CANCEL)
|
|
260
|
+
(0, error_handler_1.exitProgram)();
|
|
261
|
+
resolve({ name: chosenLanguage, code: languages[chosenLanguage] });
|
|
262
|
+
})
|
|
263
|
+
.catch(reject);
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
// ============================================================================
|
|
267
|
+
// Fallback Options Prompts
|
|
268
|
+
// ============================================================================
|
|
269
|
+
/**
|
|
270
|
+
* Prompt user for fallback options.
|
|
271
|
+
*/
|
|
272
|
+
function chooseFallbackOptions(stackAPIClient) {
|
|
273
|
+
return new Promise(async (resolve, reject) => {
|
|
274
|
+
try {
|
|
275
|
+
const questions = [
|
|
276
|
+
{
|
|
277
|
+
type: 'confirm',
|
|
278
|
+
name: 'includeFallback',
|
|
279
|
+
message: 'Include fallback locale data when exporting taxonomies?',
|
|
280
|
+
default: false,
|
|
281
|
+
},
|
|
282
|
+
];
|
|
283
|
+
const firstAnswers = await inquirer_1.default.prompt(questions);
|
|
284
|
+
const includeFallback = firstAnswers.includeFallback;
|
|
285
|
+
let fallbackLocale = null;
|
|
286
|
+
if (includeFallback) {
|
|
287
|
+
// Get available languages for fallback locale selection
|
|
288
|
+
const languages = await (0, api_client_1.getLanguages)(stackAPIClient);
|
|
289
|
+
const languagesList = Object.keys(languages);
|
|
290
|
+
const fallbackQuestion = [
|
|
291
|
+
{
|
|
292
|
+
type: 'list',
|
|
293
|
+
name: 'selectedFallbackLocale',
|
|
294
|
+
message: 'Choose fallback locale',
|
|
295
|
+
choices: languagesList,
|
|
296
|
+
},
|
|
297
|
+
];
|
|
298
|
+
const secondAnswers = await inquirer_1.default.prompt(fallbackQuestion);
|
|
299
|
+
const selectedFallbackLocale = secondAnswers.selectedFallbackLocale;
|
|
300
|
+
fallbackLocale = languages[selectedFallbackLocale];
|
|
301
|
+
}
|
|
302
|
+
resolve({
|
|
303
|
+
includeFallback,
|
|
304
|
+
fallbackLocale,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
reject(error);
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
// ============================================================================
|
|
313
|
+
// Team Export Prompts
|
|
314
|
+
// ============================================================================
|
|
315
|
+
/**
|
|
316
|
+
* Prompt to continue exporting without certain fields.
|
|
317
|
+
*/
|
|
318
|
+
async function promptContinueExport() {
|
|
319
|
+
const export_stack_role = [
|
|
320
|
+
{
|
|
321
|
+
type: 'list',
|
|
322
|
+
name: 'chooseExport',
|
|
323
|
+
message: 'Access denied: Please confirm if you still want to continue exporting the data without the { Stack Name, Stack Uid, Role Name } fields.',
|
|
324
|
+
choices: ['yes', 'no'],
|
|
325
|
+
loop: false,
|
|
326
|
+
},
|
|
327
|
+
];
|
|
328
|
+
try {
|
|
329
|
+
const answers = await inquirer_1.default.prompt(export_stack_role);
|
|
330
|
+
return answers.chooseExport === 'yes';
|
|
331
|
+
}
|
|
332
|
+
catch (error) {
|
|
333
|
+
cli_utilities_1.cliux.print(error, { color: 'red' });
|
|
334
|
+
process.exit(1);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Team export utilities.
|
|
3
|
+
* Migrated from: packages/contentstack-export-to-csv/src/util/index.js
|
|
4
|
+
*
|
|
5
|
+
* These are composite functions that use multiple utilities together
|
|
6
|
+
* for team export functionality.
|
|
7
|
+
*/
|
|
8
|
+
import type { ManagementClient, OrganizationChoice, CleanedTeam, StackRoleMapping, StackRoleMappingCsvRow } from '../types';
|
|
9
|
+
/**
|
|
10
|
+
* Export teams data for an organization.
|
|
11
|
+
*/
|
|
12
|
+
export declare function exportTeams(managementAPIClient: ManagementClient, organization: OrganizationChoice, teamUid: string | undefined, delimiter: string): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Get individual team user details and write to file.
|
|
15
|
+
*/
|
|
16
|
+
export declare function getTeamsDetail(allTeamsData: CleanedTeam[], organization: OrganizationChoice, teamUid: string | undefined, delimiter: string): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Export role mappings of teams to CSV.
|
|
19
|
+
*/
|
|
20
|
+
export declare function exportRoleMappings(managementAPIClient: ManagementClient, allTeamsData: CleanedTeam[], teamUid: string | undefined, delimiter: string): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Map team stacks with stack role and return array of objects.
|
|
23
|
+
*/
|
|
24
|
+
export declare function mapRoleWithTeams(managementAPIClient: ManagementClient, stackRoleMapping: StackRoleMapping, teamName: string, teamUid: string): Promise<StackRoleMappingCsvRow[]>;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Team export utilities.
|
|
4
|
+
* Migrated from: packages/contentstack-export-to-csv/src/util/index.js
|
|
5
|
+
*
|
|
6
|
+
* These are composite functions that use multiple utilities together
|
|
7
|
+
* for team export functionality.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.exportTeams = exportTeams;
|
|
11
|
+
exports.getTeamsDetail = getTeamsDetail;
|
|
12
|
+
exports.exportRoleMappings = exportRoleMappings;
|
|
13
|
+
exports.mapRoleWithTeams = mapRoleWithTeams;
|
|
14
|
+
const tslib_1 = require("tslib");
|
|
15
|
+
const find_1 = tslib_1.__importDefault(require("lodash/find"));
|
|
16
|
+
const cloneDeep_1 = tslib_1.__importDefault(require("lodash/cloneDeep"));
|
|
17
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
18
|
+
const config_1 = tslib_1.__importDefault(require("../config"));
|
|
19
|
+
const csv_writer_1 = require("./csv-writer");
|
|
20
|
+
const data_transform_1 = require("./data-transform");
|
|
21
|
+
const api_client_1 = require("./api-client");
|
|
22
|
+
const interactive_1 = require("./interactive");
|
|
23
|
+
/**
|
|
24
|
+
* Export teams data for an organization.
|
|
25
|
+
*/
|
|
26
|
+
async function exportTeams(managementAPIClient, organization, teamUid, delimiter) {
|
|
27
|
+
const logContext = { module: 'teams-export', orgUid: organization.uid, teamUid };
|
|
28
|
+
cli_utilities_1.log.debug('Starting teams export', logContext);
|
|
29
|
+
cli_utilities_1.cliux.print(`info: Exporting the ${teamUid && (organization === null || organization === void 0 ? void 0 : organization.name)
|
|
30
|
+
? `team with uid ${teamUid} in Organisation ${organization === null || organization === void 0 ? void 0 : organization.name} `
|
|
31
|
+
: `teams of Organisation ` + (organization === null || organization === void 0 ? void 0 : organization.name)}`, { color: 'blue' });
|
|
32
|
+
cli_utilities_1.cliux.loader('Fetching teams...');
|
|
33
|
+
const allTeamsData = await (0, api_client_1.exportOrgTeams)(managementAPIClient, organization);
|
|
34
|
+
cli_utilities_1.cliux.loader();
|
|
35
|
+
if (!(allTeamsData === null || allTeamsData === void 0 ? void 0 : allTeamsData.length)) {
|
|
36
|
+
cli_utilities_1.log.info('No teams found', logContext);
|
|
37
|
+
cli_utilities_1.cliux.print(`info: The organization ${organization === null || organization === void 0 ? void 0 : organization.name} does not have any teams associated with it. Please verify and provide the correct organization name.`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
cli_utilities_1.log.debug(`Found ${allTeamsData.length} teams`, logContext);
|
|
41
|
+
const modifiedTeam = (0, cloneDeep_1.default)(allTeamsData).map((team) => {
|
|
42
|
+
const csvRow = {
|
|
43
|
+
uid: team.uid,
|
|
44
|
+
name: team.name,
|
|
45
|
+
description: team.description,
|
|
46
|
+
organizationRole: team.organizationRole,
|
|
47
|
+
Total_Members: team.Total_Members,
|
|
48
|
+
};
|
|
49
|
+
return csvRow;
|
|
50
|
+
});
|
|
51
|
+
const fileName = `${(0, data_transform_1.kebabize)(organization.name.replace(config_1.default.organizationNameRegex, ''))}_teams_export.csv`;
|
|
52
|
+
cli_utilities_1.log.info(`Writing teams to ${fileName}`, logContext);
|
|
53
|
+
(0, csv_writer_1.write)(null, modifiedTeam, fileName, ' organization Team details', delimiter);
|
|
54
|
+
// Exporting teams user data or a single team user data
|
|
55
|
+
cli_utilities_1.cliux.print(`info: Exporting the teams user data for ${teamUid ? `team ` + teamUid : `organisation ` + (organization === null || organization === void 0 ? void 0 : organization.name)}`, { color: 'blue' });
|
|
56
|
+
await getTeamsDetail(allTeamsData, organization, teamUid, delimiter);
|
|
57
|
+
cli_utilities_1.cliux.print(`info: Exporting the stack role details for ${teamUid ? `team ` + teamUid : `organisation ` + (organization === null || organization === void 0 ? void 0 : organization.name)}`, { color: 'blue' });
|
|
58
|
+
// Exporting the stack Role data for all the teams or exporting stack role data for a single team
|
|
59
|
+
await exportRoleMappings(managementAPIClient, allTeamsData, teamUid, delimiter);
|
|
60
|
+
cli_utilities_1.log.success('Teams export completed', logContext);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get individual team user details and write to file.
|
|
64
|
+
*/
|
|
65
|
+
async function getTeamsDetail(allTeamsData, organization, teamUid, delimiter) {
|
|
66
|
+
const logContext = { module: 'teams-export', action: 'team-users', teamUid };
|
|
67
|
+
cli_utilities_1.log.debug('Exporting team user details', logContext);
|
|
68
|
+
if (!teamUid) {
|
|
69
|
+
const userData = (0, data_transform_1.getTeamsUserDetails)(allTeamsData);
|
|
70
|
+
const fileName = `${(0, data_transform_1.kebabize)(organization.name.replace(config_1.default.organizationNameRegex, ''))}_team_User_Details_export.csv`;
|
|
71
|
+
cli_utilities_1.log.info(`Writing ${userData.length} team users to ${fileName}`, logContext);
|
|
72
|
+
(0, csv_writer_1.write)(null, userData, fileName, 'Team User details', delimiter);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const team = allTeamsData.filter((t) => t.uid === teamUid)[0];
|
|
76
|
+
if (!team) {
|
|
77
|
+
cli_utilities_1.log.debug('Team not found', Object.assign(Object.assign({}, logContext), { teamUid }));
|
|
78
|
+
cli_utilities_1.cliux.print(`Team with UID ${teamUid} not found.`, { color: 'red' });
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const teamUsers = (team.users || []).map((user) => (Object.assign(Object.assign({}, user), { 'team-name': team.name, 'team-uid': team.uid })));
|
|
82
|
+
// Remove unwanted properties
|
|
83
|
+
teamUsers.forEach((user) => {
|
|
84
|
+
delete user.active;
|
|
85
|
+
delete user.orgInvitationStatus;
|
|
86
|
+
});
|
|
87
|
+
const fileName = `${(0, data_transform_1.kebabize)(organization.name.replace(config_1.default.organizationNameRegex, ''))}_team_${teamUid}_User_Details_export.csv`;
|
|
88
|
+
cli_utilities_1.log.info(`Writing ${teamUsers.length} users for team ${teamUid} to ${fileName}`, logContext);
|
|
89
|
+
(0, csv_writer_1.write)(null, teamUsers, fileName, 'Team User details', delimiter);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Export role mappings of teams to CSV.
|
|
94
|
+
*/
|
|
95
|
+
async function exportRoleMappings(managementAPIClient, allTeamsData, teamUid, delimiter) {
|
|
96
|
+
var _a;
|
|
97
|
+
const logContext = { module: 'teams-export', action: 'role-mappings', teamUid };
|
|
98
|
+
cli_utilities_1.log.debug('Exporting role mappings', logContext);
|
|
99
|
+
const stackRoleWithTeamData = [];
|
|
100
|
+
let flag = false;
|
|
101
|
+
const stackNotAdmin = [];
|
|
102
|
+
cli_utilities_1.cliux.loader('Fetching stack role mappings...');
|
|
103
|
+
if (teamUid) {
|
|
104
|
+
const team = (0, find_1.default)(allTeamsData, function (teamObject) {
|
|
105
|
+
return (teamObject === null || teamObject === void 0 ? void 0 : teamObject.uid) === teamUid;
|
|
106
|
+
});
|
|
107
|
+
for (const stack of (team === null || team === void 0 ? void 0 : team.stackRoleMapping) || []) {
|
|
108
|
+
const roleData = await mapRoleWithTeams(managementAPIClient, stack, (team === null || team === void 0 ? void 0 : team.name) || '', (team === null || team === void 0 ? void 0 : team.uid) || '');
|
|
109
|
+
stackRoleWithTeamData.push(...roleData);
|
|
110
|
+
if (roleData[0]['Stack Name'] === '') {
|
|
111
|
+
flag = true;
|
|
112
|
+
stackNotAdmin.push(stack.stackApiKey);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
for (const team of allTeamsData !== null && allTeamsData !== void 0 ? allTeamsData : []) {
|
|
118
|
+
for (const stack of (_a = team === null || team === void 0 ? void 0 : team.stackRoleMapping) !== null && _a !== void 0 ? _a : []) {
|
|
119
|
+
const roleData = await mapRoleWithTeams(managementAPIClient, stack, team === null || team === void 0 ? void 0 : team.name, team === null || team === void 0 ? void 0 : team.uid);
|
|
120
|
+
stackRoleWithTeamData.push(...roleData);
|
|
121
|
+
if (roleData[0]['Stack Name'] === '') {
|
|
122
|
+
flag = true;
|
|
123
|
+
stackNotAdmin.push(stack.stackApiKey);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
cli_utilities_1.cliux.loader();
|
|
129
|
+
if (stackNotAdmin === null || stackNotAdmin === void 0 ? void 0 : stackNotAdmin.length) {
|
|
130
|
+
cli_utilities_1.log.debug('Admin access denied to some stacks', Object.assign(Object.assign({}, logContext), { stacks: stackNotAdmin }));
|
|
131
|
+
cli_utilities_1.cliux.print(`warning: Admin access denied to the following stacks using the provided API keys. Please get in touch with the stack owner to request access.`, { color: 'yellow' });
|
|
132
|
+
cli_utilities_1.cliux.print(`${stackNotAdmin.join(' , ')}`, { color: 'yellow' });
|
|
133
|
+
}
|
|
134
|
+
if (flag) {
|
|
135
|
+
const shouldContinue = await (0, interactive_1.promptContinueExport)();
|
|
136
|
+
if (!shouldContinue) {
|
|
137
|
+
cli_utilities_1.log.debug('User chose not to continue export', logContext);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const fileName = `${(0, data_transform_1.kebabize)('Stack_Role_Mapping'.replace(config_1.default.organizationNameRegex, ''))}${teamUid ? `_${teamUid}` : ''}.csv`;
|
|
142
|
+
cli_utilities_1.log.info(`Writing ${stackRoleWithTeamData.length} role mappings to ${fileName}`, logContext);
|
|
143
|
+
(0, csv_writer_1.write)(null, stackRoleWithTeamData, fileName, 'Team Stack Role details', delimiter);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Map team stacks with stack role and return array of objects.
|
|
147
|
+
*/
|
|
148
|
+
async function mapRoleWithTeams(managementAPIClient, stackRoleMapping, teamName, teamUid) {
|
|
149
|
+
var _a;
|
|
150
|
+
const rolesResponse = await (0, api_client_1.getRoleData)(managementAPIClient, stackRoleMapping.stackApiKey);
|
|
151
|
+
const stackRole = {};
|
|
152
|
+
(_a = rolesResponse.items) === null || _a === void 0 ? void 0 : _a.forEach((role) => {
|
|
153
|
+
var _a;
|
|
154
|
+
if (!Object.prototype.hasOwnProperty.call(stackRole, role === null || role === void 0 ? void 0 : role.uid)) {
|
|
155
|
+
stackRole[role === null || role === void 0 ? void 0 : role.uid] = role === null || role === void 0 ? void 0 : role.name;
|
|
156
|
+
if ((_a = role === null || role === void 0 ? void 0 : role.stack) === null || _a === void 0 ? void 0 : _a.api_key) {
|
|
157
|
+
stackRole[role.stack.api_key] = { name: role.stack.name, uid: role.stack.uid };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
const stackInfo = stackRole[stackRoleMapping === null || stackRoleMapping === void 0 ? void 0 : stackRoleMapping.stackApiKey];
|
|
162
|
+
const stackRoleMapOfTeam = stackRoleMapping === null || stackRoleMapping === void 0 ? void 0 : stackRoleMapping.roles.map((role) => {
|
|
163
|
+
return {
|
|
164
|
+
'Team Name': teamName,
|
|
165
|
+
'Team Uid': teamUid,
|
|
166
|
+
'Stack Name': (stackInfo === null || stackInfo === void 0 ? void 0 : stackInfo.name) || '',
|
|
167
|
+
'Stack Uid': (stackInfo === null || stackInfo === void 0 ? void 0 : stackInfo.uid) || '',
|
|
168
|
+
'Role Name': stackRole[role] || '',
|
|
169
|
+
'Role Uid': role || '',
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
return stackRoleMapOfTeam;
|
|
173
|
+
}
|