Skip to content
Merged
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
6 changes: 4 additions & 2 deletions .talismanrc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
fileignoreconfig:
- filename: package-lock.json
checksum: c73d080bfbbf03bc2597891f956367bfd71f5f2f8d03525175426015265edc91
checksum: 1c4c7e056ad7330134ac5726d3ef11cd4b40f567161b5a9c405294705e819099
- filename: pnpm-lock.yaml
checksum: 0ca85066946c49994a4353c9f64b8f380d5d2050194e3e57ad7ccd7faa030d36
checksum: 6034c8cc26390236c9e172454451e918febeaec373c5509886f1d15ee1017021
- filename: packages/contentstack-import-setup/test/unit/backup-handler.test.ts
checksum: 0582d62b88834554cf12951c8690a73ef3ddbb78b82d2804d994cf4148e1ef93
- filename: packages/contentstack-import-setup/test/config.json
Expand Down Expand Up @@ -35,4 +35,6 @@ fileignoreconfig:
checksum: c09f6dc93702caff3adf689b501ec32586a16c865c1fe3a63b53ae645ca22349
- filename: packages/contentstack-import-setup/test/unit/modules/assets.test.ts
checksum: 449a5e3383631a6f78d1291aa3c28c91681879289398f0a933158fba5c5d5acf
- filename: packages/contentstack-import/src/commands/cm/stacks/import.ts
checksum: 0dbf0a6bc447206260b8acd41b85781d60ca50c948bb3ca62f444f97d64d1fb2
version: "1.0"
5 changes: 3 additions & 2 deletions packages/contentstack-export/src/export/module-exporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ModuleExporter {
return this.exportByBranches();
}
// If branches disabled then initialize the global summary
CLIProgressManager.initializeGlobalSummary('EXPORT', this.exportConfig.branchName);
CLIProgressManager.initializeGlobalSummary('EXPORT', this.exportConfig.branchName, 'EXPORTING CONTENT');
return this.export();
}

