Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 62 additions & 18 deletions packages/contentstack-export/src/export/modules/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
import config from '../../config';
import { ModuleClassParams } from '../../types';
import BaseClass, { CustomPromiseHandler, CustomPromiseHandlerInput } from './base-class';
import { EXPORT_PROCESS_NAMES, EXPORT_MODULE_CONTEXTS, EXPORT_PROCESS_STATUS, EXPORT_MODULE_NAMES } from '../../utils';

export default class ExportAssets extends BaseClass {
private assetsRootPath: string;
Expand All @@ -33,8 +34,8 @@ export default class ExportAssets extends BaseClass {

constructor({ exportConfig, stackAPIClient }: ModuleClassParams) {
super({ exportConfig, stackAPIClient });
this.exportConfig.context.module = 'assets';
this.currentModuleName = 'Assets';
this.exportConfig.context.module = EXPORT_MODULE_CONTEXTS.ASSETS;
this.currentModuleName = EXPORT_MODULE_NAMES[EXPORT_MODULE_CONTEXTS.ASSETS];
}

get commonQueryParam(): Record<string, unknown> {
Expand Down Expand Up @@ -64,41 +65,59 @@ export default class ExportAssets extends BaseClass {

// Add sub-processes
if (typeof assetsFolderCount === 'number' && assetsFolderCount > 0) {
progress.addProcess('Folders', assetsFolderCount);
progress.addProcess(EXPORT_PROCESS_NAMES.ASSET_FOLDERS, assetsFolderCount);
}
if (typeof assetsCount === 'number' && assetsCount > 0) {
progress.addProcess('Metadata', assetsCount);
progress.addProcess('Downloads', assetsCount);
progress.addProcess(EXPORT_PROCESS_NAMES.ASSET_METADATA, assetsCount);
progress.addProcess(EXPORT_PROCESS_NAMES.ASSET_DOWNLOADS, assetsCount);
}

try {
// Process asset folders
if (typeof assetsFolderCount === 'number' && assetsFolderCount > 0) {
progress.startProcess('Folders').updateStatus('Fetching folder structure...', 'Folders');
progress
.startProcess(EXPORT_PROCESS_NAMES.ASSET_FOLDERS)
.updateStatus(
EXPORT_PROCESS_STATUS[EXPORT_PROCESS_NAMES.ASSET_FOLDERS].FETCHING,
EXPORT_PROCESS_NAMES.ASSET_FOLDERS,
);
await this.getAssetsFolders(assetsFolderCount);
progress.completeProcess('Folders', true);
progress.completeProcess(EXPORT_PROCESS_NAMES.ASSET_FOLDERS, true);
}

// Process asset metadata
if (typeof assetsCount === 'number' && assetsCount > 0) {
progress.startProcess('Metadata').updateStatus('Fetching asset information...', 'Metadata');
progress
.startProcess(EXPORT_PROCESS_NAMES.ASSET_METADATA)
.updateStatus(
EXPORT_PROCESS_STATUS[EXPORT_PROCESS_NAMES.ASSET_METADATA].FETCHING,
EXPORT_PROCESS_NAMES.ASSET_METADATA,
);
await this.getAssets(assetsCount);
progress.completeProcess('Metadata', true);
progress.completeProcess(EXPORT_PROCESS_NAMES.ASSET_METADATA, true);
}

// Get versioned assets
if (!isEmpty(this.versionedAssets) && this.assetConfig.includeVersionedAssets) {
log.debug('Fetching versioned assets metadata...', this.exportConfig.context);
progress.updateStatus('Processing versioned assets...', 'Metadata');
progress.updateStatus(
EXPORT_PROCESS_STATUS[EXPORT_PROCESS_NAMES.ASSET_METADATA].FETCHING_VERSION,
EXPORT_PROCESS_NAMES.ASSET_METADATA,
);
await this.getVersionedAssets();
}

// Download all assets
if (typeof assetsCount === 'number' && assetsCount > 0) {
progress.startProcess('Downloads').updateStatus('Downloading asset files...', 'Downloads');
progress
.startProcess(EXPORT_PROCESS_NAMES.ASSET_DOWNLOADS)
.updateStatus(
EXPORT_PROCESS_STATUS[EXPORT_PROCESS_NAMES.ASSET_DOWNLOADS].DOWNLOADING,
EXPORT_PROCESS_NAMES.ASSET_DOWNLOADS,
);
log.debug('Starting download of all assets...', this.exportConfig.context);
await this.downloadAssets();
progress.completeProcess('Downloads', true);
progress.completeProcess(EXPORT_PROCESS_NAMES.ASSET_DOWNLOADS, true);
}

this.completeProgress(true);
Expand Down Expand Up @@ -128,13 +147,23 @@ export default class ExportAssets extends BaseClass {
if (!isEmpty(items)) {
this.assetsFolder.push(...items);
items.forEach((folder: any) => {
this.progressManager?.tick(true, `folder: ${folder.name || folder.uid}`, null, 'Folders');
this.progressManager?.tick(
true,
`folder: ${folder.name || folder.uid}`,
null,
EXPORT_PROCESS_NAMES.ASSET_FOLDERS,
);
});
}
};

const onReject = ({ error }: any) => {
this.progressManager?.tick(false, 'asset folder', error?.message || 'Failed to fetch folder', 'Folders');
this.progressManager?.tick(
false,
'asset folder',
error?.message || EXPORT_PROCESS_STATUS[EXPORT_PROCESS_NAMES.ASSET_FOLDERS].FAILED,
EXPORT_PROCESS_NAMES.ASSET_FOLDERS,
);
handleAndLogError(error, { ...this.exportConfig.context });
};

Expand Down Expand Up @@ -197,7 +226,12 @@ export default class ExportAssets extends BaseClass {
}

const onReject = ({ error }: any) => {
this.progressManager?.tick(false, 'asset', error?.message || 'Failed to fetch asset', 'Metadata');
this.progressManager?.tick(
false,
'asset',
error?.message || EXPORT_PROCESS_STATUS[EXPORT_PROCESS_NAMES.ASSET_METADATA].FAILED,
EXPORT_PROCESS_NAMES.ASSET_METADATA,
);
handleAndLogError(error, { ...this.exportConfig.context }, messageHandler.parse('ASSET_QUERY_FAILED'));
};

Expand All @@ -219,7 +253,12 @@ export default class ExportAssets extends BaseClass {
fs?.writeIntoFile(items, { mapKeyVal: true });
// Track progress for each asset with process name
items.forEach((asset: any) => {
this.progressManager?.tick(true, `asset: ${asset.filename || asset.uid}`, null, 'Metadata');
this.progressManager?.tick(
true,
`asset: ${asset.filename || asset.uid}`,
null,
EXPORT_PROCESS_NAMES.ASSET_METADATA,
);
});
}
};
Expand Down Expand Up @@ -418,7 +457,12 @@ export default class ExportAssets extends BaseClass {
} else {
data.pipe(assetWriterStream);
}
this.progressManager?.tick(true, `Downloaded asset: ${asset.filename || asset.uid}`, null, 'Downloads');
this.progressManager?.tick(
true,
`Downloaded asset: ${asset.filename || asset.uid}`,
null,
EXPORT_PROCESS_NAMES.ASSET_DOWNLOADS,
);
log.success(messageHandler.parse('ASSET_DOWNLOAD_SUCCESS', asset.filename, asset.uid), this.exportConfig.context);
};

Expand All @@ -428,7 +472,7 @@ export default class ExportAssets extends BaseClass {
false,
`Failed to download asset: ${asset.filename || asset.uid}`,
null,
'Downloads',
EXPORT_PROCESS_NAMES.ASSET_DOWNLOADS,
);
handleAndLogError(
error,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import * as path from 'path';
import { ContentstackClient, handleAndLogError, messageHandler, log, sanitizePath } from '@contentstack/cli-utilities';

import BaseClass from './base-class';
import { fsUtil, executeTask } from '../../utils';
import { ExportConfig, ModuleClassParams } from '../../types';
import { fsUtil, executeTask, EXPORT_MODULE_CONTEXTS, EXPORT_MODULE_NAMES } from '../../utils';

export default class ContentTypesExport extends BaseClass {
private stackAPIClient: ReturnType<ContentstackClient['stack']>;
Expand Down Expand Up @@ -52,8 +52,8 @@ export default class ContentTypesExport extends BaseClass {
sanitizePath(this.contentTypesConfig.dirName),
);
this.contentTypes = [];
this.exportConfig.context.module = 'content-types';
this.currentModuleName = 'Content Types';
this.exportConfig.context.module = EXPORT_MODULE_CONTEXTS.CONTENT_TYPES;
this.currentModuleName = EXPORT_MODULE_NAMES[EXPORT_MODULE_CONTEXTS.CONTENT_TYPES];
}

async start() {
Expand Down
53 changes: 37 additions & 16 deletions packages/contentstack-export/src/export/modules/custom-roles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ import { resolve as pResolve } from 'node:path';
import { handleAndLogError, messageHandler, log } from '@contentstack/cli-utilities';

import BaseClass from './base-class';
import { fsUtil } from '../../utils';
import {
fsUtil,
EXPORT_PROCESS_NAMES,
EXPORT_MODULE_CONTEXTS,
EXPORT_PROCESS_STATUS,
EXPORT_MODULE_NAMES,
} from '../../utils';
import { CustomRoleConfig, ModuleClassParams } from '../../types';

export default class ExportCustomRoles extends BaseClass {
Expand All @@ -25,8 +31,8 @@ export default class ExportCustomRoles extends BaseClass {
this.existingRoles = { Admin: 1, Developer: 1, 'Content Manager': 1 };
this.localesMap = {};
this.sourceLocalesMap = {};
this.exportConfig.context.module = 'custom-roles';
this.currentModuleName = 'Custom Roles';
this.exportConfig.context.module = EXPORT_MODULE_CONTEXTS.CUSTOM_ROLES;
this.currentModuleName = EXPORT_MODULE_NAMES[EXPORT_MODULE_CONTEXTS.CUSTOM_ROLES];
}

async start(): Promise<void> {
Expand Down Expand Up @@ -66,21 +72,36 @@ export default class ExportCustomRoles extends BaseClass {

// Create nested progress manager
const progress = this.createNestedProgress(this.currentModuleName)
.addProcess('Fetch Roles', totalRoles)
.addProcess('Fetch Locales', totalLocales)
.addProcess('Process Mappings', 1);

progress.startProcess('Fetch Roles').updateStatus('Fetching custom roles...', 'Fetch Roles');
.addProcess(EXPORT_PROCESS_NAMES.FETCH_ROLES, totalRoles)
.addProcess(EXPORT_PROCESS_NAMES.FETCH_LOCALES, totalLocales)
.addProcess(EXPORT_PROCESS_NAMES.PROCESS_MAPPINGS, 1);

progress
.startProcess(EXPORT_PROCESS_NAMES.FETCH_ROLES)
.updateStatus(
EXPORT_PROCESS_STATUS[EXPORT_PROCESS_NAMES.FETCH_ROLES].FETCHING,
EXPORT_PROCESS_NAMES.FETCH_ROLES,
);
await this.getCustomRoles();
progress.completeProcess('Fetch Roles', true);
progress.completeProcess(EXPORT_PROCESS_NAMES.FETCH_ROLES, true);

progress.startProcess('Fetch Locales').updateStatus('Fetching locales...', 'Fetch Locales');
progress
.startProcess(EXPORT_PROCESS_NAMES.FETCH_LOCALES)
.updateStatus(
EXPORT_PROCESS_STATUS[EXPORT_PROCESS_NAMES.FETCH_LOCALES].FETCHING,
EXPORT_PROCESS_NAMES.FETCH_LOCALES,
);
await this.getLocales();
progress.completeProcess('Fetch Locales', true);
progress.completeProcess(EXPORT_PROCESS_NAMES.FETCH_LOCALES, true);

progress.startProcess('Process Mappings').updateStatus('Processing role-locale mappings...', 'Process Mappings');
progress
.startProcess(EXPORT_PROCESS_NAMES.PROCESS_MAPPINGS)
.updateStatus(
EXPORT_PROCESS_STATUS[EXPORT_PROCESS_NAMES.PROCESS_MAPPINGS].PROCESSING,
EXPORT_PROCESS_NAMES.PROCESS_MAPPINGS,
);
await this.getCustomRolesLocales();
progress.completeProcess('Process Mappings', true);
progress.completeProcess(EXPORT_PROCESS_NAMES.PROCESS_MAPPINGS, true);

log.debug(
`Custom roles export completed. Total custom roles: ${Object.keys(this.customRoles).length}`,
Expand Down Expand Up @@ -124,7 +145,7 @@ export default class ExportCustomRoles extends BaseClass {
log.info(messageHandler.parse('ROLES_EXPORTING_ROLE', role.name), this.exportConfig.context);
this.customRoles[role.uid] = role;

this.progressManager?.tick(true, `role: ${role.name}`, null, 'Fetch Roles');
this.progressManager?.tick(true, `role: ${role.name}`, null, EXPORT_PROCESS_NAMES.FETCH_ROLES);
});

const customRolesFilePath = pResolve(this.rolesFolderPath, this.customRolesConfig.fileName);
Expand Down Expand Up @@ -153,7 +174,7 @@ export default class ExportCustomRoles extends BaseClass {
this.sourceLocalesMap[locale.uid] = locale;

// Track progress for each locale
this.progressManager?.tick(true, `locale: ${locale.name}`, null, 'Fetch Locales');
this.progressManager?.tick(true, `locale: ${locale.name}`, null, EXPORT_PROCESS_NAMES.FETCH_LOCALES);
}

log.debug(`Mapped ${Object.keys(this.sourceLocalesMap).length} locales`, this.exportConfig.context);
Expand Down Expand Up @@ -198,6 +219,6 @@ export default class ExportCustomRoles extends BaseClass {
}

// Track progress for mapping completion
this.progressManager?.tick(true, 'role-locale mappings', null, 'Process Mappings');
this.progressManager?.tick(true, 'role-locale mappings', null, EXPORT_PROCESS_NAMES.PROCESS_MAPPINGS);
}
}
Loading
Loading