@contentstack/cli-cm-export-to-csv 1.4.0 → 1.4.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/package.json +4 -4
- package/src/commands/cm/export-to-csv.js +1 -1
- package/src/util/index.js +34 -11
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-cm-export-to-csv",
|
|
3
3
|
"description": "Export entities to csv",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.2",
|
|
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.5.
|
|
8
|
+
"@contentstack/cli-command": "~1.2.12",
|
|
9
|
+
"@contentstack/cli-utilities": "~1.5.2",
|
|
10
10
|
"chalk": "^4.1.0",
|
|
11
11
|
"fast-csv": "^4.3.6",
|
|
12
12
|
"inquirer": "8.2.4",
|
|
13
13
|
"inquirer-checkbox-plus-prompt": "1.0.1",
|
|
14
|
-
"mkdirp": "^
|
|
14
|
+
"mkdirp": "^3.0.1"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"@oclif/test": "^2.2.10",
|
|
@@ -207,7 +207,7 @@ class ExportToCsvCommand extends Command {
|
|
|
207
207
|
const entriesCount = await util.getEntriesCount(stackAPIClient, contentType, language.code);
|
|
208
208
|
let flatEntries = [];
|
|
209
209
|
for (let index = 0; index < entriesCount / 100; index++) {
|
|
210
|
-
const entriesResult = await util.getEntries(stackAPIClient, contentType, language.code, index);
|
|
210
|
+
const entriesResult = await util.getEntries(stackAPIClient, contentType, language.code, index, 100);
|
|
211
211
|
const flatEntriesResult = util.cleanEntries(
|
|
212
212
|
entriesResult.items,
|
|
213
213
|
language.code,
|
package/src/util/index.js
CHANGED
|
@@ -199,7 +199,7 @@ function chooseContentType(stackAPIClient, skip) {
|
|
|
199
199
|
let _chooseContentType = [
|
|
200
200
|
{
|
|
201
201
|
type: 'checkbox',
|
|
202
|
-
message: 'Choose Content Type',
|
|
202
|
+
message: 'Choose Content Type (Press Space to select the content types) ',
|
|
203
203
|
choices: contentTypesList,
|
|
204
204
|
name: 'chosenContentTypes',
|
|
205
205
|
loop: false,
|
|
@@ -218,7 +218,7 @@ function chooseInMemContentTypes(contentTypesList) {
|
|
|
218
218
|
let _chooseContentType = [
|
|
219
219
|
{
|
|
220
220
|
type: 'checkbox-plus',
|
|
221
|
-
message: 'Choose Content Type',
|
|
221
|
+
message: 'Choose Content Type (Press Space to select the content types)',
|
|
222
222
|
choices: contentTypesList,
|
|
223
223
|
name: 'chosenContentTypes',
|
|
224
224
|
loop: false,
|
|
@@ -316,12 +316,12 @@ function getLanguages(stackAPIClient) {
|
|
|
316
316
|
});
|
|
317
317
|
}
|
|
318
318
|
|
|
319
|
-
function getEntries(stackAPIClient, contentType, language, skip) {
|
|
319
|
+
function getEntries(stackAPIClient, contentType, language, skip, limit) {
|
|
320
320
|
return new Promise((resolve, reject) => {
|
|
321
321
|
stackAPIClient
|
|
322
322
|
.contentType(contentType)
|
|
323
323
|
.entry()
|
|
324
|
-
.query({ include_publish_details: true, locale: language, skip: skip * 100 })
|
|
324
|
+
.query({ include_publish_details: true, locale: language, skip: skip * 100, limit: limit, include_workflow: true })
|
|
325
325
|
.find()
|
|
326
326
|
.then((entries) => resolve(entries))
|
|
327
327
|
.catch((error) => reject(error));
|
|
@@ -371,27 +371,50 @@ function exitProgram() {
|
|
|
371
371
|
process.exit();
|
|
372
372
|
}
|
|
373
373
|
|
|
374
|
+
function sanitizeEntries(flatEntry) {
|
|
375
|
+
// sanitize against CSV Injections
|
|
376
|
+
const CSVRegex = /^[\\+\\=@\\-]/
|
|
377
|
+
for (key in flatEntry) {
|
|
378
|
+
if (typeof flatEntry[key] === 'string' && flatEntry[key].match(CSVRegex)) {
|
|
379
|
+
flatEntry[key] = flatEntry[key].replace(/\"/g, "\"\"");
|
|
380
|
+
flatEntry[key] = `"'${flatEntry[key]}"`
|
|
381
|
+
} else if (typeof flatEntry[key] === 'object') {
|
|
382
|
+
// convert any objects or arrays to string
|
|
383
|
+
// to store this data correctly in csv
|
|
384
|
+
flatEntry[key] = JSON.stringify(flatEntry[key]);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return flatEntry;
|
|
388
|
+
}
|
|
389
|
+
|
|
374
390
|
function cleanEntries(entries, language, environments, contentTypeUid) {
|
|
375
391
|
const filteredEntries = entries.filter((entry) => {
|
|
376
|
-
return entry['locale'] === language
|
|
392
|
+
return entry['locale'] === language;
|
|
377
393
|
});
|
|
378
|
-
|
|
379
394
|
return filteredEntries.map((entry) => {
|
|
380
395
|
let workflow = '';
|
|
381
396
|
const envArr = [];
|
|
382
|
-
entry.publish_details.
|
|
383
|
-
|
|
384
|
-
|
|
397
|
+
if(entry.publish_details.length) {
|
|
398
|
+
entry.publish_details.forEach((env) => {
|
|
399
|
+
envArr.push(JSON.stringify([environments[env['environment']], env['locale'], env['time']]));
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
|
|
385
403
|
delete entry.publish_details;
|
|
404
|
+
delete entry.setWorkflowStage;
|
|
386
405
|
if ('_workflow' in entry) {
|
|
387
|
-
|
|
388
|
-
|
|
406
|
+
if(entry._workflow?.name) {
|
|
407
|
+
workflow = entry['_workflow']['name'];
|
|
408
|
+
delete entry['_workflow'];
|
|
409
|
+
}
|
|
389
410
|
}
|
|
390
411
|
entry = flatten(entry);
|
|
412
|
+
entry = sanitizeEntries(entry);
|
|
391
413
|
entry['publish_details'] = envArr;
|
|
392
414
|
entry['_workflow'] = workflow;
|
|
393
415
|
entry['ACL'] = JSON.stringify({}); // setting ACL to empty obj
|
|
394
416
|
entry['content_type_uid'] = contentTypeUid; // content_type_uid is being returned as 'uid' from the sdk for some reason
|
|
417
|
+
|
|
395
418
|
// entry['url'] might also be wrong
|
|
396
419
|
delete entry.stackHeaders;
|
|
397
420
|
delete entry.update;
|