Skip to content
Open
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
50 changes: 2 additions & 48 deletions .talismanrc
Original file line number Diff line number Diff line change
@@ -1,50 +1,4 @@
fileignoreconfig:
- filename: pnpm-lock.yaml
checksum: 8eb82c59ad8b81af64587af55c6788d09a34d1b651d030d1ef01dce472716f2a
- filename: packages/contentstack-branches/test/unit/helpers/stub-auth.ts
checksum: 8cafd5994d3ec13ba9af74c80b330bfd14721ea4e0359b456598964a6c2913ce
- filename: packages/contentstack-export/src/config/index.ts
checksum: 0219426b1873decef4d74bef5bfd50d1ed8f2567a2136122d869e4e53e4b4b99
- filename: packages/contentstack-clone/README.md
checksum: fad666bf6290c980406ddd18caec2dd89d9c7a22b422010865199659956ab523
- filename: packages/contentstack-migration/README.md
checksum: ceb7631888ee81711a32e2ac07762957bbf0f9c6c7f3f6bbc5d86326bd4352cc
- filename: packages/contentstack-external-migrate/test/commands/migrate/import.test.ts
checksum: 1d955eb34ab7e7e11cfad35cdbcb00692e39568bc690f46089fcbc0ca22a4852
- filename: packages/contentstack-external-migrate/test/adapters/contentful/export.test.ts
checksum: 118cc140edf3b68191d1ef770c4142f9f5aa7af87a5a1832d6b3edee53d61c83
- filename: packages/contentstack-cli-tsgen/test/unit/helper.test.ts
checksum: 146ff2a85a8f5ec463e51821f54c5f08143fa04209541a51017270e83b6ed46d
- filename: packages/contentstack-cli-cm-regex-validate/test/utils/connect-stack.test.ts
checksum: 018980aa2b919967b9ef9ab1bdf635d4867fe21593fba5890afa443f440228ff
- filename: packages/contentstack-bulk-operations/src/messages/index.ts
checksum: c8acefdd18f499a82d839e3cf99e34af9dd464f63f92282739411174ae7b7c37
- filename: packages/contentstack-bulk-operations/src/utils/operation-flag-matrix.ts
checksum: 99a3c3eb422a17f73f4c8f15088004fa4c95df3545bdf510310c1f3a20e4c2c2
- filename: packages/contentstack-bulk-operations/src/base-bulk-command.ts
checksum: cb1147ac666b607a093c4c827d143d0bd2de5b6e9d59973f1b7052451e82a89b
- filename: packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts
checksum: 8bca423db4c3815c651ad922d986a53b6271cce3ea27f5987b66ee594151165e
- filename: packages/contentstack-bulk-operations/test/unit/commands/bulk-assets-init.test.ts
checksum: 590b1cfe42d46d0917ac90f363b1ccd05200b180bd9c58c770ffd1f12eb18327
- filename: packages/contentstack-bulk-operations/test/unit/utils/operation-flag-matrix.test.ts
checksum: 35451ca4c03359b06531a8461091f4a3a45c4dea1f8853081fb53e4ce28c1cc3
- filename: packages/contentstack-bulk-operations/test/unit/base-bulk-command.test.ts
checksum: ca699a9d73757d44ded4d9d27beb4f460f911a7c88a14551a9402a3ac0c69873
- filename: packages/contentstack-external-migrate/src/lib/create-stack.ts
checksum: 68a9510db6f2746ac5006c091d276c1ba619a9e15c76a3edae3967e4f9c2dd4e
- filename: packages/contentstack-external-migrate/test/lib/create-stack.test.ts
checksum: 2dcbc359ee275e59e0536f3c325416eac8c43eb341b04da0d3757f5b5e556d9c
- filename: CHANGELOG.md
checksum: 88c7e1dee308fa4ae25e7815ead0842b1aac7ed669b02859cc8b25cba879595d
- filename: packages/contentstack-bulk-operations/test/unit/services/taxonomy-service.test.ts
checksum: abc5ac707341760cf59d5b8b1c4e13cf2c79955e2735c33e2db3ec6bc48eddb6
- filename: packages/contentstack-import/src/import/modules/assets.ts
checksum: cda61a9c90bb39f27c09951b8a2623851296aefd0d3220d066032287a712d899
- filename: packages/contentstack-asset-management/test/unit/utils/cs-assets-api-adapter.test.ts
checksum: 63c6bff4d51842d8fa3cce88545259d0a2c3cfe71df95d303d993f692cee883b
- filename: packages/contentstack-asset-management/src/utils/cs-assets-api-adapter.ts
checksum: bc4a53f96be6a10786e00133245c7bdc43c965c8a98b753e3879e1110cf9c601
- filename: packages/contentstack-bulk-operations/test/unit/commands/bulk-assets-cs-assets.test.ts
checksum: 1b6b5b0302d3efd9508e2e5d4fe3783da97a110735ca3106ce829cfe93874150
- filename: packages/contentstack-export/src/utils/export-config-handler.ts
checksum: ab7fd2fb63420e7a66856abace57965c1e9aa1033fc18dc8b194cf1d306f0bab
version: '1.0'
5 changes: 4 additions & 1 deletion packages/contentstack-export/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@
"csdxConfig": {
"shortCommandName": {
"cm:stacks:export": "EXPRT"
}
},
"planProtectedFeatures": [
"amAssets"
]
},
"repository": {
"type": "git",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export default class ExportCommand extends Command {
let exportDir: string = pathValidator('logs');
try {
const { flags } = await this.parse(ExportCommand);
const exportConfig = await setupExportConfig(flags);
const exportConfig = await setupExportConfig(flags, this.context);
// Prepare the context object
const context = this.createExportContext(exportConfig.apiKey, exportConfig.authenticationMethod);
exportConfig.context = { ...context };
Expand Down
74 changes: 56 additions & 18 deletions packages/contentstack-export/src/export/modules/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ import {
handleAndLogError,
messageHandler,
CLIProgressManager,
FEATURE,
} from '@contentstack/cli-utilities';
import { PATH_CONSTANTS } from '../../constants';

import config from '../../config';
import { ModuleClassParams } from '../../types';
import { ModuleClassParams, GlobalSummary } from '../../types';
import BaseClass, { CustomPromiseHandler, CustomPromiseHandlerInput } from './base-class';
import { ExportSpaces, type AssetExportCounts } from '@contentstack/cli-asset-management';
import {
Expand Down Expand Up @@ -57,31 +58,31 @@ export default class ExportAssets extends BaseClass {
};
}

/**
* Bug 3 — push real CS Assets entity counts into the final EXPORT summary: override the ASSETS
* module to count downloaded binaries only, and add dedicated ASSET TYPES / FIELDS / FOLDERS rows.
* Drives the global summary directly (no cli-utilities change); the live multibar is unaffected.
* The ASSETS strategy is set to Default so applyStrategyCorrections does not overwrite these.
*/
private applyAssetSummaryCounts(counts: AssetExportCounts): void {
type SummaryModule = { successCount: number; failureCount: number };
type GlobalSummary = {
getModules(): Map<string, SummaryModule>;
registerModule(name: string, totalItems?: number): void;
startModule(name: string): void;
completeModule(name: string, success?: boolean): void;
};
// globalSummary is runtime-accessible but typed private; reach it via a structural cast.
// globalSummary is runtime-accessible but typed private; feature-detect the shape and return null
// so callers degrade instead of throwing if a future cli-utilities version changes it.
private getGlobalSummary(): GlobalSummary | null {
const gs = (CLIProgressManager as unknown as { globalSummary?: GlobalSummary | null }).globalSummary;
// We reach into cli-utilities' summary internals, so feature-detect the shape and DEGRADE
// (skip the count overrides) instead of throwing if a future version changes it.
if (
!gs ||
typeof gs.getModules !== 'function' ||
typeof gs.registerModule !== 'function' ||
typeof gs.startModule !== 'function' ||
typeof gs.completeModule !== 'function'
) {
return null;
}
return gs;
}

/**
* Bug 3 — push real CS Assets entity counts into the final EXPORT summary: override the ASSETS
* module to count downloaded binaries only, and add dedicated ASSET TYPES / FIELDS / FOLDERS rows.
* Drives the global summary directly (no cli-utilities change); the live multibar is unaffected.
* The ASSETS strategy is set to Default so applyStrategyCorrections does not overwrite these.
*/
private applyAssetSummaryCounts(counts: AssetExportCounts): void {
const gs = this.getGlobalSummary();
if (!gs) {
log.debug('Global summary shape unavailable; skipping CS Assets summary count overrides', this.exportConfig.context);
return;
}
Expand Down Expand Up @@ -116,7 +117,44 @@ export default class ExportAssets extends BaseClass {
}
}

// Records the skip in the final summary via the failure channel, which is the only per-module
// slot carrying a message. createNestedProgress is intentionally not used: it would render an
// empty "ASSETS:" live section.
private markAssetsSkippedInSummary(reason: string): void {
const gs = this.getGlobalSummary();
if (!gs) {
log.debug('Global summary shape unavailable; skipping ASSETS skip row', this.exportConfig.context);
return;
}

try {
const name = this.currentModuleName.toUpperCase();
gs.registerModule(name);
gs.startModule(name);
const module = gs.getModules().get(name);
if (module) {
module.failures.push({ item: reason, error: reason });
module.status = 'failed';
module.endTime = Date.now();
}
} catch (e) {
log.debug(`Failed to mark ASSETS as skipped in summary: ${e}`, this.exportConfig.context);
}
}

async start(): Promise<void> {
const csAssetsInPlan = this.exportConfig.planStatus?.[FEATURE.ASSET_MANAGEMENT]?.is_part_of_plan;
if (csAssetsInPlan && this.exportConfig.management_token) {
const warning =
'Skipping Contentstack Assets export: management token authentication is not supported by the Assets APIs. ' +
'Entry-to-asset references will NOT resolve in the exported content. ' +
'Re-run the export with a logged-in session (auth token or OAuth) to export Contentstack Assets.';
cliux.print(`\nWARNING!!! ${warning}`, { color: 'yellow' });
log.error(warning, this.exportConfig.context);
this.markAssetsSkippedInSummary(warning);
return;
}

const linkedWorkspaces = this.exportConfig.linkedWorkspaces ?? [];

if (linkedWorkspaces.length > 0) {
Expand Down
2 changes: 2 additions & 0 deletions packages/contentstack-export/src/types/export-config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { FeatureStatus } from '@contentstack/cli-utilities';
import { Context, Modules, Region } from '.';
import DefaultConfig from './default-config';

Expand Down Expand Up @@ -36,6 +37,7 @@ export default interface ExportConfig extends DefaultConfig {
skipDependencies?: boolean;
authenticationMethod?: string;
linkedWorkspaces?: Array<{ uid: string; space_uid: string; is_default: boolean }>;
planStatus?: Record<string, FeatureStatus>;
}

type branch = {
Expand Down
15 changes: 15 additions & 0 deletions packages/contentstack-export/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,21 @@ export interface Context {
authenticationMethod?: string;
}

export interface SummaryModule {
status: string;
successCount: number;
failureCount: number;
failures: Array<{ item: string; error: string }>;
endTime?: number;
}

export interface GlobalSummary {
getModules(): Map<string, SummaryModule>;
registerModule(name: string, totalItems?: number): void;
startModule(name: string): void;
completeModule(name: string, success?: boolean): void;
}

export { default as DefaultConfig } from './default-config';
export { default as ExportConfig } from './export-config';
export * from './marketplace-app';
38 changes: 36 additions & 2 deletions packages/contentstack-export/src/utils/export-config-handler.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import merge from 'merge';
import * as path from 'path';
import { configHandler, isAuthenticated, cliux, sanitizePath, log } from '@contentstack/cli-utilities';
import {
configHandler,
isAuthenticated,
cliux,
sanitizePath,
log,
isFeatureEnabled,
FeatureCtx,
} from '@contentstack/cli-utilities';
import defaultConfig from '../config';
import { readFile, isDirectoryNonEmpty } from './file-helper';
import { askExportDir, askAPIKey } from './interactive';
import login from './basic-login';
import { filter, includes } from 'lodash';
import { ExportConfig } from '../types';

const setupConfig = async (exportCmdFlags: any): Promise<ExportConfig> => {
const setupConfig = async (exportCmdFlags: any, context: any): Promise<ExportConfig> => {
// Set progress supported module FIRST, before any log calls
// This ensures the logger respects the showConsoleLogs setting correctly
configHandler.set('log.progressSupportedModule', 'export');
Expand Down Expand Up @@ -152,6 +160,32 @@ const setupConfig = async (exportCmdFlags: any): Promise<ExportConfig> => {
config.authenticationMethod = authenticationMethod;
log.debug('Export configuration setup completed.', { ...config });

// Deferred plan check — credentials now available after setupExportConfig
const deferredFeatures: string[] = context?.planCheckRequired ?? [];
if (deferredFeatures.length > 0) {
const planCtx: FeatureCtx = {
apiKey: config.apiKey,
managementToken: config.management_token,
authToken: config.auth_token,
};
for (const featureUid of deferredFeatures) {
try {
const status = await isFeatureEnabled(featureUid, planCtx);
if (context) {
context.planStatus[featureUid] = status;
}

log.debug(`[export] Deferred plan status fetched for "${featureUid}".`);
} catch (error) {
log.warn(`[export] Could not fetch deferred plan status for "${featureUid}": ${(error as Error).message}`);
}
}
}

if (context?.planStatus) {
config.planStatus = context.planStatus;
}

return config;
};

Expand Down
Loading