@contentstack/cli-cm-export-to-csv 1.10.2 → 1.11.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/bin/dev.cmd +2 -0
- package/bin/dev.js +7 -0
- package/bin/run.cmd +2 -0
- package/bin/run.js +7 -0
- 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 +73 -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 +41 -28
- package/src/commands/cm/export-to-csv.js +0 -523
- package/src/util/client.js +0 -0
- package/src/util/config.js +0 -13
- package/src/util/index.js +0 -1313
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* API client utilities.
|
|
4
|
+
* Migrated from: packages/contentstack-export-to-csv/src/util/index.js
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.getOrganizations = getOrganizations;
|
|
8
|
+
exports.getOrganizationsWhereUserIsAdmin = getOrganizationsWhereUserIsAdmin;
|
|
9
|
+
exports.getOrgUsers = getOrgUsers;
|
|
10
|
+
exports.getOrgRoles = getOrgRoles;
|
|
11
|
+
exports.getStacks = getStacks;
|
|
12
|
+
exports.getContentTypeCount = getContentTypeCount;
|
|
13
|
+
exports.getContentTypes = getContentTypes;
|
|
14
|
+
exports.getLanguages = getLanguages;
|
|
15
|
+
exports.getEntriesCount = getEntriesCount;
|
|
16
|
+
exports.getEntries = getEntries;
|
|
17
|
+
exports.getEnvironments = getEnvironments;
|
|
18
|
+
exports.getAllTeams = getAllTeams;
|
|
19
|
+
exports.exportOrgTeams = exportOrgTeams;
|
|
20
|
+
exports.getRoleData = getRoleData;
|
|
21
|
+
exports.taxonomySDKHandler = taxonomySDKHandler;
|
|
22
|
+
exports.getAllTaxonomies = getAllTaxonomies;
|
|
23
|
+
exports.getAllTermsOfTaxonomy = getAllTermsOfTaxonomy;
|
|
24
|
+
exports.getTaxonomy = getTaxonomy;
|
|
25
|
+
exports.createImportableCSV = createImportableCSV;
|
|
26
|
+
const tslib_1 = require("tslib");
|
|
27
|
+
const find_1 = tslib_1.__importDefault(require("lodash/find"));
|
|
28
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
29
|
+
const config_1 = tslib_1.__importDefault(require("../config"));
|
|
30
|
+
const messages_1 = require("../messages");
|
|
31
|
+
const error_handler_1 = require("./error-handler");
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// Organization APIs
|
|
34
|
+
// ============================================================================
|
|
35
|
+
/**
|
|
36
|
+
* Get all organizations the user has access to.
|
|
37
|
+
*/
|
|
38
|
+
async function getOrganizations(managementAPIClient) {
|
|
39
|
+
try {
|
|
40
|
+
return await getOrganizationList(managementAPIClient, { skip: 0, page: 1, limit: 100 }, []);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get organization list with pagination.
|
|
48
|
+
*/
|
|
49
|
+
async function getOrganizationList(managementAPIClient, params, result = []) {
|
|
50
|
+
let organizations;
|
|
51
|
+
const configOrgUid = cli_utilities_1.configHandler.get('oauthOrgUid');
|
|
52
|
+
if (configOrgUid) {
|
|
53
|
+
organizations = await managementAPIClient.organization(configOrgUid).fetch();
|
|
54
|
+
result = result.concat([organizations]);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const response = await managementAPIClient.organization().fetchAll({ limit: 100 });
|
|
58
|
+
organizations = response;
|
|
59
|
+
result = result.concat(response.items);
|
|
60
|
+
}
|
|
61
|
+
if (!organizations.items || (organizations.items && organizations.items.length < params.limit)) {
|
|
62
|
+
const orgMap = {};
|
|
63
|
+
for (const org of result) {
|
|
64
|
+
orgMap[org.name] = org.uid;
|
|
65
|
+
}
|
|
66
|
+
return orgMap;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
params.skip = params.page * params.limit;
|
|
70
|
+
params.page++;
|
|
71
|
+
await (0, error_handler_1.wait)(200);
|
|
72
|
+
return getOrganizationList(managementAPIClient, params, result);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get organizations where user is admin.
|
|
77
|
+
*/
|
|
78
|
+
async function getOrganizationsWhereUserIsAdmin(managementAPIClient) {
|
|
79
|
+
try {
|
|
80
|
+
const result = {};
|
|
81
|
+
const configOrgUid = cli_utilities_1.configHandler.get('oauthOrgUid');
|
|
82
|
+
if (configOrgUid) {
|
|
83
|
+
const response = await managementAPIClient.organization(configOrgUid).fetch();
|
|
84
|
+
result[response.name] = response.uid;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const response = await managementAPIClient.getUser({ include_orgs_roles: true });
|
|
88
|
+
const organizations = response.organizations.filter((org) => {
|
|
89
|
+
if (org.org_roles) {
|
|
90
|
+
const org_role = org.org_roles.shift();
|
|
91
|
+
return org_role === null || org_role === void 0 ? void 0 : org_role.admin;
|
|
92
|
+
}
|
|
93
|
+
return org.is_owner === true;
|
|
94
|
+
});
|
|
95
|
+
organizations.forEach((org) => {
|
|
96
|
+
result[org.name] = org.uid;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get organization users.
|
|
107
|
+
*/
|
|
108
|
+
function getOrgUsers(managementAPIClient, orgUid) {
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
managementAPIClient
|
|
111
|
+
.getUser({ include_orgs_roles: true })
|
|
112
|
+
.then(async (response) => {
|
|
113
|
+
const userResponse = response;
|
|
114
|
+
const organization = userResponse.organizations.filter((org) => org.uid === orgUid).pop();
|
|
115
|
+
if (!organization) {
|
|
116
|
+
return reject(new Error('Org UID not found.'));
|
|
117
|
+
}
|
|
118
|
+
if (organization.is_owner === true) {
|
|
119
|
+
return managementAPIClient
|
|
120
|
+
.organization(organization.uid)
|
|
121
|
+
.getInvitations()
|
|
122
|
+
.then((data) => {
|
|
123
|
+
resolve(data);
|
|
124
|
+
})
|
|
125
|
+
.catch(reject);
|
|
126
|
+
}
|
|
127
|
+
if (!organization.getInvitations && !(0, find_1.default)(organization.org_roles, 'admin')) {
|
|
128
|
+
return reject(new Error(messages_1.messages.ERROR_ADMIN_ACCESS_DENIED));
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const users = await getUsers(managementAPIClient, { uid: organization.uid }, { skip: 0, page: 1, limit: 100 });
|
|
132
|
+
return resolve({ items: users || [] });
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
return reject(error);
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
.catch((error) => reject(error));
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get users with pagination.
|
|
143
|
+
*/
|
|
144
|
+
async function getUsers(managementAPIClient, organization, params, result = []) {
|
|
145
|
+
try {
|
|
146
|
+
const users = await managementAPIClient.organization(organization.uid).getInvitations(params);
|
|
147
|
+
if (!users.items || (users.items && !users.items.length)) {
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
result = result.concat(users.items);
|
|
152
|
+
params.skip = params.page * params.limit;
|
|
153
|
+
params.page++;
|
|
154
|
+
await (0, error_handler_1.wait)(200);
|
|
155
|
+
return getUsers(managementAPIClient, organization, params, result);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
catch (_a) {
|
|
159
|
+
return result;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Get organization roles.
|
|
164
|
+
*/
|
|
165
|
+
function getOrgRoles(managementAPIClient, orgUid) {
|
|
166
|
+
return new Promise((resolve, reject) => {
|
|
167
|
+
managementAPIClient
|
|
168
|
+
.getUser({ include_orgs_roles: true })
|
|
169
|
+
.then((response) => {
|
|
170
|
+
const userResponse = response;
|
|
171
|
+
const organization = userResponse.organizations.filter((org) => org.uid === orgUid).pop();
|
|
172
|
+
if (!organization) {
|
|
173
|
+
return reject(new Error('Org UID not found.'));
|
|
174
|
+
}
|
|
175
|
+
if (organization.is_owner === true) {
|
|
176
|
+
return managementAPIClient
|
|
177
|
+
.organization(organization.uid)
|
|
178
|
+
.roles()
|
|
179
|
+
.then((roles) => {
|
|
180
|
+
resolve(roles);
|
|
181
|
+
})
|
|
182
|
+
.catch(reject);
|
|
183
|
+
}
|
|
184
|
+
if (!organization.roles && !(0, find_1.default)(organization.org_roles, 'admin')) {
|
|
185
|
+
return reject(new Error(messages_1.messages.ERROR_ADMIN_ACCESS_DENIED));
|
|
186
|
+
}
|
|
187
|
+
managementAPIClient
|
|
188
|
+
.organization(organization.uid)
|
|
189
|
+
.roles()
|
|
190
|
+
.then((roles) => {
|
|
191
|
+
resolve(roles);
|
|
192
|
+
})
|
|
193
|
+
.catch(reject);
|
|
194
|
+
})
|
|
195
|
+
.catch((error) => reject(error));
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
// ============================================================================
|
|
199
|
+
// Stack APIs
|
|
200
|
+
// ============================================================================
|
|
201
|
+
/**
|
|
202
|
+
* Get all stacks in an organization.
|
|
203
|
+
*/
|
|
204
|
+
function getStacks(managementAPIClient, orgUid) {
|
|
205
|
+
return new Promise((resolve, reject) => {
|
|
206
|
+
const result = {};
|
|
207
|
+
managementAPIClient
|
|
208
|
+
.stack({ organization_uid: orgUid })
|
|
209
|
+
.query({ query: {} })
|
|
210
|
+
.find()
|
|
211
|
+
.then((stacks) => {
|
|
212
|
+
const stacksResponse = stacks;
|
|
213
|
+
stacksResponse.items.forEach((stack) => {
|
|
214
|
+
result[stack.name] = stack.api_key;
|
|
215
|
+
});
|
|
216
|
+
resolve(result);
|
|
217
|
+
})
|
|
218
|
+
.catch((error) => {
|
|
219
|
+
reject(error);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
// ============================================================================
|
|
224
|
+
// Content Type APIs
|
|
225
|
+
// ============================================================================
|
|
226
|
+
/**
|
|
227
|
+
* Get content type count.
|
|
228
|
+
*/
|
|
229
|
+
function getContentTypeCount(stackAPIClient) {
|
|
230
|
+
return new Promise((resolve, reject) => {
|
|
231
|
+
stackAPIClient
|
|
232
|
+
.contentType()
|
|
233
|
+
.query()
|
|
234
|
+
.count()
|
|
235
|
+
.then((contentTypes) => {
|
|
236
|
+
const response = contentTypes;
|
|
237
|
+
resolve(response.content_types);
|
|
238
|
+
})
|
|
239
|
+
.catch((error) => reject(error));
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Get content types with pagination.
|
|
244
|
+
*/
|
|
245
|
+
function getContentTypes(stackAPIClient, skip) {
|
|
246
|
+
return new Promise((resolve, reject) => {
|
|
247
|
+
const result = {};
|
|
248
|
+
stackAPIClient
|
|
249
|
+
.contentType()
|
|
250
|
+
.query({ skip: skip * 100, include_branch: true })
|
|
251
|
+
.find()
|
|
252
|
+
.then((contentTypes) => {
|
|
253
|
+
const response = contentTypes;
|
|
254
|
+
response.items.forEach((contentType) => {
|
|
255
|
+
if (contentType.title) {
|
|
256
|
+
result[contentType.title] = contentType.uid;
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
resolve(result);
|
|
260
|
+
})
|
|
261
|
+
.catch((error) => {
|
|
262
|
+
reject(error);
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
// ============================================================================
|
|
267
|
+
// Language/Locale APIs
|
|
268
|
+
// ============================================================================
|
|
269
|
+
/**
|
|
270
|
+
* Get all languages/locales for a stack.
|
|
271
|
+
*/
|
|
272
|
+
function getLanguages(stackAPIClient) {
|
|
273
|
+
return new Promise((resolve, reject) => {
|
|
274
|
+
const result = {};
|
|
275
|
+
stackAPIClient
|
|
276
|
+
.locale()
|
|
277
|
+
.query()
|
|
278
|
+
.find()
|
|
279
|
+
.then((languages) => {
|
|
280
|
+
const response = languages;
|
|
281
|
+
response.items.forEach((language) => {
|
|
282
|
+
result[language.name] = language.code;
|
|
283
|
+
});
|
|
284
|
+
resolve(result);
|
|
285
|
+
})
|
|
286
|
+
.catch((error) => reject(error));
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
// ============================================================================
|
|
290
|
+
// Entry APIs
|
|
291
|
+
// ============================================================================
|
|
292
|
+
/**
|
|
293
|
+
* Get entry count for a content type.
|
|
294
|
+
*/
|
|
295
|
+
function getEntriesCount(stackAPIClient, contentType, language) {
|
|
296
|
+
return new Promise((resolve, reject) => {
|
|
297
|
+
stackAPIClient
|
|
298
|
+
.contentType(contentType)
|
|
299
|
+
.entry()
|
|
300
|
+
.query({ include_publish_details: true, locale: language })
|
|
301
|
+
.count()
|
|
302
|
+
.then((entriesData) => {
|
|
303
|
+
const response = entriesData;
|
|
304
|
+
resolve(response.entries);
|
|
305
|
+
})
|
|
306
|
+
.catch((error) => {
|
|
307
|
+
const { formatError } = require('./error-handler');
|
|
308
|
+
reject(formatError(error));
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Get entries with pagination.
|
|
314
|
+
*/
|
|
315
|
+
function getEntries(stackAPIClient, contentType, language, skip, limit) {
|
|
316
|
+
return new Promise((resolve, reject) => {
|
|
317
|
+
stackAPIClient
|
|
318
|
+
.contentType(contentType)
|
|
319
|
+
.entry()
|
|
320
|
+
.query({
|
|
321
|
+
include_publish_details: true,
|
|
322
|
+
locale: language,
|
|
323
|
+
skip: skip * 100,
|
|
324
|
+
limit: limit,
|
|
325
|
+
include_workflow: true,
|
|
326
|
+
})
|
|
327
|
+
.find()
|
|
328
|
+
.then((entries) => resolve(entries))
|
|
329
|
+
.catch((error) => reject(error));
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
// ============================================================================
|
|
333
|
+
// Environment APIs
|
|
334
|
+
// ============================================================================
|
|
335
|
+
/**
|
|
336
|
+
* Get all environments for a stack.
|
|
337
|
+
*/
|
|
338
|
+
function getEnvironments(stackAPIClient) {
|
|
339
|
+
const result = {};
|
|
340
|
+
return stackAPIClient
|
|
341
|
+
.environment()
|
|
342
|
+
.query()
|
|
343
|
+
.find()
|
|
344
|
+
.then((environments) => {
|
|
345
|
+
const response = environments;
|
|
346
|
+
response.items.forEach((env) => {
|
|
347
|
+
result[env.uid] = env.name;
|
|
348
|
+
});
|
|
349
|
+
return result;
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
// ============================================================================
|
|
353
|
+
// Team APIs
|
|
354
|
+
// ============================================================================
|
|
355
|
+
/**
|
|
356
|
+
* Get all teams in an organization.
|
|
357
|
+
*/
|
|
358
|
+
async function getAllTeams(managementAPIClient, org, queryParam = {}) {
|
|
359
|
+
try {
|
|
360
|
+
return await managementAPIClient.organization(org.uid).teams().fetchAll(queryParam);
|
|
361
|
+
}
|
|
362
|
+
catch (error) {
|
|
363
|
+
(0, error_handler_1.handleErrorMsg)(error);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Export all organization teams with pagination.
|
|
368
|
+
*/
|
|
369
|
+
async function exportOrgTeams(managementAPIClient, org) {
|
|
370
|
+
const { cleanTeamsData } = await Promise.resolve().then(() => tslib_1.__importStar(require('./data-transform')));
|
|
371
|
+
let allTeamsInOrg = [];
|
|
372
|
+
let skip = 0;
|
|
373
|
+
const limit = (config_1.default === null || config_1.default === void 0 ? void 0 : config_1.default.limit) || 100;
|
|
374
|
+
do {
|
|
375
|
+
const data = await getAllTeams(managementAPIClient, org, {
|
|
376
|
+
skip: skip,
|
|
377
|
+
limit: limit,
|
|
378
|
+
includeUserDetails: true,
|
|
379
|
+
});
|
|
380
|
+
skip += limit;
|
|
381
|
+
allTeamsInOrg.push(...data.items);
|
|
382
|
+
if (skip >= (data.count || 0))
|
|
383
|
+
break;
|
|
384
|
+
} while (true);
|
|
385
|
+
const cleanedTeams = await cleanTeamsData(allTeamsInOrg, managementAPIClient, org);
|
|
386
|
+
return cleanedTeams;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Get role data for a stack.
|
|
390
|
+
*/
|
|
391
|
+
async function getRoleData(managementAPIClient, stackApiKey) {
|
|
392
|
+
try {
|
|
393
|
+
return await managementAPIClient.stack({ api_key: stackApiKey }).role().fetchAll();
|
|
394
|
+
}
|
|
395
|
+
catch (_a) {
|
|
396
|
+
return { items: [] };
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
// ============================================================================
|
|
400
|
+
// Taxonomy APIs
|
|
401
|
+
// ============================================================================
|
|
402
|
+
/**
|
|
403
|
+
* Taxonomy & term SDK handler.
|
|
404
|
+
*/
|
|
405
|
+
async function taxonomySDKHandler(payload, skip) {
|
|
406
|
+
const { stackAPIClient, taxonomyUID, type, format, locale, branch, include_fallback, fallback_locale } = payload;
|
|
407
|
+
const queryParams = { include_count: true, limit: payload.limit };
|
|
408
|
+
if (skip !== undefined && skip >= 0)
|
|
409
|
+
queryParams.skip = skip || 0;
|
|
410
|
+
// Add locale and branch parameters if provided
|
|
411
|
+
if (locale)
|
|
412
|
+
queryParams.locale = locale;
|
|
413
|
+
if (branch)
|
|
414
|
+
queryParams.branch = branch;
|
|
415
|
+
if (include_fallback !== undefined)
|
|
416
|
+
queryParams.include_fallback = include_fallback;
|
|
417
|
+
if (fallback_locale)
|
|
418
|
+
queryParams.fallback_locale = fallback_locale;
|
|
419
|
+
switch (type) {
|
|
420
|
+
case 'taxonomies':
|
|
421
|
+
return await stackAPIClient
|
|
422
|
+
.taxonomy()
|
|
423
|
+
.query(queryParams)
|
|
424
|
+
.find()
|
|
425
|
+
.then((data) => data)
|
|
426
|
+
.catch((err) => (0, error_handler_1.handleTaxonomyErrorMsg)(err));
|
|
427
|
+
case 'taxonomy':
|
|
428
|
+
return await stackAPIClient
|
|
429
|
+
.taxonomy(taxonomyUID)
|
|
430
|
+
.fetch()
|
|
431
|
+
.then((data) => data)
|
|
432
|
+
.catch((err) => (0, error_handler_1.handleTaxonomyErrorMsg)(err));
|
|
433
|
+
case 'terms':
|
|
434
|
+
queryParams.depth = 0;
|
|
435
|
+
return await stackAPIClient
|
|
436
|
+
.taxonomy(taxonomyUID)
|
|
437
|
+
.terms()
|
|
438
|
+
.query(queryParams)
|
|
439
|
+
.find()
|
|
440
|
+
.then((data) => data)
|
|
441
|
+
.catch((err) => (0, error_handler_1.handleTaxonomyErrorMsg)(err));
|
|
442
|
+
case 'export-taxonomies':
|
|
443
|
+
const exportParams = { format };
|
|
444
|
+
if (locale)
|
|
445
|
+
exportParams.locale = locale;
|
|
446
|
+
if (branch)
|
|
447
|
+
exportParams.branch = branch;
|
|
448
|
+
if (include_fallback !== undefined)
|
|
449
|
+
exportParams.include_fallback = include_fallback;
|
|
450
|
+
if (fallback_locale)
|
|
451
|
+
exportParams.fallback_locale = fallback_locale;
|
|
452
|
+
return await stackAPIClient
|
|
453
|
+
.taxonomy(taxonomyUID)
|
|
454
|
+
.export(exportParams)
|
|
455
|
+
.then((data) => data)
|
|
456
|
+
.catch((err) => (0, error_handler_1.handleTaxonomyErrorMsg)(err));
|
|
457
|
+
default:
|
|
458
|
+
(0, error_handler_1.handleTaxonomyErrorMsg)({ errorMessage: 'Invalid module!' });
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Get all taxonomies in a stack.
|
|
463
|
+
*/
|
|
464
|
+
async function getAllTaxonomies(payload, skip = 0, taxonomies = []) {
|
|
465
|
+
payload.type = 'taxonomies';
|
|
466
|
+
const response = await taxonomySDKHandler(payload, skip);
|
|
467
|
+
if (response.items) {
|
|
468
|
+
skip += payload.limit;
|
|
469
|
+
taxonomies.push(...response.items);
|
|
470
|
+
if (skip >= response.count) {
|
|
471
|
+
return taxonomies;
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
return getAllTaxonomies(payload, skip, taxonomies);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return taxonomies;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Get all terms for a taxonomy.
|
|
481
|
+
*/
|
|
482
|
+
async function getAllTermsOfTaxonomy(payload, skip = 0, terms = []) {
|
|
483
|
+
payload.type = 'terms';
|
|
484
|
+
const response = await taxonomySDKHandler(payload, skip);
|
|
485
|
+
if (response.items) {
|
|
486
|
+
skip += payload.limit;
|
|
487
|
+
terms.push(...response.items);
|
|
488
|
+
if (skip >= response.count) {
|
|
489
|
+
return terms;
|
|
490
|
+
}
|
|
491
|
+
else {
|
|
492
|
+
return getAllTermsOfTaxonomy(payload, skip, terms);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return terms;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Get a single taxonomy by UID.
|
|
499
|
+
*/
|
|
500
|
+
async function getTaxonomy(payload) {
|
|
501
|
+
payload.type = 'taxonomy';
|
|
502
|
+
const resp = await taxonomySDKHandler(payload);
|
|
503
|
+
return resp;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Generate importable CSV data for taxonomies.
|
|
507
|
+
*/
|
|
508
|
+
async function createImportableCSV(payload, taxonomies) {
|
|
509
|
+
const { csvParse } = await Promise.resolve().then(() => tslib_1.__importStar(require('./csv-writer')));
|
|
510
|
+
const taxonomiesData = [];
|
|
511
|
+
const headers = [];
|
|
512
|
+
payload.type = 'export-taxonomies';
|
|
513
|
+
payload.format = 'csv';
|
|
514
|
+
for (const taxonomy of taxonomies) {
|
|
515
|
+
if (taxonomy === null || taxonomy === void 0 ? void 0 : taxonomy.uid) {
|
|
516
|
+
payload.taxonomyUID = taxonomy.uid;
|
|
517
|
+
const data = await taxonomySDKHandler(payload);
|
|
518
|
+
const parsedTaxonomies = await csvParse(data, headers);
|
|
519
|
+
taxonomiesData.push(...parsedTaxonomies);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
return { taxonomiesData, headers };
|
|
523
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSV writing utilities.
|
|
3
|
+
* Migrated from: packages/contentstack-export-to-csv/src/util/index.js
|
|
4
|
+
*/
|
|
5
|
+
import type { CsvRow } from '../types';
|
|
6
|
+
/**
|
|
7
|
+
* Write data to a CSV file.
|
|
8
|
+
*
|
|
9
|
+
* @param _command - Command instance (not used but kept for parity)
|
|
10
|
+
* @param entries - Array of objects or string arrays to write
|
|
11
|
+
* @param fileName - Name of the output file
|
|
12
|
+
* @param message - Message type for logging (e.g., 'entries', 'organization details')
|
|
13
|
+
* @param csvDelimiter - CSV delimiter character (default: ',')
|
|
14
|
+
* @param headers - Optional custom headers
|
|
15
|
+
*/
|
|
16
|
+
export declare function write(_command: unknown, entries: CsvRow[], fileName: string, message: string, csvDelimiter?: string, headers?: string[]): void;
|
|
17
|
+
/**
|
|
18
|
+
* Parse CSV data and extract headers.
|
|
19
|
+
*
|
|
20
|
+
* @param data - Raw CSV data string
|
|
21
|
+
* @param headers - Array to populate with headers (mutated)
|
|
22
|
+
* @returns Parsed data without header row
|
|
23
|
+
*/
|
|
24
|
+
export declare function csvParse(data: string, headers: string[]): Promise<string[][]>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CSV writing utilities.
|
|
4
|
+
* Migrated from: packages/contentstack-export-to-csv/src/util/index.js
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.write = write;
|
|
8
|
+
exports.csvParse = csvParse;
|
|
9
|
+
const tslib_1 = require("tslib");
|
|
10
|
+
const os = tslib_1.__importStar(require("os"));
|
|
11
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
12
|
+
const fastcsv = tslib_1.__importStar(require("fast-csv"));
|
|
13
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
14
|
+
const directory = './data';
|
|
15
|
+
const delimiter = os.platform() === 'win32' ? '\\' : '/';
|
|
16
|
+
/**
|
|
17
|
+
* Write data to a CSV file.
|
|
18
|
+
*
|
|
19
|
+
* @param _command - Command instance (not used but kept for parity)
|
|
20
|
+
* @param entries - Array of objects or string arrays to write
|
|
21
|
+
* @param fileName - Name of the output file
|
|
22
|
+
* @param message - Message type for logging (e.g., 'entries', 'organization details')
|
|
23
|
+
* @param csvDelimiter - CSV delimiter character (default: ',')
|
|
24
|
+
* @param headers - Optional custom headers
|
|
25
|
+
*/
|
|
26
|
+
function write(_command, entries, fileName, message, csvDelimiter, headers) {
|
|
27
|
+
// Create data directory if it doesn't exist
|
|
28
|
+
if (process.cwd().split(delimiter).pop() !== 'data' && !fs.existsSync(directory)) {
|
|
29
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
// Change to data directory if not already there
|
|
32
|
+
if (process.cwd().split(delimiter).pop() !== 'data') {
|
|
33
|
+
process.chdir(directory);
|
|
34
|
+
}
|
|
35
|
+
cli_utilities_1.cliux.print(`Writing ${message} to file: "${process.cwd()}${delimiter}${fileName}"`);
|
|
36
|
+
const writeOptions = {
|
|
37
|
+
headers: (headers === null || headers === void 0 ? void 0 : headers.length) ? headers : true,
|
|
38
|
+
delimiter: csvDelimiter || ',',
|
|
39
|
+
};
|
|
40
|
+
fastcsv.writeToPath(fileName, entries, writeOptions);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Parse CSV data and extract headers.
|
|
44
|
+
*
|
|
45
|
+
* @param data - Raw CSV data string
|
|
46
|
+
* @param headers - Array to populate with headers (mutated)
|
|
47
|
+
* @returns Parsed data without header row
|
|
48
|
+
*/
|
|
49
|
+
function csvParse(data, headers) {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
const taxonomies = [];
|
|
52
|
+
fastcsv
|
|
53
|
+
.parseString(data, { headers: false })
|
|
54
|
+
.on('data', (rowData) => {
|
|
55
|
+
taxonomies.push(rowData);
|
|
56
|
+
})
|
|
57
|
+
.on('error', (err) => reject(err))
|
|
58
|
+
.on('end', () => {
|
|
59
|
+
var _a;
|
|
60
|
+
// Extract headers from first row
|
|
61
|
+
(_a = taxonomies[0]) === null || _a === void 0 ? void 0 : _a.forEach((header) => {
|
|
62
|
+
if (!headers.includes(header)) {
|
|
63
|
+
headers.push(header);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
// Return data without header row
|
|
67
|
+
resolve(taxonomies.splice(1));
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data transformation utilities.
|
|
3
|
+
* Migrated from: packages/contentstack-export-to-csv/src/util/index.js
|
|
4
|
+
*/
|
|
5
|
+
import type { ManagementClient, RawEntry, FlattenedEntryRow, OrgUser, OrgUsersResponse, OrgRolesResponse, UserMap, RoleMap, OrgUserCsvRow, RawTeam, CleanedTeam, TeamUser, Taxonomy, TaxonomyCsvRow, Term, TermCsvRow, EnvironmentMap, OrganizationChoice } from '../types';
|
|
6
|
+
/**
|
|
7
|
+
* Flatten a nested object into a single-level object.
|
|
8
|
+
* Arrays are flattened with bracket notation (e.g., "field[0]").
|
|
9
|
+
*
|
|
10
|
+
* @see https://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objects
|
|
11
|
+
*/
|
|
12
|
+
export declare function flatten(data: Record<string, unknown>): Record<string, unknown>;
|
|
13
|
+
/**
|
|
14
|
+
* Sanitize data against CSV injection attacks.
|
|
15
|
+
* Prefixes potentially dangerous characters with a quote.
|
|
16
|
+
* Also converts objects/arrays to JSON strings.
|
|
17
|
+
*/
|
|
18
|
+
export declare function sanitizeData<T extends Record<string, unknown>>(flatData: T): T;
|
|
19
|
+
/**
|
|
20
|
+
* Clean and format entries for CSV export.
|
|
21
|
+
*/
|
|
22
|
+
export declare function cleanEntries(entries: RawEntry[], language: string, environments: EnvironmentMap, contentTypeUid: string): FlattenedEntryRow[];
|
|
23
|
+
/**
|
|
24
|
+
* Map user UIDs to emails.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getMappedUsers(users: OrgUsersResponse): UserMap;
|
|
27
|
+
/**
|
|
28
|
+
* Map role UIDs to names.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getMappedRoles(roles: OrgRolesResponse): RoleMap;
|
|
31
|
+
/**
|
|
32
|
+
* Determine a user's organization role.
|
|
33
|
+
*/
|
|
34
|
+
export declare function determineUserOrgRole(user: OrgUser, roles: RoleMap): string;
|
|
35
|
+
/**
|
|
36
|
+
* Clean and format organization users for CSV export.
|
|
37
|
+
*/
|
|
38
|
+
export declare function cleanOrgUsers(orgUsers: OrgUsersResponse, mappedUsers: UserMap, mappedRoles: RoleMap): OrgUserCsvRow[];
|
|
39
|
+
/**
|
|
40
|
+
* Removes unnecessary fields from team data and assigns org level roles.
|
|
41
|
+
*/
|
|
42
|
+
export declare function cleanTeamsData(data: RawTeam[], managementAPIClient: ManagementClient, org: OrganizationChoice): Promise<CleanedTeam[]>;
|
|
43
|
+
/**
|
|
44
|
+
* Get team user details from all teams.
|
|
45
|
+
*/
|
|
46
|
+
export declare function getTeamsUserDetails(teams: CleanedTeam[]): TeamUser[];
|
|
47
|
+
/**
|
|
48
|
+
* Change taxonomies data in required CSV headers format.
|
|
49
|
+
*/
|
|
50
|
+
export declare function formatTaxonomiesData(taxonomies: Taxonomy[]): TaxonomyCsvRow[] | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Modify the linked taxonomy data's terms in required CSV headers format.
|
|
53
|
+
*/
|
|
54
|
+
export declare function formatTermsOfTaxonomyData(terms: Term[], taxonomyUID: string): TermCsvRow[] | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Convert string to kebab-case.
|
|
57
|
+
*/
|
|
58
|
+
export declare function kebabize(str: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Get formatted date string (MM/DD/YYYY).
|
|
61
|
+
*/
|
|
62
|
+
export declare function getFormattedDate(date: Date | string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Get date-time string for file naming.
|
|
65
|
+
*/
|
|
66
|
+
export declare function getDateTime(): string;
|