From b150485a24e2c12ab9ba550e1529304665f6109f Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 24 Jun 2026 12:57:31 +0530 Subject: [PATCH 1/3] fixed unit test cases --- .../test/unit/import-config-handler.test.ts | 14 ++++++++------ .../test/unit/modules/assets.test.ts | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/contentstack-import-setup/test/unit/import-config-handler.test.ts b/packages/contentstack-import-setup/test/unit/import-config-handler.test.ts index 6778f2315..21c7bab31 100644 --- a/packages/contentstack-import-setup/test/unit/import-config-handler.test.ts +++ b/packages/contentstack-import-setup/test/unit/import-config-handler.test.ts @@ -2,7 +2,7 @@ import { expect } from 'chai'; import * as path from 'path'; import * as os from 'os'; import * as fs from 'fs'; -import { stub, restore, SinonStub } from 'sinon'; +import { stub, restore, SinonStub, createSandbox } from 'sinon'; import * as utilities from '@contentstack/cli-utilities'; import * as cliAm from '@contentstack/cli-asset-management'; import setupConfig from '../../src/utils/import-config-handler'; @@ -153,11 +153,13 @@ describe('Import Config Handler', () => { }); it('should merge Asset Management export flags from detectAssetManagementExportFromContentDir into config', async () => { - const detectStub = stub(cliAm, 'detectAssetManagementExportFromContentDir').returns({ + const sandbox = createSandbox(); + const detectFake = sandbox.fake.returns({ assetManagementEnabled: true, source_stack: 'branch-source-key', assetManagementUrl: 'https://am.example.com', }); + sandbox.replaceGetter(cliAm, 'detectAssetManagementExportFromContentDir', () => detectFake); try { const config = await setupConfig({ @@ -166,12 +168,12 @@ describe('Import Config Handler', () => { module: ['assets'], }); - expect(detectStub.calledOnce).to.be.true; - expect(config.assetManagementEnabled).to.equal(true); - expect(config.assetManagementUrl).to.equal('https://am.example.com'); + expect(detectFake.calledOnce).to.be.true; + expect(config.csAssetsEnabled).to.equal(true); + expect(config.csAssetsUrl).to.equal('https://am.example.com'); expect(config.source_stack).to.equal('branch-source-key'); } finally { - detectStub.restore(); + sandbox.restore(); } }); }); diff --git a/packages/contentstack-import-setup/test/unit/modules/assets.test.ts b/packages/contentstack-import-setup/test/unit/modules/assets.test.ts index 9d1b6d826..023754179 100644 --- a/packages/contentstack-import-setup/test/unit/modules/assets.test.ts +++ b/packages/contentstack-import-setup/test/unit/modules/assets.test.ts @@ -200,12 +200,12 @@ describe('AssetImportSetup Asset Management export', () => { backupDir, region: { cma: 'https://api.contentstack.io/v3', - assetManagementUrl: 'https://am.example.com', + csAssetsUrl: 'https://am.example.com', }, host: 'https://api.contentstack.io/v3', fetchConcurrency: 2, writeConcurrency: 1, - assetManagementEnabled: true, + csAssetsEnabled: true, org_uid: 'org-uid-test', source_stack: 'source-api-key', context: {}, From e047d2aa7395bceb52a30f435c3196d1b70d8a5d Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 1 Jul 2026 11:16:44 +0530 Subject: [PATCH 2/3] fixed org plan check feature --- .talismanrc | 8 +++- packages/contentstack-export/package.json | 4 +- .../src/commands/cm/stacks/export.ts | 7 ++- .../src/utils/export-config-handler.ts | 44 ++++++++++++++----- .../tsconfig.tsbuildinfo | 2 +- .../src/commands/cm/stacks/import.ts | 4 +- .../src/utils/import-config-handler.ts | 23 +++++++++- 7 files changed, 73 insertions(+), 19 deletions(-) diff --git a/.talismanrc b/.talismanrc index 2db24759d..0e9b7a11f 100644 --- a/.talismanrc +++ b/.talismanrc @@ -1,4 +1,8 @@ fileignoreconfig: -- filename: pnpm-lock.yaml - checksum: 24619b075664a197c8f648b04dd86ee79d653fbb583b33e4a3768f02378912ef + - filename: pnpm-lock.yaml + checksum: 24619b075664a197c8f648b04dd86ee79d653fbb583b33e4a3768f02378912ef + - filename: packages/contentstack-import/src/utils/import-config-handler.ts + checksum: 25b986edf20dfd555f9ffc6f124d7d6eb7ac1134a5a67224a49ba48aa50b86f3 + - filename: packages/contentstack-export/src/utils/export-config-handler.ts + checksum: a024cdb82e21496794f49fd905f983c0d6677ac9d6761f2e46266fea9932041d version: '1.0' diff --git a/packages/contentstack-export/package.json b/packages/contentstack-export/package.json index c77307173..a733060c3 100644 --- a/packages/contentstack-export/package.json +++ b/packages/contentstack-export/package.json @@ -6,7 +6,7 @@ "bugs": "https://github.com/contentstack/cli/issues", "dependencies": { "@contentstack/cli-command": "~2.0.0-beta.8", - "@contentstack/cli-utilities": "~2.0.0-beta.9", + "@contentstack/cli-utilities": "~2.0.0-beta.10", "@contentstack/cli-variants": "~2.0.0-beta.16", "@contentstack/cli-asset-management": "~1.0.0-beta.4", "@oclif/core": "^4.11.4", @@ -99,4 +99,4 @@ } }, "repository": "https://github.com/contentstack/cli" -} +} \ No newline at end of file diff --git a/packages/contentstack-export/src/commands/cm/stacks/export.ts b/packages/contentstack-export/src/commands/cm/stacks/export.ts index 97f596f7f..97474435f 100644 --- a/packages/contentstack-export/src/commands/cm/stacks/export.ts +++ b/packages/contentstack-export/src/commands/cm/stacks/export.ts @@ -22,6 +22,8 @@ import { Context, ExportConfig } from '../../../types'; import { setupExportConfig } from '../../../utils'; export default class ExportCommand extends Command { + static planProtectedFeatures = ['assetsScan']; + static description: string = messageHandler.parse('Export content from a stack'); static examples: string[] = [ @@ -91,8 +93,11 @@ export default class ExportCommand extends Command { await loadChalk(); let exportDir: string = pathValidator('logs'); try { + console.log('context', this.context); + 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 }; diff --git a/packages/contentstack-export/src/utils/export-config-handler.ts b/packages/contentstack-export/src/utils/export-config-handler.ts index 3b1d559ff..e81611cef 100644 --- a/packages/contentstack-export/src/utils/export-config-handler.ts +++ b/packages/contentstack-export/src/utils/export-config-handler.ts @@ -1,6 +1,15 @@ 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, + assertFeatureEnabled, + FeatureCtx, + isFeatureEnabled, +} from '@contentstack/cli-utilities'; import defaultConfig from '../config'; import { readFile, isDirectoryNonEmpty } from './file-helper'; import { askExportDir, askAPIKey } from './interactive'; @@ -8,7 +17,7 @@ import login from './basic-login'; import { filter, includes } from 'lodash'; import { ExportConfig } from '../types'; -const setupConfig = async (exportCmdFlags: any): Promise => { +const setupConfig = async (exportCmdFlags: any, context: any): Promise => { // Set progress supported module FIRST, before any log calls // This ensures the logger respects the showConsoleLogs setting correctly configHandler.set('log.progressSupportedModule', 'export'); @@ -29,12 +38,9 @@ const setupConfig = async (exportCmdFlags: any): Promise => { if (legacyCsAssetsConfig) { externalConfig.modules['cs-assets'] = externalConfig.modules['cs-assets'] || legacyCsAssetsConfig; delete externalConfig.modules['asset-management']; - log.warn( - 'Config key "modules.asset-management" is deprecated. Please rename it to "modules.cs-assets".', - ); + log.warn('Config key "modules.asset-management" is deprecated. Please rename it to "modules.cs-assets".'); } - config = merge.recursive(config, externalConfig); } config.exportDir = sanitizePath( @@ -52,10 +58,9 @@ const setupConfig = async (exportCmdFlags: any): Promise => { config.exportDir = path.resolve(config.exportDir); if (isDirectoryNonEmpty(config.exportDir)) { - cliux.print( - '\nThe export directory is not empty. Existing files in this folder may be overwritten.', - { color: 'yellow' }, - ); + cliux.print('\nThe export directory is not empty. Existing files in this folder may be overwritten.', { + color: 'yellow', + }); } const managementTokenAlias = exportCmdFlags['management-token-alias'] || exportCmdFlags['alias']; @@ -152,6 +157,25 @@ const setupConfig = async (exportCmdFlags: any): Promise => { 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}`); + } + } + } + return config; }; diff --git a/packages/contentstack-external-migrate/tsconfig.tsbuildinfo b/packages/contentstack-external-migrate/tsconfig.tsbuildinfo index 06e254b83..07e9c07fa 100644 --- a/packages/contentstack-external-migrate/tsconfig.tsbuildinfo +++ b/packages/contentstack-external-migrate/tsconfig.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/index.ts","./src/adapters/registry.ts","./src/adapters/types.ts","./src/adapters/contentful/convert.ts","./src/adapters/contentful/export.ts","./src/adapters/contentful/index.ts","./src/adapters/contentful/validator.ts","./src/commands/external-migrate/audit.ts","./src/commands/external-migrate/convert.ts","./src/commands/external-migrate/create.ts","./src/commands/external-migrate/export.ts","./src/commands/external-migrate/import.ts","./src/commands/external-migrate/status.ts","./src/lib/bundle.ts","./src/lib/clear-import-state.ts","./src/lib/contentful-cli-spawn.ts","./src/lib/conversion-summary.ts","./src/lib/create-stack.ts","./src/lib/csdx-spawn.ts","./src/lib/local-date.ts","./src/lib/log.ts","./src/lib/manifest.ts","./src/lib/parse-json-loose.ts","./src/services/contentful/config.ts","./src/services/contentful/constants.ts","./src/services/contentful/content-type-creator.ts","./src/services/contentful/contentful.service.ts","./src/services/contentful/extension.service.ts","./src/services/contentful/market-app.utils.ts","./src/services/contentful/marketplace.service.ts","./src/services/contentful/releases.ts","./src/services/contentful/scheduled.ts","./src/services/contentful/tasks.ts","./src/services/contentful/types.ts","./src/services/contentful/users.ts","./src/services/contentful/workflows.ts","./src/services/contentful/contentful/jsonrte.ts","./src/services/contentful/contentful/markdown.ts","./src/services/contentful/contentful/roles.ts","./src/services/contentful/contentful/taxonomy.service.ts","./src/services/contentful/mapper/write.ts","./src/services/contentful/migration-contentful/index.js","./src/services/contentful/migration-contentful/libs/contenttypemapper.js","./src/services/contentful/migration-contentful/libs/createinitialmapper.js","./src/services/contentful/migration-contentful/libs/extractcontenttypes.js","./src/services/contentful/migration-contentful/libs/extractlocale.js","./src/services/contentful/migration-contentful/libs/extracttaxonomy.js","./src/services/contentful/migration-contentful/utils/helper.js","./src/services/contentful/prompts/master-locale.ts","./src/services/contentful/utils/custom-logger.utils.ts","./src/services/contentful/utils/index.ts"],"version":"5.9.3"} \ No newline at end of file +{"root":["./src/index.ts","./src/adapters/registry.ts","./src/adapters/types.ts","./src/adapters/contentful/convert.ts","./src/adapters/contentful/export.ts","./src/adapters/contentful/index.ts","./src/adapters/contentful/validator.ts","./src/commands/migrate/audit.ts","./src/commands/migrate/convert.ts","./src/commands/migrate/create.ts","./src/commands/migrate/export.ts","./src/commands/migrate/import.ts","./src/commands/migrate/status.ts","./src/lib/bundle.ts","./src/lib/clear-import-state.ts","./src/lib/contentful-cli-spawn.ts","./src/lib/conversion-summary.ts","./src/lib/create-stack.ts","./src/lib/csdx-spawn.ts","./src/lib/local-date.ts","./src/lib/log.ts","./src/lib/manifest.ts","./src/lib/parse-json-loose.ts","./src/services/contentful/config.ts","./src/services/contentful/constants.ts","./src/services/contentful/content-type-creator.ts","./src/services/contentful/contentful.service.ts","./src/services/contentful/extension.service.ts","./src/services/contentful/market-app.utils.ts","./src/services/contentful/marketplace.service.ts","./src/services/contentful/releases.ts","./src/services/contentful/scheduled.ts","./src/services/contentful/tasks.ts","./src/services/contentful/types.ts","./src/services/contentful/users.ts","./src/services/contentful/workflows.ts","./src/services/contentful/contentful/jsonrte.ts","./src/services/contentful/contentful/markdown.ts","./src/services/contentful/contentful/roles.ts","./src/services/contentful/contentful/taxonomy.service.ts","./src/services/contentful/mapper/write.ts","./src/services/contentful/migration-contentful/index.js","./src/services/contentful/migration-contentful/libs/contenttypemapper.js","./src/services/contentful/migration-contentful/libs/createinitialmapper.js","./src/services/contentful/migration-contentful/libs/extractcontenttypes.js","./src/services/contentful/migration-contentful/libs/extractlocale.js","./src/services/contentful/migration-contentful/libs/extracttaxonomy.js","./src/services/contentful/migration-contentful/utils/helper.js","./src/services/contentful/prompts/master-locale.ts","./src/services/contentful/utils/custom-logger.utils.ts","./src/services/contentful/utils/index.ts"],"version":"5.9.3"} \ No newline at end of file diff --git a/packages/contentstack-import/src/commands/cm/stacks/import.ts b/packages/contentstack-import/src/commands/cm/stacks/import.ts index 1d56aca9a..209b0e6c2 100644 --- a/packages/contentstack-import/src/commands/cm/stacks/import.ts +++ b/packages/contentstack-import/src/commands/cm/stacks/import.ts @@ -20,6 +20,8 @@ import { ModuleImporter } from '../../../import'; import { setupImportConfig } from '../../../utils'; export default class ImportCommand extends Command { + static planProtectedFeatures = ['assetsScan']; + static description = messageHandler.parse('Import content from a stack'); static examples: string[] = [ @@ -124,7 +126,7 @@ export default class ImportCommand extends Command { let importConfig: ImportConfig; try { const { flags } = await this.parse(ImportCommand); - importConfig = await setupImportConfig(flags); + importConfig = await setupImportConfig(flags, this.context); // Prepare the context object createLogContext( this.context?.info?.command || 'cm:stacks:import', diff --git a/packages/contentstack-import/src/utils/import-config-handler.ts b/packages/contentstack-import/src/utils/import-config-handler.ts index abcacecb9..6bdff3e8a 100644 --- a/packages/contentstack-import/src/utils/import-config-handler.ts +++ b/packages/contentstack-import/src/utils/import-config-handler.ts @@ -1,7 +1,7 @@ import merge from 'merge'; import * as path from 'path'; import { omit, filter, includes, isArray } from 'lodash'; -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, readFileSync } from './file-helper'; import { askContentDir, askAPIKey } from './interactive'; @@ -9,7 +9,7 @@ import login from './login-handler'; import { ImportConfig } from '../types'; import { existsSync } from 'fs'; -const setupConfig = async (importCmdFlags: any): Promise => { +const setupConfig = async (importCmdFlags: any, context?: any): Promise => { // Set progress supported module FIRST, before any log calls // This ensures the logger respects the showConsoleLogs setting correctly configHandler.set('log.progressSupportedModule', 'import'); @@ -166,6 +166,25 @@ const setupConfig = async (importCmdFlags: any): Promise => { config.authenticationMethod = authenticationMethod; log.debug('Import configuration setup completed.', { ...config }); + // Deferred plan check — credentials now available after setupImportConfig + 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(`[import] Deferred plan status fetched for "${featureUid}".`); + } catch (error) { + log.warn(`[import] Could not fetch deferred plan status for "${featureUid}": ${(error as Error).message}`); + } + } + } + return config; }; From e6285c718718c56873ffbb9edfb8847f3380400c Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 1 Jul 2026 11:18:45 +0530 Subject: [PATCH 3/3] removed console logs --- packages/contentstack-export/src/commands/cm/stacks/export.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/contentstack-export/src/commands/cm/stacks/export.ts b/packages/contentstack-export/src/commands/cm/stacks/export.ts index 97474435f..afe844ac1 100644 --- a/packages/contentstack-export/src/commands/cm/stacks/export.ts +++ b/packages/contentstack-export/src/commands/cm/stacks/export.ts @@ -93,8 +93,6 @@ export default class ExportCommand extends Command { await loadChalk(); let exportDir: string = pathValidator('logs'); try { - console.log('context', this.context); - const { flags } = await this.parse(ExportCommand); const exportConfig = await setupExportConfig(flags, this.context);