Expand All @@ -50,7 +50,8 @@ class ModuleExporter {
// Reset progress manager for each branch (except the first one which was initialized in export command)
if (index >= 0) {
CLIProgressManager.clearGlobalSummary();
CLIProgressManager.initializeGlobalSummary(`EXPORT-${branch.uid}`, branch.uid);
CLIProgressManager.initializeGlobalSummary(`EXPORT-${branch.uid}`, branch.uid, `EXPORTING "${branch.uid}" BRANCH CONTENT`,);

}

log.info(`Exporting content from branch ${branch.uid}`, this.exportConfig.context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ export default class CLIProgressManager {
/**
* Initialize global summary manager for the entire operation
*/
static initializeGlobalSummary(operationName: string, branchName: string): SummaryManager {
static initializeGlobalSummary(operationName: string, branchName: string, headerTitle?: string): SummaryManager {
CLIProgressManager.globalSummary = new SummaryManager({ operationName, context: { branchName } });

// Only show header if console logs are disabled (progress UI mode)
if (!configHandler.get('log')?.showConsoleLogs) {
CLIProgressManager.displayOperationHeader(operationName, branchName);
CLIProgressManager.displayOperationHeader(branchName, headerTitle);
}

return CLIProgressManager.globalSummary;
Expand All @@ -79,10 +79,13 @@ export default class CLIProgressManager {
/**
* Display operation header with branch information
*/
static displayOperationHeader(operationName: string, branchName: string): void {
const branchInfo = branchName ? `EXPORTING "${branchName.toUpperCase()}" BRANCH CONTENT` : '';
static displayOperationHeader(branchName: string, headerTitle?: string): void {
if (!headerTitle) return;

const safeBranchName = branchName || 'main';
const branchInfo = headerTitle || `${safeBranchName?.toUpperCase()} CONTENT`;

console.log('\n' + chalk.bold('='.repeat(80)));
console.log(chalk.bold.cyan(` ${operationName.toUpperCase()}`));
if (branchInfo) {
console.log(chalk.bold.white(` ${branchInfo}`));
}
Expand Down Expand Up @@ -171,7 +174,7 @@ export default class CLIProgressManager {
}

/**
* Convert module name from UPPERCASE to PascalCase
* Convert module name from UPPERCASE to PascalCase
*/
private formatModuleName(name: string): string {
return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
Expand Down Expand Up @@ -478,15 +481,15 @@ export default class CLIProgressManager {
` ${status} ${processName}: ${process.successCount}✓ ${process.failureCount}✗ (${process.current}/${process.total})`,
);

// Show first few failures for this process
if (process.failures.length > 0) {
process.failures.slice(0, 3).forEach((failure) => {
this.log(` ✗ ${failure.item}: ${failure.error}`);
});
if (process.failures.length > 3) {
this.log(` ... and ${process.failures.length - 3} more failures`);
}
}
// Show first few failures for this process - TEMPORARILY DISABLED - will be shown in separate section later
// if (process.failures.length > 0) {
// process.failures.slice(0, 3).forEach((failure) => {
// this.log(` ✗ ${failure.item}: ${failure.error}`);
// });
// if (process.failures.length > 3) {
// this.log(` ... and ${process.failures.length - 3} more failures`);
// }
// }
}

this.log(`\nOverall: ${this.successCount}✓ ${this.failureCount}✗`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,6 @@ export default class SummaryManager {
const operationEndTime = Date.now();
const totalDuration = operationEndTime - this.operationStartTime;

const branchInfo = this.branchName ? `EXPORTING "${this.branchName.toUpperCase()}" BRANCH RESULTS` : '';

console.log('\n' + chalk.bold('='.repeat(80)));
console.log(chalk.bold.cyan(` ${this.operationName} SUMMARY`));
if (branchInfo) {
console.log(chalk.bold.white(` ${branchInfo}`));
}
console.log(chalk.bold('='.repeat(80)));

// Overall Statistics
const totalModules = this.modules.size;
const completedModules = Array.from(this.modules.values()).filter((m) => m.status === 'completed').length;
Expand All @@ -81,6 +72,7 @@ export default class SummaryManager {
const totalSuccess = Array.from(this.modules.values()).reduce((sum, m) => sum + m.successCount, 0);
const totalFailures = Array.from(this.modules.values()).reduce((sum, m) => sum + m.failureCount, 0);

console.log('\n' + chalk.bold('='.repeat(80)));
console.log('\n' + chalk.bold('Overall Statistics:'));
console.log(` Total ${this.operationName} Time: ${chalk.cyan(this.formatDuration(totalDuration))}`);
console.log(` Modules Processed: ${chalk.cyan(completedModules)}/${chalk.cyan(totalModules)}`);
Expand Down Expand Up @@ -110,16 +102,17 @@ export default class SummaryManager {
`${duration.padStart(8)}`,
);

// Show failures if any
if (module.failures.length > 0) {
console.log(chalk.red(` Failures (${module.failures.length}):`));
module.failures.slice(0, 5).forEach((failure) => {
console.log(chalk.red(` - ${failure.item}: ${failure.error}`));
});
if (module.failures.length > 5) {
console.log(chalk.red(` ... and ${module.failures.length - 5} more`));
}
}

// Show failures if any - TEMPORARILY DISABLED - will be shown in separate section later
// if (module.failures.length > 0) {
// console.log(chalk.red(` Failures (${module.failures.length}):`));
// module.failures.slice(0, 5).forEach((failure) => {
// console.log(chalk.red(` - ${failure.item}: ${failure.error}`));
// });
// if (module.failures.length > 5) {
// console.log(chalk.red(` ... and ${module.failures.length - 5} more`));
// }
// }
});

// Final Status
Expand All @@ -132,6 +125,8 @@ export default class SummaryManager {
console.log(chalk.bold.red(`❌ ${this.operationName} failed`));
}

//TODO:- Smart Failure Summary - only show if there are failures

console.log(chalk.bold('='.repeat(80)));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,30 +127,34 @@ export class PersonalizationAdapter<T> extends AdapterHelper<T, HttpClient> impl
}

async init(): Promise<void> {
log.debug('Initializing personalization adapter...', this.exportConfig?.context);
await authenticationHandler.getAuthDetails();
const token = authenticationHandler.accessToken;
log.debug(
`Authentication type: ${authenticationHandler.isOauthEnabled ? 'OAuth' : 'Token'}`,
this.exportConfig?.context,
);

if (authenticationHandler.isOauthEnabled) {
log.debug('Setting OAuth authorization header', this.exportConfig?.context);
this.apiClient.headers({ authorization: token });
if (this.adapterConfig.cmaConfig) {
log.debug('Setting OAuth authorization header for CMA client', this.exportConfig?.context);
this.cmaAPIClient?.headers({ authorization: token });
}
} else {
log.debug('Setting authtoken header', this.exportConfig?.context);
this.apiClient.headers({ authtoken: token });
if (this.adapterConfig.cmaConfig) {
log.debug('Setting authtoken header for CMA client', this.exportConfig?.context);
this.cmaAPIClient?.headers({ authtoken: token });
try {
log.debug('Initializing personalization adapter...', this.exportConfig?.context);
await authenticationHandler.getAuthDetails();
const token = authenticationHandler.accessToken;
log.debug(
`Authentication type: ${authenticationHandler.isOauthEnabled ? 'OAuth' : 'Token'}`,
this.exportConfig?.context,
);

if (authenticationHandler.isOauthEnabled) {
log.debug('Setting OAuth authorization header', this.exportConfig?.context);
this.apiClient.headers({ authorization: token });
if (this.adapterConfig.cmaConfig) {
log.debug('Setting OAuth authorization header for CMA client', this.exportConfig?.context);
this.cmaAPIClient?.headers({ authorization: token });
}
} else {
log.debug('Setting authtoken header', this.exportConfig?.context);
this.apiClient.headers({ authtoken: token });
if (this.adapterConfig.cmaConfig) {
log.debug('Setting authtoken header for CMA client', this.exportConfig?.context);
this.cmaAPIClient?.headers({ authtoken: token });
}
}
log.debug('Personalization adapter initialization completed', this.exportConfig?.context);
} catch (error: any) {
log.debug(`Personalization adapter initialization failed: ${error}`, this.exportConfig?.context);
}
log.debug('Personalization adapter initialization completed', this.exportConfig?.context);
}

async projects(options: GetProjectsParams): Promise<ProjectStruct[]> {
Expand All @@ -170,7 +174,7 @@ export class PersonalizationAdapter<T> extends AdapterHelper<T, HttpClient> impl

return result;
} catch (error: any) {
this.updateProgress(false, 'projects fetch', error?.message || 'Failed to fetch projects', 'Projects');
log.debug(`Failed to fetch projects: ${error}`, this.exportConfig?.context);
throw error;
}
}
Expand Down Expand Up @@ -226,7 +230,7 @@ export class PersonalizationAdapter<T> extends AdapterHelper<T, HttpClient> impl

return result;
} catch (error: any) {
this.updateProgress(false, 'experiences fetch', error?.message || 'Failed to fetch experiences', 'Experiences');
log.debug(`Failed to fetch experiences: ${error}`, this.exportConfig?.context);
throw error;
}
}
Expand Down Expand Up @@ -318,10 +322,16 @@ export class PersonalizationAdapter<T> extends AdapterHelper<T, HttpClient> impl

async getEvents(): Promise<EventStruct[] | void> {
log.debug('Fetching events from personalization API', this.exportConfig?.context);
const data = await this.apiClient.get<EventStruct>('/events');
const result = (await this.handleVariantAPIRes(data)) as EventStruct[];
log.debug(`Fetched ${result?.length || 0} events`, this.exportConfig?.context);
return result;
try {
const data = await this.apiClient.get<EventStruct>('/events');
const result = (await this.handleVariantAPIRes(data)) as EventStruct[];
log.debug(`Fetched ${result?.length || 0} events`, this.exportConfig?.context);
return result;
} catch (error: any) {
log.debug(`Failed to fetch events: ${error}`, this.exportConfig?.context);
// Return empty array instead of throwing to prevent spinner from hanging
throw error;
}
}

async createEvents(event: CreateEventInput): Promise<void | EventStruct> {
Expand All @@ -333,18 +343,30 @@ export class PersonalizationAdapter<T> extends AdapterHelper<T, HttpClient> impl

async getAudiences(): Promise<AudienceStruct[] | void> {
log.debug('Fetching audiences from personalization API', this.exportConfig?.context);
const data = await this.apiClient.get<AudienceStruct>('/audiences');
const result = (await this.handleVariantAPIRes(data)) as AudienceStruct[];
log.debug(`Fetched ${result?.length || 0} audiences`, this.exportConfig?.context);
return result;
try {
const data = await this.apiClient.get<AudienceStruct>('/audiences');
const result = (await this.handleVariantAPIRes(data)) as AudienceStruct[];
log.debug(`Fetched ${result?.length || 0} audiences`, this.exportConfig?.context);
return result;
} catch (error: any) {
log.debug(`Failed to fetch audiences: ${error}`, this.exportConfig?.context);
// Return empty array instead of throwing to prevent spinner from hanging
throw error;
}
}

async getAttributes(): Promise<AttributeStruct[] | void> {
log.debug('Fetching attributes from personalization API', this.exportConfig?.context);
const data = await this.apiClient.get<AttributeStruct>('/attributes');
const result = (await this.handleVariantAPIRes(data)) as AttributeStruct[];
log.debug(`Fetched ${result?.length || 0} attributes`, this.exportConfig?.context);
return result;
try {
const data = await this.apiClient.get<AttributeStruct>('/attributes');
const result = (await this.handleVariantAPIRes(data)) as AttributeStruct[];
log.debug(`Fetched ${result?.length || 0} attributes`, this.exportConfig?.context);
return result;
} catch (error: any) {
log.debug(`Failed to fetch attributes: ${error}`, this.exportConfig?.context);
// Return empty array instead of throwing to prevent spinner from hanging
throw error;
}
}

/**
Expand Down