@contentstack/cli-cm-export-to-csv 1.3.8 → 1.3.10
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/oclif.manifest.json +18 -3
- package/package.json +4 -3
- package/src/commands/cm/export-to-csv.js +91 -15
- package/src/util/index.js +43 -11
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.3.
|
|
2
|
+
"version": "1.3.10",
|
|
3
3
|
"commands": {
|
|
4
4
|
"cm:export-to-csv": {
|
|
5
5
|
"id": "cm:export-to-csv",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"Exporting entries to csv",
|
|
16
16
|
"csdx cm:export-to-csv --action <entries> --locale <locale> --alias <management-token-alias> --content-type <content-type>",
|
|
17
17
|
"",
|
|
18
|
-
"Exporting entries to csv with stack name provided",
|
|
19
|
-
"csdx cm:export-to-csv --action <entries> --locale <locale> --alias <management-token-alias> --content-type <content-type> --stack-name <stack-name>",
|
|
18
|
+
"Exporting entries to csv with stack name provided and branch name provided",
|
|
19
|
+
"csdx cm:export-to-csv --action <entries> --locale <locale> --alias <management-token-alias> --content-type <content-type> --stack-name <stack-name> --branch <branch-name>",
|
|
20
20
|
"",
|
|
21
21
|
"Exporting organization users to csv",
|
|
22
22
|
"csdx cm:export-to-csv --action <users> --org <org-uid>",
|
|
@@ -58,6 +58,14 @@
|
|
|
58
58
|
"required": false,
|
|
59
59
|
"multiple": false
|
|
60
60
|
},
|
|
61
|
+
"stack-api-key": {
|
|
62
|
+
"name": "stack-api-key",
|
|
63
|
+
"type": "option",
|
|
64
|
+
"char": "k",
|
|
65
|
+
"description": "API key of the source stack",
|
|
66
|
+
"required": false,
|
|
67
|
+
"multiple": false
|
|
68
|
+
},
|
|
61
69
|
"org-name": {
|
|
62
70
|
"name": "org-name",
|
|
63
71
|
"type": "option",
|
|
@@ -78,6 +86,13 @@
|
|
|
78
86
|
"description": "Content type for which entries needs to be exported",
|
|
79
87
|
"required": false,
|
|
80
88
|
"multiple": false
|
|
89
|
+
},
|
|
90
|
+
"branch": {
|
|
91
|
+
"name": "branch",
|
|
92
|
+
"type": "option",
|
|
93
|
+
"description": "Branch from which entries need to be exported",
|
|
94
|
+
"required": false,
|
|
95
|
+
"multiple": false
|
|
81
96
|
}
|
|
82
97
|
},
|
|
83
98
|
"args": {}
|
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.3.
|
|
4
|
+
"version": "1.3.10",
|
|
5
5
|
"author": "Abhinav Gupta @abhinav-from-contentstack",
|
|
6
6
|
"bugs": "https://github.com/contentstack/cli/issues",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@contentstack/cli-command": "^1.2.
|
|
9
|
-
"@contentstack/cli-utilities": "^1.4.
|
|
8
|
+
"@contentstack/cli-command": "^1.2.9",
|
|
9
|
+
"@contentstack/cli-utilities": "^1.4.5",
|
|
10
10
|
"chalk": "^4.1.0",
|
|
11
11
|
"fast-csv": "^4.3.6",
|
|
12
12
|
"inquirer": "8.2.4",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"postpack": "rm -f oclif.manifest.json",
|
|
45
45
|
"prepack": "oclif manifest && oclif readme",
|
|
46
46
|
"test": "nyc mocha --forbid-only \"test/**/*.test.js\"",
|
|
47
|
+
"test:unit": "nyc mocha --timeout 10000 --forbid-only \"test/unit/**/*.test.js\"",
|
|
47
48
|
"version": "oclif readme && git add README.md",
|
|
48
49
|
"clean": "rm -rf ./node_modules tsconfig.build.tsbuildinfo"
|
|
49
50
|
},
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
const { Command } = require('@contentstack/cli-command');
|
|
2
|
-
const {
|
|
2
|
+
const {
|
|
3
|
+
configHandler,
|
|
4
|
+
managementSDKClient,
|
|
5
|
+
flags,
|
|
6
|
+
isAuthenticated,
|
|
7
|
+
cliux,
|
|
8
|
+
doesBranchExist,
|
|
9
|
+
} = require('@contentstack/cli-utilities');
|
|
3
10
|
const util = require('../../util');
|
|
4
11
|
const config = require('../../util/config');
|
|
5
12
|
|
|
@@ -26,6 +33,12 @@ class ExportToCsvCommand extends Command {
|
|
|
26
33
|
required: false,
|
|
27
34
|
description: 'Name of the stack that needs to be created as csv filename.',
|
|
28
35
|
}),
|
|
36
|
+
'stack-api-key': flags.string({
|
|
37
|
+
char: 'k',
|
|
38
|
+
multiple: false,
|
|
39
|
+
required: false,
|
|
40
|
+
description: 'API key of the source stack',
|
|
41
|
+
}),
|
|
29
42
|
'org-name': flags.string({
|
|
30
43
|
multiple: false,
|
|
31
44
|
required: false,
|
|
@@ -41,6 +54,11 @@ class ExportToCsvCommand extends Command {
|
|
|
41
54
|
required: false,
|
|
42
55
|
multiple: false,
|
|
43
56
|
}),
|
|
57
|
+
branch: flags.string({
|
|
58
|
+
description: 'Branch from which entries need to be exported',
|
|
59
|
+
multiple: false,
|
|
60
|
+
required: false,
|
|
61
|
+
}),
|
|
44
62
|
};
|
|
45
63
|
|
|
46
64
|
async run() {
|
|
@@ -52,9 +70,11 @@ class ExportToCsvCommand extends Command {
|
|
|
52
70
|
action: actionFlag,
|
|
53
71
|
'org-name': orgName,
|
|
54
72
|
'stack-name': stackName,
|
|
73
|
+
'stack-api-key': stackAPIKey,
|
|
55
74
|
locale: locale,
|
|
56
75
|
'content-type': contentTypesFlag,
|
|
57
76
|
alias: managementTokenAlias,
|
|
77
|
+
branch: branchUid,
|
|
58
78
|
},
|
|
59
79
|
} = await this.parse(ExportToCsvCommand);
|
|
60
80
|
|
|
@@ -76,6 +96,7 @@ class ExportToCsvCommand extends Command {
|
|
|
76
96
|
let stackAPIClient;
|
|
77
97
|
let language;
|
|
78
98
|
let contentTypes = [];
|
|
99
|
+
let stackBranches;
|
|
79
100
|
const listOfTokens = configHandler.get('tokens');
|
|
80
101
|
|
|
81
102
|
if (managementTokenAlias && listOfTokens[managementTokenAlias]) {
|
|
@@ -105,16 +126,59 @@ class ExportToCsvCommand extends Command {
|
|
|
105
126
|
} else {
|
|
106
127
|
organization = await util.chooseOrganization(managementAPIClient); // prompt for organization
|
|
107
128
|
}
|
|
108
|
-
|
|
109
|
-
|
|
129
|
+
if (!stackAPIKey) {
|
|
130
|
+
stack = await util.chooseStack(managementAPIClient, organization.uid); // prompt for stack
|
|
131
|
+
} else {
|
|
132
|
+
stack = await util.chooseStack(managementAPIClient, organization.uid, stackAPIKey);
|
|
133
|
+
}
|
|
110
134
|
}
|
|
111
135
|
|
|
112
136
|
stackAPIClient = this.getStackClient(managementAPIClient, stack);
|
|
137
|
+
|
|
138
|
+
if (branchUid) {
|
|
139
|
+
try {
|
|
140
|
+
const branchExists = await doesBranchExist(stackAPIClient, branchUid);
|
|
141
|
+
if (branchExists?.errorCode) {
|
|
142
|
+
throw new Error(branchExists.errorMessage);
|
|
143
|
+
}
|
|
144
|
+
stack.branch_uid = branchUid;
|
|
145
|
+
stackAPIClient = this.getStackClient(managementAPIClient, stack);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
if (error.message || error.errorMessage) {
|
|
148
|
+
cliux.error(util.formatError(error));
|
|
149
|
+
this.exit();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
stackBranches = await this.getStackBranches(stackAPIClient);
|
|
154
|
+
if (stackBranches === undefined) {
|
|
155
|
+
stackAPIClient = this.getStackClient(managementAPIClient, stack);
|
|
156
|
+
} else {
|
|
157
|
+
const { branch } = await util.chooseBranch(stackBranches);
|
|
158
|
+
stack.branch_uid = branch;
|
|
159
|
+
stackAPIClient = this.getStackClient(managementAPIClient, stack);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
113
163
|
const contentTypeCount = await util.getContentTypeCount(stackAPIClient);
|
|
164
|
+
|
|
114
165
|
const environments = await util.getEnvironments(stackAPIClient); // fetch environments, because in publish details only env uid are available and we need env names
|
|
115
166
|
|
|
116
167
|
if (contentTypesFlag) {
|
|
117
168
|
contentTypes = contentTypesFlag.split(',').map(this.snakeCase);
|
|
169
|
+
const contentTypesArray = await stackAPIClient
|
|
170
|
+
.contentType()
|
|
171
|
+
.query()
|
|
172
|
+
.find()
|
|
173
|
+
.then((res) => res.items.map((contentType) => contentType.uid));
|
|
174
|
+
|
|
175
|
+
const doesContentTypeExist = contentTypesArray.includes(contentTypesFlag);
|
|
176
|
+
|
|
177
|
+
if (!doesContentTypeExist) {
|
|
178
|
+
throw new Error(
|
|
179
|
+
`The Content Type ${contentTypesFlag} was not found. Please try again. Content Type is not valid.`,
|
|
180
|
+
);
|
|
181
|
+
}
|
|
118
182
|
} else {
|
|
119
183
|
for (let index = 0; index <= contentTypeCount / 100; index++) {
|
|
120
184
|
const contentTypesMap = await util.getContentTypes(stackAPIClient, index);
|
|
@@ -152,12 +216,11 @@ class ExportToCsvCommand extends Command {
|
|
|
152
216
|
);
|
|
153
217
|
flatEntries = flatEntries.concat(flatEntriesResult);
|
|
154
218
|
}
|
|
155
|
-
let fileName = `${stack.name}_${contentType}_${language.code}_entries_export.csv`;
|
|
156
|
-
|
|
219
|
+
let fileName = `${stackName ? stackName : stack.name}_${contentType}_${language.code}_entries_export.csv`;
|
|
157
220
|
util.write(this, flatEntries, fileName, 'entries'); // write to file
|
|
158
221
|
}
|
|
159
222
|
} catch (error) {
|
|
160
|
-
|
|
223
|
+
cliux.error(util.formatError(error));
|
|
161
224
|
}
|
|
162
225
|
break;
|
|
163
226
|
}
|
|
@@ -184,21 +247,21 @@ class ExportToCsvCommand extends Command {
|
|
|
184
247
|
const mappedRoles = util.getMappedRoles(orgRoles);
|
|
185
248
|
const listOfUsers = util.cleanOrgUsers(orgUsers, mappedUsers, mappedRoles);
|
|
186
249
|
const fileName = `${util.kebabize(
|
|
187
|
-
organization.name.replace(config.organizationNameRegex, ''),
|
|
250
|
+
(orgName ? orgName : organization.name).replace(config.organizationNameRegex, ''),
|
|
188
251
|
)}_users_export.csv`;
|
|
189
252
|
|
|
190
253
|
util.write(this, listOfUsers, fileName, 'organization details');
|
|
191
254
|
} catch (error) {
|
|
192
|
-
if (error.message) {
|
|
193
|
-
|
|
255
|
+
if (error.message || error.errorMessage) {
|
|
256
|
+
cliux.error(util.formatError(error));
|
|
194
257
|
}
|
|
195
258
|
}
|
|
196
259
|
break;
|
|
197
260
|
}
|
|
198
261
|
}
|
|
199
262
|
} catch (error) {
|
|
200
|
-
if (error.message) {
|
|
201
|
-
|
|
263
|
+
if (error.message || error.errorMessage) {
|
|
264
|
+
cliux.error(util.formatError(error));
|
|
202
265
|
}
|
|
203
266
|
}
|
|
204
267
|
}
|
|
@@ -208,13 +271,26 @@ class ExportToCsvCommand extends Command {
|
|
|
208
271
|
}
|
|
209
272
|
|
|
210
273
|
getStackClient(managementAPIClient, stack) {
|
|
274
|
+
const stackInit = {
|
|
275
|
+
api_key: stack.apiKey,
|
|
276
|
+
branch_uid: stack.branch_uid,
|
|
277
|
+
};
|
|
211
278
|
if (stack.token) {
|
|
212
279
|
return managementAPIClient.stack({
|
|
213
|
-
|
|
280
|
+
...stackInit,
|
|
214
281
|
management_token: stack.token,
|
|
215
282
|
});
|
|
216
283
|
}
|
|
217
|
-
return managementAPIClient.stack(
|
|
284
|
+
return managementAPIClient.stack(stackInit);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
getStackBranches(stackAPIClient) {
|
|
288
|
+
return stackAPIClient
|
|
289
|
+
.branch()
|
|
290
|
+
.query()
|
|
291
|
+
.find()
|
|
292
|
+
.then(({ items }) => (items !== undefined ? items : []))
|
|
293
|
+
.catch((_err) => {});
|
|
218
294
|
}
|
|
219
295
|
}
|
|
220
296
|
|
|
@@ -226,8 +302,8 @@ ExportToCsvCommand.examples = [
|
|
|
226
302
|
'Exporting entries to csv',
|
|
227
303
|
'csdx cm:export-to-csv --action <entries> --locale <locale> --alias <management-token-alias> --content-type <content-type>',
|
|
228
304
|
'',
|
|
229
|
-
'Exporting entries to csv with stack name provided',
|
|
230
|
-
'csdx cm:export-to-csv --action <entries> --locale <locale> --alias <management-token-alias> --content-type <content-type> --stack-name <stack-name>',
|
|
305
|
+
'Exporting entries to csv with stack name provided and branch name provided',
|
|
306
|
+
'csdx cm:export-to-csv --action <entries> --locale <locale> --alias <management-token-alias> --content-type <content-type> --stack-name <stack-name> --branch <branch-name>',
|
|
231
307
|
'',
|
|
232
308
|
'Exporting organization users to csv',
|
|
233
309
|
'csdx cm:export-to-csv --action <users> --org <org-uid>',
|
package/src/util/index.js
CHANGED
|
@@ -8,6 +8,7 @@ const debug = require('debug')('export-to-csv');
|
|
|
8
8
|
const checkboxPlus = require('inquirer-checkbox-plus-prompt');
|
|
9
9
|
|
|
10
10
|
const config = require('./config.js');
|
|
11
|
+
const { cliux } = require('@contentstack/cli-utilities');
|
|
11
12
|
|
|
12
13
|
const directory = './data';
|
|
13
14
|
const delimeter = os.platform() === 'win32' ? '\\' : '/';
|
|
@@ -97,13 +98,24 @@ function getOrganizationsWhereUserIsAdmin(managementAPIClient) {
|
|
|
97
98
|
});
|
|
98
99
|
}
|
|
99
100
|
|
|
100
|
-
function chooseStack(managementAPIClient, orgUid) {
|
|
101
|
+
function chooseStack(managementAPIClient, orgUid, stackApiKey) {
|
|
101
102
|
return new Promise(async (resolve, reject) => {
|
|
102
103
|
try {
|
|
103
104
|
let stacks = await getStacks(managementAPIClient, orgUid);
|
|
105
|
+
|
|
106
|
+
if (stackApiKey) {
|
|
107
|
+
const stackName = Object.keys(stacks).find((key) => stacks[key] === stackApiKey);
|
|
108
|
+
|
|
109
|
+
if (stackName) {
|
|
110
|
+
resolve({ name: stackName, apiKey: stackApiKey });
|
|
111
|
+
} else {
|
|
112
|
+
throw new Error('Could not find stack');
|
|
113
|
+
}
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
104
117
|
let stackList = Object.keys(stacks);
|
|
105
118
|
stackList.push(config.cancelString);
|
|
106
|
-
|
|
107
119
|
let _chooseStack = [
|
|
108
120
|
{
|
|
109
121
|
type: 'list',
|
|
@@ -126,6 +138,26 @@ function chooseStack(managementAPIClient, orgUid) {
|
|
|
126
138
|
});
|
|
127
139
|
}
|
|
128
140
|
|
|
141
|
+
async function chooseBranch(branchList) {
|
|
142
|
+
try {
|
|
143
|
+
const branches = await branchList;
|
|
144
|
+
|
|
145
|
+
const branchesArray = branches.map((branch) => branch.uid);
|
|
146
|
+
|
|
147
|
+
let _chooseBranch = [
|
|
148
|
+
{
|
|
149
|
+
type: 'list',
|
|
150
|
+
name: 'branch',
|
|
151
|
+
message: 'Choose a Branch',
|
|
152
|
+
choices: branchesArray,
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
return await inquirer.prompt(_chooseBranch);
|
|
156
|
+
} catch (err) {
|
|
157
|
+
cliux.error(err);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
129
161
|
function getStacks(managementAPIClient, orgUid) {
|
|
130
162
|
return new Promise((resolve, reject) => {
|
|
131
163
|
let result = {};
|
|
@@ -167,7 +199,7 @@ function chooseContentType(stackAPIClient, skip) {
|
|
|
167
199
|
}
|
|
168
200
|
|
|
169
201
|
function chooseInMemContentTypes(contentTypesList) {
|
|
170
|
-
return new Promise(
|
|
202
|
+
return new Promise((resolve, reject) => {
|
|
171
203
|
let _chooseContentType = [
|
|
172
204
|
{
|
|
173
205
|
type: 'checkbox-plus',
|
|
@@ -213,7 +245,7 @@ function getContentTypes(stackAPIClient, skip) {
|
|
|
213
245
|
let result = {};
|
|
214
246
|
stackAPIClient
|
|
215
247
|
.contentType()
|
|
216
|
-
.query({ skip: skip * 100 })
|
|
248
|
+
.query({ skip: skip * 100, include_branch: true })
|
|
217
249
|
.find()
|
|
218
250
|
.then((contentTypes) => {
|
|
219
251
|
contentTypes.items.forEach((contentType) => {
|
|
@@ -221,7 +253,9 @@ function getContentTypes(stackAPIClient, skip) {
|
|
|
221
253
|
});
|
|
222
254
|
resolve(result);
|
|
223
255
|
})
|
|
224
|
-
.catch((error) =>
|
|
256
|
+
.catch((error) => {
|
|
257
|
+
reject(error);
|
|
258
|
+
});
|
|
225
259
|
});
|
|
226
260
|
}
|
|
227
261
|
|
|
@@ -376,7 +410,7 @@ function write(command, entries, fileName, message) {
|
|
|
376
410
|
process.chdir(directory);
|
|
377
411
|
}
|
|
378
412
|
// eslint-disable-next-line no-undef
|
|
379
|
-
|
|
413
|
+
cliux.print(`Writing ${message} to file: ${process.cwd()}${delimeter}${fileName}`);
|
|
380
414
|
fastcsv.writeToPath(fileName, entries, { headers: true });
|
|
381
415
|
}
|
|
382
416
|
|
|
@@ -400,7 +434,7 @@ function startupQuestions() {
|
|
|
400
434
|
});
|
|
401
435
|
}
|
|
402
436
|
|
|
403
|
-
function getOrgUsers(managementAPIClient, orgUid
|
|
437
|
+
function getOrgUsers(managementAPIClient, orgUid) {
|
|
404
438
|
return new Promise((resolve, reject) => {
|
|
405
439
|
managementAPIClient
|
|
406
440
|
.getUser({ include_orgs_roles: true })
|
|
@@ -442,10 +476,7 @@ async function getUsers(managementAPIClient, organization, params, result = [])
|
|
|
442
476
|
await wait(200);
|
|
443
477
|
return getUsers(managementAPIClient, organization, params, result);
|
|
444
478
|
}
|
|
445
|
-
} catch (error) {
|
|
446
|
-
console.error(error);
|
|
447
|
-
throw error;
|
|
448
|
-
}
|
|
479
|
+
} catch (error) {}
|
|
449
480
|
}
|
|
450
481
|
|
|
451
482
|
function getMappedUsers(users) {
|
|
@@ -612,6 +643,7 @@ function wait(time) {
|
|
|
612
643
|
module.exports = {
|
|
613
644
|
chooseOrganization: chooseOrganization,
|
|
614
645
|
chooseStack: chooseStack,
|
|
646
|
+
chooseBranch: chooseBranch,
|
|
615
647
|
chooseContentType: chooseContentType,
|
|
616
648
|
chooseLanguage: chooseLanguage,
|
|
617
649
|
getEntries: getEntries,
|