From 7598aaf41679abe7283d5db703f31e4ace0a8720 Mon Sep 17 00:00:00 2001 From: naman-contentstack Date: Thu, 21 May 2026 12:30:56 +0530 Subject: [PATCH 01/18] feat: add support for asset scaning in import command --- .talismanrc | 18 ++---------------- .../src/import/module-importer.ts | 16 ++++++++++++++++ .../src/import/modules/assets.ts | 7 +++++++ .../src/types/import-config.ts | 1 + 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/.talismanrc b/.talismanrc index 16286bff7..1999c2dd4 100644 --- a/.talismanrc +++ b/.talismanrc @@ -1,18 +1,4 @@ fileignoreconfig: - - filename: pnpm-lock.yaml - checksum: 264c0294416c2aa2028c8283831aa7ed17d63e8c69553a7b2b9774336bc0811f - - filename: packages/contentstack-bootstrap/test/bootstrap.test.js - checksum: 37b502482fc32831c39091dd1755e8b0a9f6f8bac89e5eb9d397c6af1f213d83 - - filename: packages/contentstack-bootstrap/test/utils.test.js - checksum: e0ca2eb58ab1c3ac3b4d9c14a17bb8f4788678074dd65f6acc128a8a8f51997f - - filename: packages/contentstack-export-to-csv/test/unit/base-command.test.ts - checksum: 4c2befce053135453c1db31f21351bf3f797ff2f15723ca52e183ed6ed9e48e4 - - filename: packages/contentstack-export-to-csv/test/unit/utils/teams-export.functional.test.ts - checksum: 17cdae91c22a935309bf4514b6616f1aea91fd0166fede182e673ade43667a36 - - filename: packages/contentstack-export-to-csv/test/unit/utils/interactive.test.ts - checksum: 72c1e719e5c51a42debc817a5fe5bb1adee63b2d823df2e9ee36d0b970db7886 - - filename: packages/contentstack-export-to-csv/test/unit/utils/api-client.functional.test.ts - checksum: 6d6638919ef7260f642d32cf730e2654d159d2d3582714fb2d7a9c209b9c6eeb - - filename: packages/contentstack-export-to-csv/test/unit/commands/export-to-csv.test.ts - checksum: 9621a9d013796e99a25e894404c4d7c6799bd33bde77852f09d5e32b4d1c1c49 + - filename: packages/contentstack-import/src/import/modules/assets.ts + checksum: 8d6d1cadf9178f79aeae508f157c019342e1899f9c3f8116bd25b4ec27e593be version: '1.0' diff --git a/packages/contentstack-import/src/import/module-importer.ts b/packages/contentstack-import/src/import/module-importer.ts index 930350a18..109c54160 100755 --- a/packages/contentstack-import/src/import/module-importer.ts +++ b/packages/contentstack-import/src/import/module-importer.ts @@ -26,6 +26,12 @@ class ModuleImporter { const stackDetails: Record = await this.stackAPIClient.fetch(); this.importConfig.stackName = stackDetails.name as string; this.importConfig.org_uid = stackDetails.org_uid as string; + + const assetScanningEnabled = await this.detectAssetScanning(this.importConfig.org_uid); + if (assetScanningEnabled) { + this.importConfig.assetScanningEnabled = true; + this.importConfig.skipAssetsPublish = true; + } } await this.resolveImportPath(); @@ -194,6 +200,16 @@ class ModuleImporter { log.error(`Audit failed with following error. ${error}`, this.importConfig.context); } } + + private async detectAssetScanning(orgUid: string): Promise { + try { + const orgDetails = await this.managementAPIClient.organization(orgUid).fetch({ include_plan: true }); + const features: Array<{ uid: string; enabled?: boolean }> = orgDetails?.plan?.features || []; + return features.some((f) => (f.uid === 'assetsScan' || f.uid === 'amAssetsScan') && f.enabled === true); + } catch { + return false; + } + } } export default ModuleImporter; diff --git a/packages/contentstack-import/src/import/modules/assets.ts b/packages/contentstack-import/src/import/modules/assets.ts index c65345d91..c2ab64bc9 100644 --- a/packages/contentstack-import/src/import/modules/assets.ts +++ b/packages/contentstack-import/src/import/modules/assets.ts @@ -197,6 +197,13 @@ export default class ImportAssets extends BaseClass { this.completeProgress(true); log.success('Assets imported successfully!', this.importConfig.context); + + if (this.importConfig.assetScanningEnabled) { + log.info('ℹ Asset Scanning is enabled for this stack.', this.importConfig.context); + log.info(' Assets cannot be published immediately — scanning must complete first.', this.importConfig.context); + log.info(' Once scanning is done, publish your assets using:', this.importConfig.context); + log.info(' csdx cm:stacks:bulk-assets --data-dir ./content --stack-api-key ', this.importConfig.context); + } } catch (error) { this.completeProgress(false, error?.message || 'Asset import failed'); handleAndLogError(error, { ...this.importConfig.context }); diff --git a/packages/contentstack-import/src/types/import-config.ts b/packages/contentstack-import/src/types/import-config.ts index 1587a360e..60fa64389 100644 --- a/packages/contentstack-import/src/types/import-config.ts +++ b/packages/contentstack-import/src/types/import-config.ts @@ -14,6 +14,7 @@ export default interface ImportConfig extends DefaultConfig, ExternalConfig { authenticationMethod?: string; skipAssetsPublish?: boolean; skipEntriesPublish?: boolean; + assetScanningEnabled?: boolean; cliLogsPath: string; canCreatePrivateApp: boolean; contentDir: string; From 09f2db8da97dbb7d7977736e52b49ac6d10f6f36 Mon Sep 17 00:00:00 2001 From: naman-contentstack Date: Thu, 21 May 2026 12:34:32 +0530 Subject: [PATCH 02/18] chore: update talisman file --- .talismanrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.talismanrc b/.talismanrc index 1999c2dd4..88cd645b3 100644 --- a/.talismanrc +++ b/.talismanrc @@ -1,4 +1,4 @@ fileignoreconfig: - - filename: packages/contentstack-import/src/import/modules/assets.ts +- filename: packages/contentstack-import/src/import/modules/assets.ts checksum: 8d6d1cadf9178f79aeae508f157c019342e1899f9c3f8116bd25b4ec27e593be version: '1.0' From d94825f0f306dd9b071a20d33c575e918ffb16c0 Mon Sep 17 00:00:00 2001 From: Naman Dembla Date: Thu, 28 May 2026 14:29:35 +0530 Subject: [PATCH 03/18] chore: update log message --- packages/contentstack-import/src/import/modules/assets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contentstack-import/src/import/modules/assets.ts b/packages/contentstack-import/src/import/modules/assets.ts index c2ab64bc9..abf864637 100644 --- a/packages/contentstack-import/src/import/modules/assets.ts +++ b/packages/contentstack-import/src/import/modules/assets.ts @@ -199,7 +199,7 @@ export default class ImportAssets extends BaseClass { log.success('Assets imported successfully!', this.importConfig.context); if (this.importConfig.assetScanningEnabled) { - log.info('ℹ Asset Scanning is enabled for this stack.', this.importConfig.context); + log.info(' Asset Scanning is enabled for this stack.', this.importConfig.context); log.info(' Assets cannot be published immediately — scanning must complete first.', this.importConfig.context); log.info(' Once scanning is done, publish your assets using:', this.importConfig.context); log.info(' csdx cm:stacks:bulk-assets --data-dir ./content --stack-api-key ', this.importConfig.context); From be27c50f3f87fbdc6083977cc9ac8a699552a285 Mon Sep 17 00:00:00 2001 From: Naman Dembla Date: Thu, 28 May 2026 14:30:28 +0530 Subject: [PATCH 04/18] chore: update log message spacing --- packages/contentstack-import/src/import/modules/assets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contentstack-import/src/import/modules/assets.ts b/packages/contentstack-import/src/import/modules/assets.ts index abf864637..fbce6e743 100644 --- a/packages/contentstack-import/src/import/modules/assets.ts +++ b/packages/contentstack-import/src/import/modules/assets.ts @@ -199,7 +199,7 @@ export default class ImportAssets extends BaseClass { log.success('Assets imported successfully!', this.importConfig.context); if (this.importConfig.assetScanningEnabled) { - log.info(' Asset Scanning is enabled for this stack.', this.importConfig.context); + log.info(' Asset Scanning is enabled for this stack.', this.importConfig.context); log.info(' Assets cannot be published immediately — scanning must complete first.', this.importConfig.context); log.info(' Once scanning is done, publish your assets using:', this.importConfig.context); log.info(' csdx cm:stacks:bulk-assets --data-dir ./content --stack-api-key ', this.importConfig.context); From 661e8e198e3fe7f9b385be550c6ae223fda92726 Mon Sep 17 00:00:00 2001 From: naman-contentstack Date: Fri, 29 May 2026 14:13:10 +0530 Subject: [PATCH 05/18] feat: feat: add asset scanning support --- .talismanrc | 4 + .../src/base-bulk-command.ts | 12 +- .../src/commands/cm/stacks/bulk-assets.ts | 284 +++++++++++++++++- .../src/interfaces/index.ts | 8 +- .../src/messages/index.ts | 19 ++ .../src/services/asset-service.ts | 49 ++- .../src/services/bulk-operation-service.ts | 60 +++- .../src/utils/batch-queue-handler.ts | 14 +- .../src/utils/config-builder.ts | 70 +++-- .../src/utils/data-dir-asset-fetcher.ts | 114 +++++++ .../src/utils/helpers.ts | 36 ++- .../src/utils/index.ts | 6 + .../src/utils/item-fetcher.ts | 1 + 13 files changed, 611 insertions(+), 66 deletions(-) create mode 100644 packages/contentstack-bulk-operations/src/utils/data-dir-asset-fetcher.ts diff --git a/.talismanrc b/.talismanrc index 3db7ed059..d07a9f629 100644 --- a/.talismanrc +++ b/.talismanrc @@ -5,4 +5,8 @@ fileignoreconfig: checksum: 580932f192dd3fdd8bb2c55b7a7a78f1694f646ef5c5041f86c75668778f7ecb - filename: packages/contentstack-bulk-operations/test/unit/utils/asset-uids-from-file.test.ts checksum: 8123f7a675a0275795b59b15d0f2d5f8f1e57ccbecf3f97249a0dc5a037b9203 +- filename: packages/contentstack-bulk-operations/src/utils/data-dir-asset-fetcher.ts + checksum: ddcf4601ac47be300eba0eb901e4d45d748c2c4eab676c56677cb9a802fe3db0 +- filename: packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts + checksum: c8767e79c1010cccf984d2124b2c6252b7cba1fb1b6a9f216fa7ddb5b195a935 version: '1.0' diff --git a/packages/contentstack-bulk-operations/src/base-bulk-command.ts b/packages/contentstack-bulk-operations/src/base-bulk-command.ts index e5f0bc62c..a6b0a987a 100644 --- a/packages/contentstack-bulk-operations/src/base-bulk-command.ts +++ b/packages/contentstack-bulk-operations/src/base-bulk-command.ts @@ -132,7 +132,7 @@ export abstract class BaseBulkCommand extends Command { protected rateLimiter!: AdaptiveRateLimiter; protected retryStrategy!: RetryStrategy; protected operationExecutor!: OperationExecutor; - private batchResults: Map = new Map(); + protected batchResults: Map = new Map(); protected parsedFlags: any; /** @@ -165,7 +165,7 @@ export abstract class BaseBulkCommand extends Command { } // Fill missing required flags via interactive prompts - flags = await fillMissingFlags(flags); + flags = await this.resolveFlagsInteractively(flags); this.parsedFlags = flags; await this.buildConfiguration(flags); @@ -265,6 +265,14 @@ export abstract class BaseBulkCommand extends Command { } } + + /** + * Resolve flags interactively — subclasses can override to skip prompts for specific modes. + */ + protected async resolveFlagsInteractively(flags: any): Promise { + return await fillMissingFlags(flags); + } + /** * Build operation configuration */ diff --git a/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts b/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts index 71122a91d..53bc50c1a 100644 --- a/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts +++ b/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts @@ -1,12 +1,17 @@ -import { flags, handleAndLogError, FlagInput } from '@contentstack/cli-utilities'; +import * as fs from 'fs'; +import * as path from 'path'; -import { ResourceType } from '../../../interfaces'; +import { flags, handleAndLogError, log } from '@contentstack/cli-utilities'; + +import { AssetPublishData, BulkOperationResult, OperationType, ResourceType } from '../../../interfaces'; import { BaseBulkCommand } from '../../../base-bulk-command'; -import { $t, messages, fetchAssets } from '../../../utils'; +import { $t, messages, fetchAssets, scanDataDirStats, BATCH_CONSTANTS, categorizeByScanStatus } from '../../../utils'; +import type { DataDirScanStats } from '../../../utils'; +import { AssetService } from '../../../services'; /** * Bulk operations command for assets - * Supports publish, unpublish, and cross publish operations + * Supports publish, unpublish, cross-publish, and data-dir publish operations */ export default class BulkAssets extends BaseBulkCommand { static description = messages.BULK_ASSETS_DESCRIPTION; @@ -32,25 +37,47 @@ export default class BulkAssets extends BaseBulkCommand { // Revert (unpublish) previously published assets using success log '<%= config.bin %> <%= command.id %> --revert ./bulk-operation -a myAlias', + + // Publish assets from exported content folder (e.g. after asset scanning clears) + '<%= config.bin %> <%= command.id %> --data-dir ./content --operation publish -k blt123', ]; - static flags: FlagInput = { + static flags = { ...BaseBulkCommand.baseFlags, 'folder-uid': flags.string({ description: messages.FOLDER_UID, }), + 'data-dir': flags.string({ + char: 'd', + description: messages.DATA_DIR_FLAG_DESC, + }), + 'dry-run': flags.boolean({ + description: messages.DRY_RUN_FLAG_DESC, + default: false, + }), }; protected resourceType: ResourceType = ResourceType.ASSET; + protected async resolveFlagsInteractively(flags: any): Promise { + if (flags['data-dir']) { + return flags; + } + return super.resolveFlagsInteractively(flags); + } + async run(): Promise { try { - // Handle cross-publish separately if source-env is specified if (this.bulkOperationConfig.sourceEnv) { await this.handleCrossPublish(this.parsedFlags); return; } + if (this.bulkOperationConfig.dataDir) { + await this.runDataDirFlow(); + return; + } + const assets = await this.fetchItems(); if (assets.length === 0) { @@ -58,18 +85,39 @@ export default class BulkAssets extends BaseBulkCommand { return; } - this.logger.info( - $t(messages.FOUND_ASSETS_TO_OPERATE, { count: assets.length, operation: this.parsedFlags.operation || '' }) - ); + const { clean, pending, quarantined, noStatus } = categorizeByScanStatus(assets); + const scanningEnabled = clean.length + pending.length + quarantined.length > 0; + const publishable = scanningEnabled ? clean : [...clean, ...noStatus]; + + if (scanningEnabled) { + // Log individual skipped assets + pending.forEach((a) => this.logger.warn($t(messages.SCAN_STATUS_SKIPPED_PENDING, { uid: a.uid }))); + quarantined.forEach((a) => this.logger.warn($t(messages.SCAN_STATUS_SKIPPED_QUARANTINED, { uid: a.uid }))); - // Confirm operation - const confirmed = await this.confirmOperation(assets); + this.printScanningDashboard({ + total: assets.length, + clean: clean.length, + pending: pending.length, + quarantined: quarantined.length, + }); + + if (publishable.length === 0) { + this.logger.warn($t(messages.NO_PUBLISHABLE_ASSETS)); + return; + } + } else { + log.info( + $t(messages.FOUND_ASSETS_TO_OPERATE, { count: assets.length, operation: this.parsedFlags.operation || '' }) + ); + } + + const confirmed = await this.confirmOperation(publishable); if (!confirmed) { this.logger.warn($t(messages.OPERATION_CANCELLED)); return; } - const result = await this.executeBulkOperation(assets); + const result = await this.executeBulkOperation(publishable); this.printOperationSummary(result); } catch (error) { handleAndLogError(error); @@ -78,6 +126,218 @@ export default class BulkAssets extends BaseBulkCommand { } } + private async runDataDirFlow(): Promise { + const { dataDir, dryRun } = this.bulkOperationConfig; + + // Capture original CLI locales/envs before pass 1 overwrites them on the config. + const cliLocales = [...(this.bulkOperationConfig.locales || [])]; + const cliEnvs = [...(this.bulkOperationConfig.environments || [])]; + + // Pass 1 — count-only scan: no AssetPublishData objects built, one chunk in memory at a time. + let stats: DataDirScanStats; + try { + stats = await scanDataDirStats(dataDir!, cliEnvs, cliLocales, this.logger); + } catch (err: any) { + this.logger.error($t(messages.DATA_DIR_READ_ERROR, { path: dataDir!, error: err.message || String(err) })); + return; + } + + this.bulkOperationConfig.environments = stats.environments; + this.bulkOperationConfig.locales = stats.locales; + + // Pass 1.5 — fetch scan status for all target UIDs (post-import UIDs on the destination stack). + const targetUids = Object.values(stats.assetUidMapper); + const assetService = new AssetService(this.managementStack, this.deliveryStack, this.logger); + const scanStatusMap = await assetService.fetchScanStatusByUIDs(targetUids); + + let cleanCount = 0; + let pendingCount = 0; + let quarantinedCount = 0; + for (const uid of targetUids) { + const status = scanStatusMap.get(uid); + if (status === 'pending') pendingCount++; + else if (status === 'quarantined') quarantinedCount++; + else cleanCount++; // clean or undefined (scanning disabled) — both are publishable + } + + this.printScanningDashboard({ + total: stats.eligible + stats.skipped + stats.unmapped, + localSkipped: stats.skipped, + unmapped: stats.unmapped, + clean: cleanCount, + pending: pendingCount, + quarantined: quarantinedCount, + }); + + if (cleanCount === 0) { + this.logger.warn($t(messages.NO_PUBLISHABLE_ASSETS)); + return; + } + + // new Array(n) has .length === n but allocates no elements — just for the count. + const confirmed = await this.confirmOperation(new Array(cleanCount)); + if (!confirmed) { + this.logger.warn($t(messages.OPERATION_CANCELLED)); + return; + } + + if (dryRun) { + log.info($t(messages.DATA_DIR_DRY_RUN)); + return; + } + + // Pass 2 — stream and publish: one chunk at a time, batches of ≤50 items enqueued directly. + // stats.assetUidMapper and stats.assetsIndex are reused from pass 1 — no second disk read. + const result = await this.streamAndPublish( + dataDir!, + cliLocales, + stats.totalItems, + stats.assetUidMapper, + stats.assetsIndex, + scanStatusMap + ); + this.printOperationSummary(result); + } + + /** + * Pass 2 of the data-dir flow. + * Reads chunk files one at a time, fills a working batch of ≤50 AssetPublishData items, + * and enqueues each batch directly into the queue manager without ever holding the full + * asset list in memory. Peak memory: one chunk file + one batch of ≤50 items. + * + * assetUidMapper and assetsIndex are passed in from pass 1 to avoid re-reading those files. + * scanStatusMap filters out non-clean assets before enqueueing. + */ + private async streamAndPublish( + dataDir: string, + cliLocales: string[], + totalItemCount: number, + assetUidMapper: Record, + assetsIndex: Record, + scanStatusMap: Map + ): Promise { + // Snapshot both arrays so in-flight mutations to bulkOperationConfig can't corrupt payloads. + const environments = [...this.bulkOperationConfig.environments!]; + const locales = [...this.bulkOperationConfig.locales!]; + const operation = this.bulkOperationConfig.operation as OperationType; + const startTime = Date.now(); + + // Warn early if the mapper is empty — all assets will be skipped and the user needs to know why. + if (Object.keys(assetUidMapper).length === 0) { + this.logger.warn( + 'Asset UID mapper is empty — all assets will be skipped. Ensure the import completed successfully.' + ); + } + + const useOverrideLocales = cliLocales.length > 0; + const BATCH_SIZE = BATCH_CONSTANTS.maxItems; + // totalItemCount comes from pass 1 using identical counting logic — used as upper bound for totalBatches. + // Scan status filtering may reduce the actual count; the invariant check below will log any mismatch. + const totalBatches = Math.ceil(totalItemCount / BATCH_SIZE); + + let workingBatch: AssetPublishData[] = []; + let batchNumber = 0; + let totalSubmitted = 0; + + this.batchResults.clear(); + + const flushBatch = (): void => { + if (workingBatch.length === 0) return; + batchNumber++; + this.queueManager.enqueue(ResourceType.ASSET, operation, { + items: [...workingBatch], + environments, + locales, + batchNumber, + totalBatches, + operation, + }); + totalSubmitted += workingBatch.length; + workingBatch = []; + }; + + for (const chunkFilename of Object.values(assetsIndex)) { + const chunkPath = path.join(dataDir, 'assets', chunkFilename); + const chunkData: Record = JSON.parse(fs.readFileSync(chunkPath, 'utf-8')); + + for (const asset of Object.values(chunkData)) { + if (!asset.publish_details || asset.publish_details.length === 0) continue; + const targetUid = assetUidMapper[asset.uid as string]; + if (!targetUid) continue; + + // Skip assets that did not pass scanning. + const scanStatus = scanStatusMap.get(targetUid); + if (scanStatus === 'quarantined') { + this.logger.warn($t(messages.SCAN_STATUS_SKIPPED_QUARANTINED, { uid: targetUid })); + continue; + } + if (scanStatus === 'pending') { + this.logger.warn($t(messages.SCAN_STATUS_SKIPPED_PENDING, { uid: targetUid })); + continue; + } + + const assetLocales: string[] = useOverrideLocales + ? cliLocales + : [...new Set(asset.publish_details.map((pd: any) => pd.locale as string))]; + + for (const locale of assetLocales) { + workingBatch.push({ type: 'asset', uid: targetUid, locale, version: asset._version }); + if (workingBatch.length >= BATCH_SIZE) { + flushBatch(); + } + } + } + // chunkData falls out of scope here — GC can reclaim it before the next chunk is read. + } + + flushBatch(); + + // Invariant: pass 1 and pass 2 use identical counting logic (excluding scan status filtering). + // If batchNumber < totalBatches, scan status filtering reduced the published count — expected. + if (batchNumber !== totalBatches) { + this.logger.debug( + `Batch count: predicted ${totalBatches}, actual ${batchNumber}. Difference is expected when assets are skipped due to scan status.` + ); + } + + await this.queueManager.waitForCompletion(); + + const duration = Date.now() - startTime; + const jobIds = [...this.batchResults.values()].map((r) => r.jobId).filter((id): id is string => !!id); + + return { success: 0, failed: 0, total: totalSubmitted, duration, jobIds }; + } + + private printScanningDashboard(opts: { + total: number; + clean: number; + pending: number; + quarantined: number; + localSkipped?: number; + unmapped?: number; + }): void { + const { total, clean, pending, quarantined, localSkipped, unmapped } = opts; + const SEP = '─'.repeat(42); + + log.info(''); + log.info(` ${messages.DATA_DIR_ASSET_SCANNING_HEADER}`); + log.info(' ' + SEP); + log.info(` ${messages.DATA_DIR_TOTAL.padEnd(38)} ${total}`); + if (localSkipped !== undefined) { + log.warn(` ${messages.DATA_DIR_NO_PUBLISH_DETAILS.padEnd(38)} ${localSkipped}`); + } + if (unmapped !== undefined) { + log.warn(` ${messages.DATA_DIR_UNMAPPED.padEnd(38)} ${unmapped}`); + } + log.info(' ' + SEP); + log.info(` ${messages.SCAN_STATUS_CLEAN.padEnd(38)} ${clean}`); + if (pending > 0) log.warn(` ${messages.SCAN_STATUS_PENDING.padEnd(38)} ${pending}`); + if (quarantined > 0) log.warn(` ${messages.SCAN_STATUS_QUARANTINED.padEnd(38)} ${quarantined}`); + log.info(' ' + SEP); + log.info(` ${messages.DATA_DIR_WILL_PUBLISH.padEnd(38)} ${clean}`); + log.info(''); + } + protected async fetchItems(): Promise { return await fetchAssets(this.bulkOperationConfig, this.managementStack, this.deliveryStack, this.logger); } diff --git a/packages/contentstack-bulk-operations/src/interfaces/index.ts b/packages/contentstack-bulk-operations/src/interfaces/index.ts index c315fba34..13a4f2959 100644 --- a/packages/contentstack-bulk-operations/src/interfaces/index.ts +++ b/packages/contentstack-bulk-operations/src/interfaces/index.ts @@ -58,6 +58,8 @@ export interface BulkOperationConfig { // Asset-specific options folderUid?: string; + dataDir?: string; + dryRun?: boolean; // Cross-publish sourceEnv?: string; @@ -135,6 +137,7 @@ export interface Asset { title?: string; _version?: number; publish_details?: PublishDetails[]; + _asset_scan_status?: 'pending' | 'clean' | 'quarantined'; [key: string]: any; } @@ -196,6 +199,8 @@ export interface CommandFlags { // Asset-specific flags 'folder-uid'?: string; + 'data-dir'?: string; + 'dry-run'?: boolean; /** AM bulk delete/move */ 'space-uid'?: string; @@ -254,6 +259,7 @@ export interface AssetPublishData { locale: string; version?: number; publish_details?: PublishDetails[]; + _asset_scan_status?: 'pending' | 'clean' | 'quarantined'; } /** One row for AM bulk-delete payload `{ uid, locale }[]`. */ @@ -444,4 +450,4 @@ export interface CrossPublishConfig { contentTypes?: string[]; resourceType: ResourceType; deliveryStack: DeliveryStack | null; // Pass delivery stack from command (optional) -} \ No newline at end of file +} diff --git a/packages/contentstack-bulk-operations/src/messages/index.ts b/packages/contentstack-bulk-operations/src/messages/index.ts index a285f734e..bc9633540 100644 --- a/packages/contentstack-bulk-operations/src/messages/index.ts +++ b/packages/contentstack-bulk-operations/src/messages/index.ts @@ -210,6 +210,25 @@ const bulkAssetsMsg = { CROSS_PUBLISHING: 'Cross-publishing from {sourceEnv} to {targetEnvs}', SYNCED_ASSETS: 'Synced {count} assets from {sourceEnv}', ASSETS_READY_FOR_CROSS_PUBLISH: '{count} assets ready for cross-publish', + + // Data-dir / scanning dashboard + DATA_DIR_ASSET_SCANNING_HEADER: 'Asset Scan Status', + DATA_DIR_TOTAL: 'Total assets found', + DATA_DIR_VALID: 'Clean (will publish)', + DATA_DIR_NO_PUBLISH_DETAILS: 'No publish details (skipped)', + DATA_DIR_UNMAPPED: 'Not imported / UID unmapped (skipped)', + DATA_DIR_WILL_PUBLISH: 'Will publish', + DATA_DIR_DRY_RUN: 'Dry run — no publish API calls will be made.', + DATA_DIR_FLAG_DESC: 'Path to exported content folder containing asset publish details.', + DRY_RUN_FLAG_DESC: 'Preview the publish plan without making any API calls.', + DATA_DIR_READ_ERROR: 'Failed to read data directory at {path}: {error}', + SCAN_STATUS_CLEAN: 'Clean (will publish)', + SCAN_STATUS_PENDING: 'Still scanning (skipped)', + SCAN_STATUS_QUARANTINED: 'Quarantined (skipped)', + SCAN_STATUS_SKIPPED_PENDING: 'Skipped (still scanning): {uid}', + SCAN_STATUS_SKIPPED_QUARANTINED: 'Skipped (quarantined): {uid}', + SCAN_STATUS_FETCHING: 'Checking asset scan status for {count} assets...', + NO_PUBLISHABLE_ASSETS: 'No publishable assets — all assets are either still scanning or quarantined.', }; /** diff --git a/packages/contentstack-bulk-operations/src/services/asset-service.ts b/packages/contentstack-bulk-operations/src/services/asset-service.ts index aba844fb1..903ce3730 100644 --- a/packages/contentstack-bulk-operations/src/services/asset-service.ts +++ b/packages/contentstack-bulk-operations/src/services/asset-service.ts @@ -37,7 +37,7 @@ export class AssetService { const batchUids = uids.slice(i, i + BATCH_CONSTANTS.assetFetchBatchSize); const batchPromises = batchUids.map(async (uid) => { try { - const asset = this.deliveryStack ? await this.deliveryStack.asset(uid).fetch() : undefined; + const asset = await this.deliveryStack?.asset(uid).fetch(); return asset; } catch (error: any) { // Asset might not exist or not be published to this environment @@ -125,7 +125,13 @@ export class AssetService { try { while (hasMore) { - const queryOptions: any = { skip, limit, include_count: true, include_publish_details: true }; + const queryOptions: any = { + skip, + limit, + include_count: true, + include_publish_details: true, + include_asset_scan_status: true, + }; // Add any filters from options if (options.query) { @@ -207,7 +213,14 @@ export class AssetService { while (hasMore) { const query = this.stack .asset() - .query({ skip, limit, include_count: true, include_publish_details: true, folder: folderUid }); + .query({ + skip, + limit, + include_count: true, + include_publish_details: true, + include_asset_scan_status: true, + folder: folderUid, + }); const response = await query.find(); const assets = response.items || []; @@ -273,4 +286,34 @@ export class AssetService { throw error; } } + + /** + * Fetch scan status for a specific list of asset UIDs. + * Batches requests at 100 UIDs per call to stay within API limits. + * Returns a Map — undefined means scanning is not enabled on the stack. + */ + async fetchScanStatusByUIDs(uids: string[]): Promise> { + const statusMap = new Map(); + if (uids.length === 0) return statusMap; + + this.logger.info($t(messages.SCAN_STATUS_FETCHING, { count: uids.length })); + + const BATCH = 100; + for (let i = 0; i < uids.length; i += BATCH) { + const batch = uids.slice(i, i + BATCH); + try { + const response = await this.stack + .asset() + .query({ uid: { $in: batch }, include_asset_scan_status: true, limit: BATCH }) + .find(); + for (const asset of response.items || []) { + statusMap.set(asset.uid, asset._asset_scan_status); + } + } catch (error: any) { + this.logger.warn(`Failed to fetch scan status for batch starting at index ${i}: ${error?.message}`); + } + } + + return statusMap; + } } diff --git a/packages/contentstack-bulk-operations/src/services/bulk-operation-service.ts b/packages/contentstack-bulk-operations/src/services/bulk-operation-service.ts index 705d1a90c..18c9618f5 100644 --- a/packages/contentstack-bulk-operations/src/services/bulk-operation-service.ts +++ b/packages/contentstack-bulk-operations/src/services/bulk-operation-service.ts @@ -47,13 +47,15 @@ export class BulkOperationService { async executeBulkPublish( items: Array, operation: OperationType, - resourceType: ResourceType + resourceType: ResourceType, + environments?: string[], + locales?: string[] ): Promise { this.logger.info($t(messages.SUBMITTING_BULK_JOB, { operation, count: items.length })); try { // Step 1: Submit bulk job - const jobId = await this.submitBulkJob(items, operation, resourceType); + const jobId = await this.submitBulkJob(items, operation, resourceType, environments, locales); this.logger.debug($t(messages.BULK_JOB_CREATED, { jobId })); // Return immediate result after job submission @@ -78,10 +80,12 @@ export class BulkOperationService { private async submitBulkJob( items: Array, operation: OperationType, - resourceType: ResourceType + resourceType: ResourceType, + environments?: string[], + locales?: string[] ): Promise { try { - const payload = this.prepareBulkPayload(items, operation, resourceType); + const payload = this.prepareBulkPayload(items, operation, resourceType, environments, locales); let response: any; switch (operation) { case OperationType.PUBLISH: @@ -203,16 +207,23 @@ export class BulkOperationService { private prepareBulkPayload( items: Array, operation: OperationType, - resourceType: ResourceType + resourceType: ResourceType, + environments?: string[], + locales?: string[] ): any { if (resourceType === ResourceType.ENTRY) { - return this.prepareEntryBulkPayload(items as EntryPublishData[], operation); + return this.prepareEntryBulkPayload(items as EntryPublishData[], operation, environments, locales); } else { - return this.prepareAssetBulkPayload(items as AssetPublishData[], operation); + return this.prepareAssetBulkPayload(items as AssetPublishData[], operation, environments, locales); } } - private prepareEntryBulkPayload(items: EntryPublishData[], operation: OperationType): any { + private prepareEntryBulkPayload( + items: EntryPublishData[], + operation: OperationType, + batchEnvironments?: string[], + batchLocales?: string[] + ): any { const entries = items.map((item) => { const entry: any = { uid: item.uid, @@ -233,8 +244,17 @@ export class BulkOperationService { return entry; }); - const environments = items[0]?.publish_details?.map((pd) => pd.environment) || []; - const locales = Array.from(new Set(items.map((item) => item.locale))); + const environments = batchEnvironments?.length + ? batchEnvironments + : items[0]?.publish_details?.map((pd) => pd.environment) || []; + const locales = batchLocales?.length ? batchLocales : Array.from(new Set(items.map((item) => item.locale))); + + if (!environments.length) { + throw new Error('No environments for bulk publish. Ensure entries have publish_details with environment data.'); + } + if (!locales.length) { + throw new Error('No locales for bulk publish. Ensure entries have a locale field.'); + } return { entries, @@ -244,14 +264,28 @@ export class BulkOperationService { }; } - private prepareAssetBulkPayload(items: AssetPublishData[], operation: OperationType): any { + private prepareAssetBulkPayload( + items: AssetPublishData[], + operation: OperationType, + batchEnvironments?: string[], + batchLocales?: string[] + ): any { const assets = items.map((item) => ({ uid: item.uid, version: item.version, })); - const environments = items[0]?.publish_details?.map((pd) => pd.environment) || []; - const locales = items[0]?.publish_details?.map((pd) => pd.locale) || []; + const environments = batchEnvironments?.length + ? batchEnvironments + : items[0]?.publish_details?.map((pd) => pd.environment) || []; + const locales = batchLocales?.length ? batchLocales : items[0]?.publish_details?.map((pd) => pd.locale) || []; + + if (!environments.length) { + throw new Error('No environments for bulk publish. Ensure assets have publish_details with environment data.'); + } + if (!locales.length) { + throw new Error('No locales for bulk publish. Ensure assets have publish_details with locale data.'); + } return { assets, diff --git a/packages/contentstack-bulk-operations/src/utils/batch-queue-handler.ts b/packages/contentstack-bulk-operations/src/utils/batch-queue-handler.ts index e32eadcd8..4e624e5da 100644 --- a/packages/contentstack-bulk-operations/src/utils/batch-queue-handler.ts +++ b/packages/contentstack-bulk-operations/src/utils/batch-queue-handler.ts @@ -21,7 +21,7 @@ export function setupBatchQueueListeners(config: BatchQueueConfig) { } logger.info( - `Processing batch ${batch.batchNumber ?? 0}/${batch.totalBatches ?? 0}: ` + + `Processing batch ${batch.batchNumber}/${batch.totalBatches}: ` + `${batch.items.length} items, ` + `${batch.locales.length} locales, ` + `${batch.environments.length} environments` @@ -29,7 +29,13 @@ export function setupBatchQueueListeners(config: BatchQueueConfig) { (async () => { try { - const result = await bulkService.executeBulkPublish(batch.items, batch.operation, resourceType); + const result = await bulkService.executeBulkPublish( + batch.items, + batch.operation, + resourceType, + batch.environments, + batch.locales + ); batchResults.set(item.id, result); queueManager.updateItemStatus(item.id, OperationStatus.SUCCESS); @@ -76,7 +82,7 @@ export function setupBatchQueueListeners(config: BatchQueueConfig) { if (!batch) return; handleAndLogError(error, { - batchNumber: `${batch.batchNumber ?? 0}/${batch.totalBatches ?? 0}`, + batchNumber: `${batch.batchNumber}/${batch.totalBatches}`, itemCount: batch.items.length, }); @@ -109,7 +115,7 @@ async function handleRetryOrFailure({ : retryStrategy.getDelay(item.retryCount); logger.warn( - `Batch ${batch.batchNumber ?? 0}/${batch.totalBatches ?? 0} failed with ${ + `Batch ${batch.batchNumber}/${batch.totalBatches} failed with ${ isRateLimit ? '429 Rate Limit' : getErrorCode(error) }, retrying in ${Math.ceil(delay / 1000)}s` ); diff --git a/packages/contentstack-bulk-operations/src/utils/config-builder.ts b/packages/contentstack-bulk-operations/src/utils/config-builder.ts index c53deb98c..e92e9fb7c 100644 --- a/packages/contentstack-bulk-operations/src/utils/config-builder.ts +++ b/packages/contentstack-bulk-operations/src/utils/config-builder.ts @@ -69,24 +69,28 @@ function validateConfig(config: BulkOperationConfig): string[] { errors.push(`Invalid operation type: ${config.operation}. Must be 'publish' or 'unpublish'`); } - // Environments validation - if ( - (operation === OperationType.PUBLISH || operation === OperationType.UNPUBLISH) && - (!config.environments || config.environments.length === 0) - ) { - errors.push('Environments are required for publish/unpublish operations'); - } - if (config.environments?.some((env) => !env || env.trim() === '')) { - errors.push('Environment list cannot contain empty values'); + // Environments validation — skipped when assets are read from a data directory + if (!config.dataDir) { + if ( + (operation === OperationType.PUBLISH || operation === OperationType.UNPUBLISH) && + (!config.environments || config.environments.length === 0) + ) { + errors.push('Environments are required for publish/unpublish operations'); + } + if (config.environments?.some((env) => !env || env.trim() === '')) { + errors.push('Environment list cannot contain empty values'); + } } - // Locales validation + // Locales validation — skipped when assets are read from a data directory const isNonLocalized = config.filter === FilterType.NON_LOCALIZED; - if (!isNonLocalized && (!config.locales || config.locales.length === 0)) { - errors.push('Locales are required'); - } - if (config.locales?.some((locale) => !locale || locale.trim() === '')) { - errors.push('Locale list cannot contain empty values'); + if (!config.dataDir) { + if (!isNonLocalized && (!config.locales || config.locales.length === 0)) { + errors.push('Locales are required'); + } + if (config.locales?.some((locale) => !locale || locale.trim() === '')) { + errors.push('Locale list cannot contain empty values'); + } } // Filter validation @@ -144,24 +148,28 @@ function validateCommandFlags(flags: CommandFlags): string[] { const operation = flags.operation as OperationType; - // Environment validation - if ( - (operation === OperationType.PUBLISH || operation === OperationType.UNPUBLISH) && - (!flags.environments || flags.environments.length === 0) - ) { - errors.push('Environments are required for publish/unpublish operations'); - } - if (flags.environments?.some((env) => !env || env.trim() === '')) { - errors.push('Environment list cannot contain empty values'); + // Environment validation — skipped when assets are read from a data directory + if (!flags['data-dir']) { + if ( + (operation === OperationType.PUBLISH || operation === OperationType.UNPUBLISH) && + (!flags.environments || flags.environments.length === 0) + ) { + errors.push('Environments are required for publish/unpublish operations'); + } + if (flags.environments?.some((env) => !env || env.trim() === '')) { + errors.push('Environment list cannot contain empty values'); + } } - // Locale validation + // Locale validation — skipped when assets are read from a data directory const isNonLocalized = flags.filter === FilterType.NON_LOCALIZED; - if (!isNonLocalized && (!flags.locales || flags.locales.length === 0)) { - errors.push('Locales are required'); - } - if (flags.locales?.some((locale) => !locale || locale.trim() === '')) { - errors.push('Locale list cannot contain empty values'); + if (!flags['data-dir']) { + if (!isNonLocalized && (!flags.locales || flags.locales.length === 0)) { + errors.push('Locales are required'); + } + if (flags.locales?.some((locale) => !locale || locale.trim() === '')) { + errors.push('Locale list cannot contain empty values'); + } } // Content types validation @@ -243,6 +251,8 @@ export function buildConfig(flags: CommandFlags): BulkOperationConfig { contentTypes: flags['content-types'] !== undefined ? expandFlagStringList(flags['content-types']) : undefined, includeVariants: flags['include-variants'], folderUid: flags['folder-uid'], + dataDir: flags['data-dir'], + dryRun: flags['dry-run'], sourceEnv: flags['source-env'], publishMode: (flags['publish-mode'] as PublishMode) || PublishMode.BULK, apiVersion: flags['api-version'] || '3', diff --git a/packages/contentstack-bulk-operations/src/utils/data-dir-asset-fetcher.ts b/packages/contentstack-bulk-operations/src/utils/data-dir-asset-fetcher.ts new file mode 100644 index 000000000..71ea47bd3 --- /dev/null +++ b/packages/contentstack-bulk-operations/src/utils/data-dir-asset-fetcher.ts @@ -0,0 +1,114 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +export interface DataDirScanStats { + /** Number of assets eligible for publish (have publish_details + mapped UID). */ + eligible: number; + /** Total AssetPublishData items that will be created (eligible × locale expansions). */ + totalItems: number; + skipped: number; + unmapped: number; + environments: string[]; + locales: string[]; + /** Reusable in pass 2 — already loaded during pass 1, avoids a second disk read. */ + assetUidMapper: Record; + /** Reusable in pass 2 — already loaded during pass 1, avoids a second disk read. */ + assetsIndex: Record; +} + +/** + * Pass 1: count-only scan of the data directory. + * Reads chunk files one at a time, counts eligible/skipped/unmapped, and + * discovers environments and locales — without building any AssetPublishData objects. + * Memory footprint: uid mapper + env map + one chunk at a time. + * + * Returns assetUidMapper and assetsIndex so pass 2 (streamAndPublish) can reuse them + * without re-reading the same files from disk. + */ +export async function scanDataDirStats( + dataDir: string, + overrideEnvs?: string[], + overrideLocales?: string[], + logger?: any +): Promise { + const assetsIndexPath = path.join(dataDir, 'assets', 'assets.json'); + const environmentsPath = path.join(dataDir, 'environments', 'environments.json'); + const assetUidMapperPath = path.join(dataDir, 'mapper', 'assets', 'uid-mapping.json'); + + if (!fs.existsSync(assetsIndexPath)) { + throw new Error( + `Asset index not found: ${assetsIndexPath}. Ensure --data-dir points to the import backup directory.` + ); + } + + let assetUidMapper: Record = {}; + if (fs.existsSync(assetUidMapperPath)) { + assetUidMapper = JSON.parse(fs.readFileSync(assetUidMapperPath, 'utf-8')); + } else { + logger?.warn( + `Asset UID mapper not found: ${assetUidMapperPath}. Ensure --data-dir points to the import backup directory.` + ); + } + + const environmentsMap: Record = {}; + if (fs.existsSync(environmentsPath)) { + const envData: Record = JSON.parse(fs.readFileSync(environmentsPath, 'utf-8')); + for (const [uid, env] of Object.entries(envData)) { + environmentsMap[uid] = (env as any).name || uid; + } + } else { + logger?.warn(`Environments file not found: ${environmentsPath}`); + } + + const assetsIndex: Record = JSON.parse(fs.readFileSync(assetsIndexPath, 'utf-8')); + + let eligible = 0; + let totalItems = 0; + let skipped = 0; + let unmapped = 0; + const allEnvs = new Set(); + const allLocales = new Set(); + + for (const chunkFilename of Object.values(assetsIndex)) { + const chunkPath = path.join(dataDir, 'assets', chunkFilename); + const chunkData: Record = JSON.parse(fs.readFileSync(chunkPath, 'utf-8')); + + for (const asset of Object.values(chunkData)) { + if (!asset.publish_details || asset.publish_details.length === 0) { + skipped++; + continue; + } + + const targetUid = assetUidMapper[asset.uid as string]; + if (!targetUid) { + unmapped++; + continue; + } + + eligible++; + + if (!overrideLocales?.length) { + for (const pd of asset.publish_details) { + if (pd.locale) allLocales.add(pd.locale as string); + } + } + if (!overrideEnvs?.length) { + for (const pd of asset.publish_details) { + const envName = environmentsMap[pd.environment] || pd.environment; + if (envName) allEnvs.add(envName as string); + } + } + + const localeCount = overrideLocales?.length + ? overrideLocales.length + : new Set(asset.publish_details.map((pd: any) => pd.locale as string)).size; + totalItems += localeCount; + } + // chunkData falls out of scope here — GC reclaims it + } + + const environments = overrideEnvs?.length ? overrideEnvs : [...allEnvs]; + const locales = overrideLocales?.length ? overrideLocales : [...allLocales]; + + return { eligible, totalItems, skipped, unmapped, environments, locales, assetUidMapper, assetsIndex }; +} diff --git a/packages/contentstack-bulk-operations/src/utils/helpers.ts b/packages/contentstack-bulk-operations/src/utils/helpers.ts index 7e5beb260..8b7666048 100644 --- a/packages/contentstack-bulk-operations/src/utils/helpers.ts +++ b/packages/contentstack-bulk-operations/src/utils/helpers.ts @@ -1,7 +1,7 @@ import chalk from 'chalk'; import { getLogPath } from '@contentstack/cli-utilities'; import { $t, messages } from './index'; -import { AssetPublishData, EntryPublishData, BulkOperationResult, BulkJobResult } from '../interfaces'; +import { AssetPublishData, EntryPublishData, BulkOperationResult, BulkJobResult, Asset } from '../interfaces'; export function chunkArray(array: T[], chunkSize: number): T[][] { const chunks: T[][] = []; @@ -122,3 +122,37 @@ export function logSummary(result: any): void { console.log(''); } + +/** + * Categorize assets by their _asset_scan_status field. + * Assets with no status field belong to stacks where scanning is disabled — treat as publishable. + */ +export function categorizeByScanStatus(assets: Asset[]): { + clean: Asset[]; + pending: Asset[]; + quarantined: Asset[]; + noStatus: Asset[]; +} { + const clean: Asset[] = []; + const pending: Asset[] = []; + const quarantined: Asset[] = []; + const noStatus: Asset[] = []; + + for (const asset of assets) { + switch (asset._asset_scan_status) { + case 'clean': + clean.push(asset); + break; + case 'pending': + pending.push(asset); + break; + case 'quarantined': + quarantined.push(asset); + break; + default: + noStatus.push(asset); + } + } + + return { clean, pending, quarantined, noStatus }; +} diff --git a/packages/contentstack-bulk-operations/src/utils/index.ts b/packages/contentstack-bulk-operations/src/utils/index.ts index 02c334e3e..66497598c 100644 --- a/packages/contentstack-bulk-operations/src/utils/index.ts +++ b/packages/contentstack-bulk-operations/src/utils/index.ts @@ -21,6 +21,7 @@ import { aggregateBatchResults, createOperationResult, logSummary, + categorizeByScanStatus, } from './helpers'; import { setupBatchQueueListeners } from './batch-queue-handler'; import { confirmOperation } from './operation-confirmation'; @@ -51,6 +52,8 @@ import { validateAndBuildBulkDeleteItems, LoadAssetUidsError, } from './asset-uids-from-file'; +import { scanDataDirStats } from './data-dir-asset-fetcher'; +import type { DataDirScanStats } from './data-dir-asset-fetcher'; import { compareFieldValues, compareNonLocalizedFields, @@ -90,6 +93,7 @@ export { fetchAssets, fetchEntries, logSummary, + categorizeByScanStatus, logOperationInfo, validateBatch, enqueueIndividualItems, @@ -117,4 +121,6 @@ export { loadBulkDeleteItemsFromFile, validateAndBuildBulkDeleteItems, LoadAssetUidsError, + scanDataDirStats, }; +export type { DataDirScanStats }; diff --git a/packages/contentstack-bulk-operations/src/utils/item-fetcher.ts b/packages/contentstack-bulk-operations/src/utils/item-fetcher.ts index 35076ade2..c794520ce 100644 --- a/packages/contentstack-bulk-operations/src/utils/item-fetcher.ts +++ b/packages/contentstack-bulk-operations/src/utils/item-fetcher.ts @@ -221,6 +221,7 @@ export async function fetchAssets( environment: env, locale, })), + _asset_scan_status: asset._asset_scan_status, }); } } From 13eae5915e36f1a0fa5ebf4d95f8957eca4d129c Mon Sep 17 00:00:00 2001 From: naman-contentstack Date: Fri, 29 May 2026 14:15:52 +0530 Subject: [PATCH 06/18] chore: add config in bulk package --- packages/contentstack-bulk-operations/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/contentstack-bulk-operations/package.json b/packages/contentstack-bulk-operations/package.json index 39b6c1599..8f787d1bf 100644 --- a/packages/contentstack-bulk-operations/package.json +++ b/packages/contentstack-bulk-operations/package.json @@ -112,6 +112,7 @@ }, "csdxConfig": { "shortCommandName": { + "cm:stacks:bulk-am-assets": "BOAM", "cm:stacks:bulk-assets": "BOA", "cm:stacks:bulk-entries": "BOE", "cm:stacks:bulk-taxonomies": "BOT" From 04726617b3658525272815cac5257268b125bbcf Mon Sep 17 00:00:00 2001 From: naman-contentstack Date: Fri, 5 Jun 2026 15:57:10 +0530 Subject: [PATCH 07/18] chore: fix failing test and lint issues --- .../src/base-bulk-command.ts | 3 +-- .../src/services/asset-service.ts | 18 ++++++++---------- .../services/bulk-operation-service.test.ts | 15 +++++---------- 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/packages/contentstack-bulk-operations/src/base-bulk-command.ts b/packages/contentstack-bulk-operations/src/base-bulk-command.ts index 567961bce..2693105fe 100644 --- a/packages/contentstack-bulk-operations/src/base-bulk-command.ts +++ b/packages/contentstack-bulk-operations/src/base-bulk-command.ts @@ -164,7 +164,7 @@ export abstract class BaseBulkCommand extends Command { } // Fill missing required flags via interactive prompts - flags = await this.resolveFlagsInteractively(flags); + flags = await this.resolveFlagsInteractively(flags); this.parsedFlags = flags; await this.buildConfiguration(flags); @@ -264,7 +264,6 @@ export abstract class BaseBulkCommand extends Command { } } - /** * Resolve flags interactively — subclasses can override to skip prompts for specific modes. */ diff --git a/packages/contentstack-bulk-operations/src/services/asset-service.ts b/packages/contentstack-bulk-operations/src/services/asset-service.ts index 903ce3730..562e316af 100644 --- a/packages/contentstack-bulk-operations/src/services/asset-service.ts +++ b/packages/contentstack-bulk-operations/src/services/asset-service.ts @@ -211,16 +211,14 @@ export class AssetService { try { while (hasMore) { - const query = this.stack - .asset() - .query({ - skip, - limit, - include_count: true, - include_publish_details: true, - include_asset_scan_status: true, - folder: folderUid, - }); + const query = this.stack.asset().query({ + skip, + limit, + include_count: true, + include_publish_details: true, + include_asset_scan_status: true, + folder: folderUid, + }); const response = await query.find(); const assets = response.items || []; diff --git a/packages/contentstack-bulk-operations/test/unit/services/bulk-operation-service.test.ts b/packages/contentstack-bulk-operations/test/unit/services/bulk-operation-service.test.ts index 60e1d6881..b34a84e20 100644 --- a/packages/contentstack-bulk-operations/test/unit/services/bulk-operation-service.test.ts +++ b/packages/contentstack-bulk-operations/test/unit/services/bulk-operation-service.test.ts @@ -132,7 +132,7 @@ describe('BulkOperationService', () => { content_type: 'blog', locale: 'en-us', version: 1, - publish_details: [], + publish_details: [{ environment: 'production', locale: 'en-us', version: 1 }], }, ]; @@ -168,7 +168,7 @@ describe('BulkOperationService', () => { content_type: 'blog', locale: 'en-us', version: 1, - publish_details: [], + publish_details: [{ environment: 'production', locale: 'en-us', version: 1 }], }, ]; @@ -390,14 +390,9 @@ describe('BulkOperationService', () => { } as EntryPublishData, ]; - const payload = (bulkOperationService as any).prepareBulkPayload( - mockItems, - OperationType.PUBLISH, - ResourceType.ENTRY - ); - - expect(payload.entries).to.have.lengthOf(1); - expect(payload.environments).to.deep.equal([]); + expect(() => + (bulkOperationService as any).prepareBulkPayload(mockItems, OperationType.PUBLISH, ResourceType.ENTRY) + ).to.throw('No environments for bulk publish'); }); }); From 33bd17aceafb8c0e758ccea6d715d7e4fa5f78ec Mon Sep 17 00:00:00 2001 From: naman-contentstack Date: Mon, 8 Jun 2026 12:48:52 +0530 Subject: [PATCH 08/18] feat: enhance bulk asset operations with data-dir support and user prompts --- .../src/commands/cm/stacks/bulk-assets.ts | 4 +-- .../src/messages/index.ts | 5 ++++ .../src/utils/interactive.ts | 25 +++++++++++++++++-- .../src/commands/cm/stacks/import.ts | 5 ++++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts b/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts index 53bc50c1a..5c4770578 100644 --- a/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts +++ b/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts @@ -5,7 +5,7 @@ import { flags, handleAndLogError, log } from '@contentstack/cli-utilities'; import { AssetPublishData, BulkOperationResult, OperationType, ResourceType } from '../../../interfaces'; import { BaseBulkCommand } from '../../../base-bulk-command'; -import { $t, messages, fetchAssets, scanDataDirStats, BATCH_CONSTANTS, categorizeByScanStatus } from '../../../utils'; +import { $t, messages, fetchAssets, scanDataDirStats, BATCH_CONSTANTS, categorizeByScanStatus, fillMissingFlags } from '../../../utils'; import type { DataDirScanStats } from '../../../utils'; import { AssetService } from '../../../services'; @@ -63,7 +63,7 @@ export default class BulkAssets extends BaseBulkCommand { if (flags['data-dir']) { return flags; } - return super.resolveFlagsInteractively(flags); + return fillMissingFlags(flags, { promptDataDir: true }); } async run(): Promise { diff --git a/packages/contentstack-bulk-operations/src/messages/index.ts b/packages/contentstack-bulk-operations/src/messages/index.ts index ab7e6f7d9..c51fe6023 100644 --- a/packages/contentstack-bulk-operations/src/messages/index.ts +++ b/packages/contentstack-bulk-operations/src/messages/index.ts @@ -379,6 +379,11 @@ const interactiveMsg = { TAXONOMY_UNSUPPORTED_RETRY: 'Retry and revert are not supported for bulk-taxonomies.', TAXONOMY_UNSUPPORTED_CROSS_PUBLISH: 'Cross-publish is not supported for bulk-taxonomies.', + // Data-dir (backup folder) prompt + USE_DATA_DIR_PROMPT: 'Do you want to publish assets using publish details from an import backup folder (data-dir)?', + ENTER_DATA_DIR: 'Enter the path to the import backup folder (data-dir):', + DATA_DIR_REQUIRED: 'Backup folder path is required', + // Errors NO_DELIVERY_TOKENS_FOUND: 'No delivery token aliases found. Add one using: csdx auth:tokens:add -a --delivery-token --api-key --environment --type delivery', diff --git a/packages/contentstack-bulk-operations/src/utils/interactive.ts b/packages/contentstack-bulk-operations/src/utils/interactive.ts index 2aa68cdc1..a17485e9a 100644 --- a/packages/contentstack-bulk-operations/src/utils/interactive.ts +++ b/packages/contentstack-bulk-operations/src/utils/interactive.ts @@ -151,7 +151,7 @@ async function promptForSourceAlias(): Promise { /** * Fills in missing required flags by prompting the user */ -export async function fillMissingFlags(flags: any): Promise { +export async function fillMissingFlags(flags: any, options?: { promptDataDir?: boolean }): Promise { const updatedFlags = { ...flags }; // Skip interactive mode for retry/revert operations @@ -169,9 +169,10 @@ export async function fillMissingFlags(flags: any): Promise { // Check if non-localized filter is used const isNonLocalized = updatedFlags.filter === FilterType.NON_LOCALIZED; const needsLocales = !isNonLocalized && (!updatedFlags.locales || updatedFlags.locales.length === 0); + const needsDataDir = options?.promptDataDir && !updatedFlags['data-dir']; // Only show interactive mode header if we need to prompt - if (needsCredentials || needsOperation || needsEnvironments || needsLocales) { + if (needsCredentials || needsOperation || needsEnvironments || needsLocales || needsDataDir) { cliux.print(messages.INTERACTIVE_MODE_START, { color: 'cyan' }); didPrompt = true; } @@ -191,6 +192,26 @@ export async function fillMissingFlags(flags: any): Promise { updatedFlags.operation = await promptForOperation(); } + // 2.5. Data-dir (import backup folder) — alternative to environments/locales for asset publish + if (needsDataDir) { + const useDataDir = await cliux.inquire({ + type: 'confirm', + name: 'useDataDir', + message: messages.USE_DATA_DIR_PROMPT, + default: false, + }); + if (useDataDir) { + updatedFlags['data-dir'] = await cliux.inquire({ + type: 'input', + name: 'dataDir', + message: messages.ENTER_DATA_DIR, + validate: (v: string) => (!v?.trim() ? messages.DATA_DIR_REQUIRED : true), + }); + cliux.print(messages.INTERACTIVE_MODE_COMPLETE, { color: 'green' }); + return updatedFlags; + } + } + // 3. Check for cross-publish mode const isCrossPublish = updatedFlags['source-env'] || updatedFlags['source-alias']; diff --git a/packages/contentstack-import/src/commands/cm/stacks/import.ts b/packages/contentstack-import/src/commands/cm/stacks/import.ts index 1d56aca9a..b1aadbb72 100644 --- a/packages/contentstack-import/src/commands/cm/stacks/import.ts +++ b/packages/contentstack-import/src/commands/cm/stacks/import.ts @@ -159,6 +159,11 @@ export default class ImportCommand extends Command { backupDir = importConfig.backupDir; //Note: Final summary is now handled by summary manager CLIProgressManager.printGlobalSummary(); + if (importConfig.assetScanningEnabled) { + cliux.print('\nAsset Scanning is enabled — assets were not published.', { color: 'yellow' }); + cliux.print(' Once scanning completes, publish your assets using:', { color: 'yellow' }); + cliux.print(` csdx cm:stacks:bulk-assets --data-dir ${backupDir} --stack-api-key ${importConfig.apiKey}`, { color: 'cyan' }); + } this.logSuccessAndBackupMessages(backupDir, importConfig); // Clear progress module setting now that import is complete clearProgressModuleSetting(); From 4e091242f171e2e15bdca4a7b3c36ff2d644631f Mon Sep 17 00:00:00 2001 From: naman-contentstack Date: Mon, 8 Jun 2026 12:49:33 +0530 Subject: [PATCH 09/18] chore: update talisman --- .talismanrc | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/.talismanrc b/.talismanrc index ca3f83227..736fbb319 100644 --- a/.talismanrc +++ b/.talismanrc @@ -1,26 +1,6 @@ fileignoreconfig: - filename: pnpm-lock.yaml checksum: acb2fc21dd3481f162aedaccecbe45d565b3297957345044a12aa50d2850ac4e -- filename: packages/contentstack-variants/test/unit/import/experiences.test.ts - checksum: 6142418bafea6454a72b313d933deb494ce4ea1d8cead7ef918c10e283c2c603 -- filename: packages/contentstack-variants/test/unit/export/variant-entries.test.ts - checksum: e150faeefa7b3586b70a6f454c1f68efe05526f582977dba28243b1e47606a42 -- filename: packages/contentstack-variants/test/unit/export/experiences.test.ts - checksum: eb9c989dd14373a90e8866ba3350245d3c06e8ba43cfebb24f40c1106b2e6b95 -- filename: packages/contentstack-variants/test/unit/utils/personalization-api-adapter.test.ts - checksum: d729c9586d3a19e321d79e490790b9d0aa345f81917376199d962de68317fae1 -- filename: packages/contentstack-variants/test/unit/import/variant-entries.test.ts - checksum: 1337a680c98cfa7d4be2e48db284c8e44866f5eee1e72afb4ba52c2264c3850f -- filename: packages/contentstack-export/src/export/modules/taxonomies.ts - checksum: b6d077118280bc88385405f504f921468a9fd490ac37a4a21f741be729fd1ca3 -- filename: packages/contentstack-import/test/unit/import/modules/base-class.test.ts - checksum: fe372852d5f2f3f57ef62c603406c30ccecdb444c17133ac0b21dda399b962c0 -- filename: packages/contentstack-export/test/unit/export/modules/taxonomies.test.ts - checksum: cab2ad4d897d23f04f988c1f018a9583ab7f0ee1815994d7bc9fce23dea70073 -- filename: packages/contentstack-query-export/src/core/query-executor.ts - checksum: 708f8a9bc837ed15342fe73920588978a97cab9002c401dbc6ad7030e0238f48 -- filename: packages/contentstack-bulk-operations/test/unit/commands/bulk-am-assets.test.ts - checksum: f8d21db7db0ca2eebe7cc40af0a59f02e74e1689efb6d50a1072dc5ca3e03e9b -- filename: packages/contentstack-asset-management/src/query-export/cs-assets-query-exporter.ts - checksum: f7d03d649ab0b6d45985fcd9bd8ae374ea34ad5c44cb9365af92b3c9ae4728e6 +- filename: packages/contentstack-import/src/commands/cm/stacks/import.ts + checksum: d50d85534c8779b99e46b0fb8a765c0b4e5a30881007346852c254e8e2604c03 version: '1.0' From 8bb7e4331218cf0045a8d58d89debfd5c471da87 Mon Sep 17 00:00:00 2001 From: naman-contentstack Date: Tue, 9 Jun 2026 12:21:01 +0530 Subject: [PATCH 10/18] chore: lint fixes --- .../src/commands/cm/stacks/bulk-assets.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts b/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts index 5c4770578..e8bfc9835 100644 --- a/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts +++ b/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts @@ -5,7 +5,15 @@ import { flags, handleAndLogError, log } from '@contentstack/cli-utilities'; import { AssetPublishData, BulkOperationResult, OperationType, ResourceType } from '../../../interfaces'; import { BaseBulkCommand } from '../../../base-bulk-command'; -import { $t, messages, fetchAssets, scanDataDirStats, BATCH_CONSTANTS, categorizeByScanStatus, fillMissingFlags } from '../../../utils'; +import { + $t, + messages, + fetchAssets, + scanDataDirStats, + BATCH_CONSTANTS, + categorizeByScanStatus, + fillMissingFlags, +} from '../../../utils'; import type { DataDirScanStats } from '../../../utils'; import { AssetService } from '../../../services'; From 194d42fce9203f326262515ad97925c7f3be260d Mon Sep 17 00:00:00 2001 From: naman-contentstack Date: Thu, 25 Jun 2026 17:54:41 +0530 Subject: [PATCH 11/18] fix: minor fixes in asset scanning flow --- .talismanrc | 6 ++-- .../src/commands/cm/stacks/bulk-assets.ts | 17 +--------- .../src/messages/index.ts | 5 --- .../src/utils/interactive.ts | 34 +++++-------------- .../src/commands/cm/stacks/import.ts | 2 +- .../src/import/modules/assets.ts | 2 +- 6 files changed, 16 insertions(+), 50 deletions(-) diff --git a/.talismanrc b/.talismanrc index b03f6eed4..54870602d 100644 --- a/.talismanrc +++ b/.talismanrc @@ -1,4 +1,6 @@ fileignoreconfig: -- filename: pnpm-lock.yaml - checksum: 7ec6345eb15ed0be001753ee49733421a8a07096dc8a18465cdad1b82562fed8 +- filename: packages/contentstack-import/src/commands/cm/stacks/import.ts + checksum: bbf5ebdec2350c3b6d8118a25046e4e11b68c56434ac6c89be6aaab047a6ac4b +- filename: packages/contentstack-import/src/import/modules/assets.ts + checksum: ce46c32788ea908075873b4dee475bae75975eb58771d0da06a3debb6817bf91 version: '1.0' diff --git a/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts b/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts index e8bfc9835..c50b12766 100644 --- a/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts +++ b/packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts @@ -5,15 +5,7 @@ import { flags, handleAndLogError, log } from '@contentstack/cli-utilities'; import { AssetPublishData, BulkOperationResult, OperationType, ResourceType } from '../../../interfaces'; import { BaseBulkCommand } from '../../../base-bulk-command'; -import { - $t, - messages, - fetchAssets, - scanDataDirStats, - BATCH_CONSTANTS, - categorizeByScanStatus, - fillMissingFlags, -} from '../../../utils'; +import { $t, messages, fetchAssets, scanDataDirStats, BATCH_CONSTANTS, categorizeByScanStatus } from '../../../utils'; import type { DataDirScanStats } from '../../../utils'; import { AssetService } from '../../../services'; @@ -67,13 +59,6 @@ export default class BulkAssets extends BaseBulkCommand { protected resourceType: ResourceType = ResourceType.ASSET; - protected async resolveFlagsInteractively(flags: any): Promise { - if (flags['data-dir']) { - return flags; - } - return fillMissingFlags(flags, { promptDataDir: true }); - } - async run(): Promise { try { if (this.bulkOperationConfig.sourceEnv) { diff --git a/packages/contentstack-bulk-operations/src/messages/index.ts b/packages/contentstack-bulk-operations/src/messages/index.ts index c51fe6023..ab7e6f7d9 100644 --- a/packages/contentstack-bulk-operations/src/messages/index.ts +++ b/packages/contentstack-bulk-operations/src/messages/index.ts @@ -379,11 +379,6 @@ const interactiveMsg = { TAXONOMY_UNSUPPORTED_RETRY: 'Retry and revert are not supported for bulk-taxonomies.', TAXONOMY_UNSUPPORTED_CROSS_PUBLISH: 'Cross-publish is not supported for bulk-taxonomies.', - // Data-dir (backup folder) prompt - USE_DATA_DIR_PROMPT: 'Do you want to publish assets using publish details from an import backup folder (data-dir)?', - ENTER_DATA_DIR: 'Enter the path to the import backup folder (data-dir):', - DATA_DIR_REQUIRED: 'Backup folder path is required', - // Errors NO_DELIVERY_TOKENS_FOUND: 'No delivery token aliases found. Add one using: csdx auth:tokens:add -a --delivery-token --api-key --environment --type delivery', diff --git a/packages/contentstack-bulk-operations/src/utils/interactive.ts b/packages/contentstack-bulk-operations/src/utils/interactive.ts index a17485e9a..41e3d319a 100644 --- a/packages/contentstack-bulk-operations/src/utils/interactive.ts +++ b/packages/contentstack-bulk-operations/src/utils/interactive.ts @@ -151,7 +151,7 @@ async function promptForSourceAlias(): Promise { /** * Fills in missing required flags by prompting the user */ -export async function fillMissingFlags(flags: any, options?: { promptDataDir?: boolean }): Promise { +export async function fillMissingFlags(flags: any): Promise { const updatedFlags = { ...flags }; // Skip interactive mode for retry/revert operations @@ -162,17 +162,21 @@ export async function fillMissingFlags(flags: any, options?: { promptDataDir?: b // Track if we prompted for anything let didPrompt = false; + // The presence of --data-dir is what selects the import-backup publish flow: + // environments and locales are then derived per-asset from the backup, so we + // neither prompt for the data-dir path nor for environments/locales here. + const hasDataDir = !!updatedFlags['data-dir']; + // Check if any required fields are missing const needsCredentials = !updatedFlags.alias && !updatedFlags['stack-api-key']; const needsOperation = !updatedFlags.operation; - const needsEnvironments = !updatedFlags.environments || updatedFlags.environments.length === 0; // Check if non-localized filter is used const isNonLocalized = updatedFlags.filter === FilterType.NON_LOCALIZED; - const needsLocales = !isNonLocalized && (!updatedFlags.locales || updatedFlags.locales.length === 0); - const needsDataDir = options?.promptDataDir && !updatedFlags['data-dir']; + const needsEnvironments = !hasDataDir && (!updatedFlags.environments || updatedFlags.environments.length === 0); + const needsLocales = !hasDataDir && !isNonLocalized && (!updatedFlags.locales || updatedFlags.locales.length === 0); // Only show interactive mode header if we need to prompt - if (needsCredentials || needsOperation || needsEnvironments || needsLocales || needsDataDir) { + if (needsCredentials || needsOperation || needsEnvironments || needsLocales) { cliux.print(messages.INTERACTIVE_MODE_START, { color: 'cyan' }); didPrompt = true; } @@ -192,26 +196,6 @@ export async function fillMissingFlags(flags: any, options?: { promptDataDir?: b updatedFlags.operation = await promptForOperation(); } - // 2.5. Data-dir (import backup folder) — alternative to environments/locales for asset publish - if (needsDataDir) { - const useDataDir = await cliux.inquire({ - type: 'confirm', - name: 'useDataDir', - message: messages.USE_DATA_DIR_PROMPT, - default: false, - }); - if (useDataDir) { - updatedFlags['data-dir'] = await cliux.inquire({ - type: 'input', - name: 'dataDir', - message: messages.ENTER_DATA_DIR, - validate: (v: string) => (!v?.trim() ? messages.DATA_DIR_REQUIRED : true), - }); - cliux.print(messages.INTERACTIVE_MODE_COMPLETE, { color: 'green' }); - return updatedFlags; - } - } - // 3. Check for cross-publish mode const isCrossPublish = updatedFlags['source-env'] || updatedFlags['source-alias']; diff --git a/packages/contentstack-import/src/commands/cm/stacks/import.ts b/packages/contentstack-import/src/commands/cm/stacks/import.ts index b1aadbb72..fbd208892 100644 --- a/packages/contentstack-import/src/commands/cm/stacks/import.ts +++ b/packages/contentstack-import/src/commands/cm/stacks/import.ts @@ -162,7 +162,7 @@ export default class ImportCommand extends Command { if (importConfig.assetScanningEnabled) { cliux.print('\nAsset Scanning is enabled — assets were not published.', { color: 'yellow' }); cliux.print(' Once scanning completes, publish your assets using:', { color: 'yellow' }); - cliux.print(` csdx cm:stacks:bulk-assets --data-dir ${backupDir} --stack-api-key ${importConfig.apiKey}`, { color: 'cyan' }); + cliux.print(` csdx cm:stacks:bulk-assets --data-dir ${backupDir} --stack-api-key ${importConfig.apiKey} --operation publish`, { color: 'cyan' }); } this.logSuccessAndBackupMessages(backupDir, importConfig); // Clear progress module setting now that import is complete diff --git a/packages/contentstack-import/src/import/modules/assets.ts b/packages/contentstack-import/src/import/modules/assets.ts index fbce6e743..f6158d5a8 100644 --- a/packages/contentstack-import/src/import/modules/assets.ts +++ b/packages/contentstack-import/src/import/modules/assets.ts @@ -202,7 +202,7 @@ export default class ImportAssets extends BaseClass { log.info(' Asset Scanning is enabled for this stack.', this.importConfig.context); log.info(' Assets cannot be published immediately — scanning must complete first.', this.importConfig.context); log.info(' Once scanning is done, publish your assets using:', this.importConfig.context); - log.info(' csdx cm:stacks:bulk-assets --data-dir ./content --stack-api-key ', this.importConfig.context); + log.info(' csdx cm:stacks:bulk-assets --data-dir ./content --stack-api-key --operation publish', this.importConfig.context); } } catch (error) { this.completeProgress(false, error?.message || 'Asset import failed'); From e047d2aa7395bceb52a30f435c3196d1b70d8a5d Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 1 Jul 2026 11:16:44 +0530 Subject: [PATCH 12/18] 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 13/18] 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); From 3d7772511e6a9e288f6ef429bfa14d165da31d8b Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 1 Jul 2026 19:43:31 +0530 Subject: [PATCH 14/18] added asset scanning plan check --- packages/contentstack-export/package.json | 3 ++- .../src/commands/cm/stacks/export.ts | 3 +-- .../src/types/export-config.ts | 1 + .../src/utils/export-config-handler.ts | 9 ++++++++- packages/contentstack-import/package.json | 6 ++++-- .../src/commands/cm/stacks/import.ts | 6 +++--- .../src/import/module-importer.ts | 6 ------ .../src/import/modules/assets.ts | 11 ++++++++++- .../src/types/import-config.ts | 1 + .../src/utils/import-config-handler.ts | 18 +++++++++++++++++- 10 files changed, 47 insertions(+), 17 deletions(-) diff --git a/packages/contentstack-export/package.json b/packages/contentstack-export/package.json index a733060c3..e6ea7a0a9 100644 --- a/packages/contentstack-export/package.json +++ b/packages/contentstack-export/package.json @@ -96,7 +96,8 @@ "csdxConfig": { "shortCommandName": { "cm:stacks:export": "EXPRT" - } + }, + "planProtectedFeatures": ["assetsScan"] }, "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 afe844ac1..6fd15b4c8 100644 --- a/packages/contentstack-export/src/commands/cm/stacks/export.ts +++ b/packages/contentstack-export/src/commands/cm/stacks/export.ts @@ -22,8 +22,6 @@ 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[] = [ @@ -96,6 +94,7 @@ export default class ExportCommand extends Command { const { flags } = await this.parse(ExportCommand); const exportConfig = await setupExportConfig(flags, this.context); + console.log('Context', this.context); // Prepare the context object const context = this.createExportContext(exportConfig.apiKey, exportConfig.authenticationMethod); exportConfig.context = { ...context }; diff --git a/packages/contentstack-export/src/types/export-config.ts b/packages/contentstack-export/src/types/export-config.ts index 893e2dc8e..acf43724c 100644 --- a/packages/contentstack-export/src/types/export-config.ts +++ b/packages/contentstack-export/src/types/export-config.ts @@ -36,6 +36,7 @@ export default interface ExportConfig extends DefaultConfig { skipDependencies?: boolean; authenticationMethod?: string; linkedWorkspaces?: Array<{ uid: string; space_uid: string; is_default: boolean }>; + planStatus: any; } type branch = { diff --git a/packages/contentstack-export/src/utils/export-config-handler.ts b/packages/contentstack-export/src/utils/export-config-handler.ts index e81611cef..e7bb25838 100644 --- a/packages/contentstack-export/src/utils/export-config-handler.ts +++ b/packages/contentstack-export/src/utils/export-config-handler.ts @@ -168,7 +168,10 @@ const setupConfig = async (exportCmdFlags: any, context: any): Promise = await this.stackAPIClient.fetch(); this.importConfig.stackName = stackDetails.name as string; this.importConfig.org_uid = stackDetails.org_uid as string; - - const assetScanningEnabled = await this.detectAssetScanning(this.importConfig.org_uid); - if (assetScanningEnabled) { - this.importConfig.assetScanningEnabled = true; - this.importConfig.skipAssetsPublish = true; - } } await this.resolveImportPath(); diff --git a/packages/contentstack-import/src/import/modules/assets.ts b/packages/contentstack-import/src/import/modules/assets.ts index fbce6e743..541f6f0eb 100644 --- a/packages/contentstack-import/src/import/modules/assets.ts +++ b/packages/contentstack-import/src/import/modules/assets.ts @@ -39,11 +39,13 @@ export default class ImportAssets extends BaseClass { private assetsUrlMap: Record = {}; private assetsFolderMap: Record = {}; private rootFolder: { uid: string; name: string; parent_uid: string; created_at: string }; + private planStatus: Record = {}; constructor({ importConfig, stackAPIClient }: ModuleClassParams) { super({ importConfig, stackAPIClient }); this.importConfig.context.module = MODULE_CONTEXTS.ASSETS; this.currentModuleName = MODULE_NAMES[MODULE_CONTEXTS.ASSETS]; + this.planStatus = this.importConfig.planStatus; this.assetsPath = join(this.importConfig.backupDir, PATH_CONSTANTS.CONTENT_DIRS.ASSETS); this.mapperDirPath = join(this.importConfig.backupDir, PATH_CONSTANTS.MAPPER, PATH_CONSTANTS.MAPPER_MODULES.ASSETS); @@ -66,6 +68,10 @@ export default class ImportAssets extends BaseClass { try { log.debug('Starting assets import process...', this.importConfig.context); + if (this.planStatus['assetsScan']?.is_part_of_plan) { + log.info('Assets Scanning is enabled in this stack', this.importConfig.context); + log.warn('Assets publishing will be skipped', this.importConfig.context); + } // CS Assets: csAssetsEnabled is set in the config handler when spaces/ + am_v2 are detected. if (this.importConfig.csAssetsEnabled) { if (!this.importConfig.csAssetsUrl) { @@ -200,7 +206,10 @@ export default class ImportAssets extends BaseClass { if (this.importConfig.assetScanningEnabled) { log.info(' Asset Scanning is enabled for this stack.', this.importConfig.context); - log.info(' Assets cannot be published immediately — scanning must complete first.', this.importConfig.context); + log.info( + ' Assets cannot be published immediately — scanning must complete first.', + this.importConfig.context, + ); log.info(' Once scanning is done, publish your assets using:', this.importConfig.context); log.info(' csdx cm:stacks:bulk-assets --data-dir ./content --stack-api-key ', this.importConfig.context); } diff --git a/packages/contentstack-import/src/types/import-config.ts b/packages/contentstack-import/src/types/import-config.ts index 90db2ca08..6f8e06515 100644 --- a/packages/contentstack-import/src/types/import-config.ts +++ b/packages/contentstack-import/src/types/import-config.ts @@ -61,6 +61,7 @@ export default interface ImportConfig extends DefaultConfig, ExternalConfig { context: Context; csAssetsUrl?: string; csAssetsEnabled?: boolean; + planStatus: any; } type branch = { diff --git a/packages/contentstack-import/src/utils/import-config-handler.ts b/packages/contentstack-import/src/utils/import-config-handler.ts index 6bdff3e8a..65f9a08dd 100644 --- a/packages/contentstack-import/src/utils/import-config-handler.ts +++ b/packages/contentstack-import/src/utils/import-config-handler.ts @@ -1,7 +1,15 @@ import merge from 'merge'; import * as path from 'path'; import { omit, filter, includes, isArray } from 'lodash'; -import { configHandler, isAuthenticated, cliux, sanitizePath, log, isFeatureEnabled, FeatureCtx } 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'; @@ -185,6 +193,14 @@ const setupConfig = async (importCmdFlags: any, context?: any): Promise Date: Wed, 8 Jul 2026 15:35:07 +0530 Subject: [PATCH 15/18] fixed snyk --- .talismanrc | 2 + packages/contentstack-apps-cli/package.json | 2 +- pnpm-lock.yaml | 534 ++++++++++++++------ pnpm-workspace.yaml | 1 + 4 files changed, 374 insertions(+), 165 deletions(-) diff --git a/.talismanrc b/.talismanrc index 73151fc22..33631a9a5 100644 --- a/.talismanrc +++ b/.talismanrc @@ -4,4 +4,6 @@ fileignoreconfig: checksum: bbf5ebdec2350c3b6d8118a25046e4e11b68c56434ac6c89be6aaab047a6ac4b - filename: packages/contentstack-import/src/import/modules/assets.ts checksum: 9441f294d8eca1397a988fefec148b20dbe25c1138f6119cf5c573770de43895 +- filename: pnpm-lock.yaml + checksum: cee37c1d5b89d422e6ab3c84678ea3d71e42f8d5ff9cb2c22a29c25d18dddf08 version: '1.0' diff --git a/packages/contentstack-apps-cli/package.json b/packages/contentstack-apps-cli/package.json index d35386080..d6854b533 100644 --- a/packages/contentstack-apps-cli/package.json +++ b/packages/contentstack-apps-cli/package.json @@ -23,7 +23,7 @@ "dependencies": { "@apollo/client": "^3.14.1", "@contentstack/cli-command": "~2.0.0-beta.8", - "@contentstack/cli-launch": "^1.10.0", + "@contentstack/cli-launch": "^1.11.1", "@contentstack/cli-utilities": "~2.0.0-beta.9", "adm-zip": "^0.5.17", "chalk": "^5.6.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1b8ea1339..a9710f21b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,6 +9,7 @@ overrides: follow-redirects: 1.16.0 uuid: 14.0.0 lodash: 4.18.1 + brace-expansion: 5.0.7 importers: @@ -30,8 +31,8 @@ importers: specifier: ~2.0.0-beta.8 version: 2.0.0-beta.8(@types/node@20.19.43) '@contentstack/cli-launch': - specifier: ^1.10.0 - version: 1.11.0(@types/node@20.19.43)(tslib@2.8.1)(typescript@5.9.3) + specifier: ^1.11.1 + version: 1.11.1(@types/node@20.19.43)(tslib@2.8.1)(typescript@5.9.3) '@contentstack/cli-utilities': specifier: ~2.0.0-beta.9 version: 2.0.0-beta.9(@types/node@20.19.43) @@ -56,7 +57,7 @@ importers: devDependencies: '@oclif/test': specifier: ^4.1.18 - version: 4.1.20(@oclif/core@4.11.11) + version: 4.1.20(@oclif/core@4.11.14) '@types/adm-zip': specifier: ^0.5.8 version: 0.5.8 @@ -512,7 +513,7 @@ importers: version: 6.2.52 '@oclif/test': specifier: ^4.1.18 - version: 4.1.20(@oclif/core@4.11.11) + version: 4.1.20(@oclif/core@4.11.14) '@types/chai': specifier: ^4.3.20 version: 4.3.20 @@ -585,7 +586,7 @@ importers: version: 6.2.52 '@oclif/test': specifier: ^4.1.18 - version: 4.1.20(@oclif/core@4.11.11) + version: 4.1.20(@oclif/core@4.11.14) '@types/jest': specifier: ^29.5.14 version: 29.5.14 @@ -808,8 +809,8 @@ importers: specifier: ~2.0.0-beta.8 version: 2.0.0-beta.8(@types/node@22.20.0) '@contentstack/cli-utilities': - specifier: ~2.0.0-beta.9 - version: 2.0.0-beta.9(@types/node@22.20.0) + specifier: ~2.0.0-beta.10 + version: 2.0.0-beta.10(@types/node@22.20.0) '@contentstack/cli-variants': specifier: ~2.0.0-beta.16 version: link:../contentstack-variants @@ -2362,6 +2363,10 @@ packages: resolution: {integrity: sha512-UYnIkO4B3k/qhz4snI6UFVkKcbseyXXreXzKM4T8d/fzMl0Ra6cNGeIMiGgo1RZ2rYlNRfZ2HdfhsPw6e3hlHA==} engines: {node: '>=14.0.0'} + '@contentstack/cli-command@1.8.4': + resolution: {integrity: sha512-xo6d+KrwqGZakUKz6Uw9I3CsW6HC+NqwsMd5kc9IN5j/UhzLZujLAj6fotQY+cyJYG/Dz9D+tSIaL8ZAMRTkLg==} + engines: {node: '>=22.0.0'} + '@contentstack/cli-command@2.0.0-beta.8': resolution: {integrity: sha512-LZMiD3geKqc9zyzdpEktrzrvG1v/YyTVc5n5GF5iE17llnM9Ts5WfGKjhQX49ZavWbJYI0Qk06BF2ncomHQhvg==} engines: {node: '>=14.0.0'} @@ -2376,14 +2381,20 @@ packages: '@contentstack/cli-dev-dependencies@2.0.0-beta.0': resolution: {integrity: sha512-tLP05taIeepvp5Xte2LKDTKeYtDjCxOLlNWzwMFhMFYU1Z7oOgiCu8RVHNz+EkAm5xScKORx1OyEgyNLFoTLBw==} - '@contentstack/cli-launch@1.11.0': - resolution: {integrity: sha512-W/TXIo6odfnPe+qHgoxAts5KahnMRBURGwf4olkoZFYGXoEQ6ZjPXuI2tHUvC0gmWcQOV0z6LDNK+99xJ0aBjg==} + '@contentstack/cli-launch@1.11.1': + resolution: {integrity: sha512-sInkejRj3BQY2P4EsAzkSy9OIWBFS5rFwP7v9sC9mMMo7UGuasF7hZUJHiIDCcwEnRTIRPQ41qX6NBlIr3steA==} engines: {node: '>=22.0.0'} hasBin: true '@contentstack/cli-utilities@1.18.4': resolution: {integrity: sha512-6Q+zge0WP8e5FXRXH1mmsbzAy3xHluUsDdUHO2w8/1w5wyG1rifCi2YcP3GdZJPAoHTq21X9fL9i2KCPZ1GsXg==} + '@contentstack/cli-utilities@1.18.5': + resolution: {integrity: sha512-0qRZznIiU8jqYl7BTs84w9Ke2fVGRDCY22PSUg0DABR1nzrnTVwTTne/gjhuQUoQjMU7GG4rvAScY0SU/0mHAg==} + + '@contentstack/cli-utilities@2.0.0-beta.10': + resolution: {integrity: sha512-u2fhvYR+P5AateT4+AaUHsdEDxeP/eJZUQvfA0xHZhrwOqN/WVkkXDu96j/g7U0hqdMKRHtXzrYpmdfjEeMtMA==} + '@contentstack/cli-utilities@2.0.0-beta.9': resolution: {integrity: sha512-OWL1ZDl4e1/hCt2+CS+zvFSQuEs0WOfe1HpGNTZzUETj8/gULPhb2wdvTS3vOOcpA55d0rbTt4JjYBa83BpzcA==} @@ -2401,9 +2412,16 @@ packages: resolution: {integrity: sha512-jeOnYw3g/14IdIKjmkzNEb21a5K1SJnDUNwFNBeZyU+Z5aGY4FoPOv98b3quWaMMCtoShW4v2lFHcUPpjVP5Mg==} engines: {node: '>=8.0.0'} + '@contentstack/management@1.30.4': + resolution: {integrity: sha512-wFmHxf2WfPVXD8uvFpaxdY882ELqYhdPu1aQM9VM/UYUtJg+7uCj9k785ujYfgbSKgxfY6APgwI++n59v3Entg==} + engines: {node: '>=8.0.0'} + '@contentstack/marketplace-sdk@1.5.3': resolution: {integrity: sha512-Hj/V7M+C8oazmSZ8/h6dNNKNqPczUiv+gzTaZDFDDW9XqzmbzwZxdoNzOBzpi6IuENsojqqjBP5K4WjKddPzfQ==} + '@contentstack/marketplace-sdk@1.5.4': + resolution: {integrity: sha512-rqsL/FvYTqF1a1MK/AZLdWCGf7WY48f4pT/iLkwt6wxh7apxaAwWSWy9ZWRtDu7EIV9FDDTHZ33iYWKH41fnlw==} + '@contentstack/types-generator@3.10.2': resolution: {integrity: sha512-UAzJH8SMX9xVrQOPyiaq/4jBvqy9a5sRbnBlTCEZBnUcMsGI8TyVjvVp+IlD0M5MsMJmPjygrKKOrIgLHSu+VQ==} @@ -2994,6 +3012,12 @@ packages: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -3018,10 +3042,18 @@ packages: resolution: {integrity: sha512-LoGzrvkH9I8dwhxuLafcf90MAp+fYfAiAhpyixaVAWaclIgs+vXeMMQwBG90/wqjdygIKcFAqNnNJrfl3s3X8Q==} engines: {node: '>=18.0.0'} + '@oclif/core@4.11.14': + resolution: {integrity: sha512-cZ5Ktd+rT0PO+o7KBH4vRFTgg+xMLf8F41WK39p8MkXEViZA/Qqe+4lzZT6102zgUxMORET1HtF9t5w8CB3tnQ==} + engines: {node: '>=18.0.0'} + '@oclif/plugin-help@6.2.52': resolution: {integrity: sha512-qtrVz41wHDqG2rvx7xToYHVgJVBRcxE8aPSla/d5wNuHPZsDLm56Nl07pI+DNLA42Xbt9a70POl08qZgBH6FgA==} engines: {node: '>=18.0.0'} + '@oclif/plugin-help@6.2.53': + resolution: {integrity: sha512-njx2nTH87EQEEuz4ShNtL0gzzN981MRkDPqScbu+Tkd7NpIv30OHdTjQK1GzGtkf+V2RvSYIrX+LrLsUVh9DJw==} + engines: {node: '>=18.0.0'} + '@oclif/plugin-not-found@3.2.88': resolution: {integrity: sha512-5YTKSpuV77910/iGnGsj0fr9kOazCy/h1brki1CocbfawdvaVPedcwCH25wMcdRfo8mFD656bG9/kdki/+Wb9A==} engines: {node: '>=18.0.0'} @@ -3058,8 +3090,8 @@ packages: '@otplib/preset-v11@12.0.1': resolution: {integrity: sha512-9hSetMI7ECqbFiKICrNa4w70deTUfArtwXykPUvSHWOdzOlfa9ajglu7mNCntlvxycTiOAXkQGwjQCzzDEMRMg==} - '@oxc-project/types@0.137.0': - resolution: {integrity: sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==} + '@oxc-project/types@0.138.0': + resolution: {integrity: sha512-1a7ZKmrRTCoN1XMZ4L0PyyqrMnrNlLyPuOkdSX2MZg7IiIGRUyurNhAm73ptDOraoBcIordsIGKNPKUzy3ZmfA==} '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} @@ -3089,91 +3121,91 @@ packages: resolution: {integrity: sha512-pmNVGuooS30Mm7YbZd5T7E5zYVO6D5Ct91sn4T39mUvMUc3sCGridcnhAufL1/Bz2QzAtzEn0agNrdk3+5yWzw==} hasBin: true - '@rolldown/binding-android-arm64@1.1.2': - resolution: {integrity: sha512-2cZ+7xRS+DBcuJBJKnfzsbleumJhBqSlJVpuzHC0nTqfd3QQ7Vx2/x5YR/D7cBamKSeWplwo82Fn9lqYUDEMfA==} + '@rolldown/binding-android-arm64@1.1.4': + resolution: {integrity: sha512-EZLpf/8y7GXkkra90ML47kzik/GMP3EMcE9bPyHmRfxLC6z9+aW5A8poCsoxjrT5GfEcNAAvWwUHjvP1pUQkfw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.1.2': - resolution: {integrity: sha512-RkPMJnygxsgOYdkfqgpwY0/Fzm8d0VQe6HGU2/B00Xa9eqdLbrII+DOKAodbJAn3ZL1AJxGHkZRPYazgGY6Ljw==} + '@rolldown/binding-darwin-arm64@1.1.4': + resolution: {integrity: sha512-aUi+HBvmYb7j8krl1+qJgkG8C17fO79gk3c+jPw4S8glRFc1DTija9S3EyaTSQUm5GJXYKDAsugBEhFHH2vYiQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.1.2': - resolution: {integrity: sha512-Uiczh6vFhwyfd7WNe7Q7mCA4KxAiLdz7jPE/WGizfRpIieoyFuNVMmM8HqZ9HwudTkY6/AeMQwlNJ9NJijguWw==} + '@rolldown/binding-darwin-x64@1.1.4': + resolution: {integrity: sha512-F7hHC3gwY11+vByKPRWqwGbeXWVgKmL+pTGCinaEhdihzBV2aQ0fvZOch9cXYUOKuKKq429HeYXOqQLc7wFCEg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.1.2': - resolution: {integrity: sha512-+TpdtTRgHiJFjCVFbw311SuLk3KfytPOQQn+VlAEv+gBxYPtL7E6JS9e/tk+8CwxhIZvemJKo4rTKgfWNsKkkA==} + '@rolldown/binding-freebsd-x64@1.1.4': + resolution: {integrity: sha512-sI5yw+7s92SK6odiEhD5lKCBlWcpjHS5qyqpVQbZAJ0fIzEUXrmbl3DH2ybR3PZogulNJF+COLtmA8hUfvkCCQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.1.2': - resolution: {integrity: sha512-4lv1/tkmi7ueIVHnyreaOeUpiZP26BH9rRy6hoYfR9310A2B9nUEVRDvBx69vx64Nr3eTPPRkyciqJJs+j9Jmw==} + '@rolldown/binding-linux-arm-gnueabihf@1.1.4': + resolution: {integrity: sha512-mCi0OKgEieFircrtVYmQAFGszRtMnZ6fpZAXrxanXAu7lqZcsK1E1RAaZNG0uKAnxox3B1f4EyQNnoyMfN1vAA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.1.2': - resolution: {integrity: sha512-gBSUVO0eaWgw1JMjK3gB8BMlX2Mk148s2lTiVT3e9vjVxbl7UDfMWWY8CfIaaqiXuM9fVTMxIpUz6CAo/B6Vlw==} + '@rolldown/binding-linux-arm64-gnu@1.1.4': + resolution: {integrity: sha512-B9Ial3Kv5sh0SHnB1g/QWcUQCEvCF6QKGAl4zXypYj65mVI+B4AhFBwPtSN7pDrJeIx8Z7zdy4ntx+wQABom7w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@rolldown/binding-linux-arm64-musl@1.1.2': - resolution: {integrity: sha512-LjQP/iZLBu8o8PjIfk4x3At0/mT6h282pvz8Z5LAyhGbu/kDezyO7ea62rF5uoqmgnIYqbN/MqJ3Si3Aymi7xQ==} + '@rolldown/binding-linux-arm64-musl@1.1.4': + resolution: {integrity: sha512-lZVym0PuHE1KZ22gmFTC15lAkrg9iTszR617oYRB/iPY1A56ywoJzVKOJBKaot5RiikCObmur6pogpse3gRcng==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@rolldown/binding-linux-ppc64-gnu@1.1.2': - resolution: {integrity: sha512-X/7bVLWelEsbyWDUSXt7zVsTniLLPIY2n1rH58qr78l9i7MNbbxBWD8gI2vRfBWf4NUXJCUuQnfZDsp32LqsfQ==} + '@rolldown/binding-linux-ppc64-gnu@1.1.4': + resolution: {integrity: sha512-t2DNiLJWNTbnEHyUzTumldML6ET4/g16467LZoDDJ3tSxGvguL5/NyC2lCsNKuyRycg9XeDQF5SSv+TNOhQEXg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - '@rolldown/binding-linux-s390x-gnu@1.1.2': - resolution: {integrity: sha512-gb6dYKW/1KDorGXyy48glEBJs/sxVSC5pcVrox/pFGV4mvwSFeg2sK5L2tRkVsVlh7kueqOgg4GEcuipJcGuKg==} + '@rolldown/binding-linux-s390x-gnu@1.1.4': + resolution: {integrity: sha512-0WIRnL1Uw4BvTZRLQt+PVgo6ZKTJadlC2btP+/EOXv2f/DWbY0rEgl+y834mIVwP1FkTlWVTrGGJXf12lru7EQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - '@rolldown/binding-linux-x64-gnu@1.1.2': - resolution: {integrity: sha512-JY4w85pU3iAiJVMh5nuk4/Mh9GjMsupe8MrIN53rwxAZW64GKrWeJBuN6SxQg9QTU5uB1cxyhDzW8jqRn1EABw==} + '@rolldown/binding-linux-x64-gnu@1.1.4': + resolution: {integrity: sha512-JWtGshGfX+oENAKonoNkqEJX+7hC8yfhi9GUyPX1VX4mdh1y5r+ZiJLR5XzAB0aoP6s/PcILsGjKq8O0mm24bw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@rolldown/binding-linux-x64-musl@1.1.2': - resolution: {integrity: sha512-xvpA7o5KCYLB0Rwscmuylb1/zHHSUx4g4xilm4prC5jP76pEUlzBmMbgpbh7bVDbId4NcfT96gN5i6mE6UDaiw==} + '@rolldown/binding-linux-x64-musl@1.1.4': + resolution: {integrity: sha512-rT6yQcxUuXs4CnbofqwHRRV0iem349rLMYpTjkgQGLjrY4ado/eDzwPZPTCgTOlF6Nkp8NEv70yLMTn6qkWxsQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@rolldown/binding-openharmony-arm64@1.1.2': - resolution: {integrity: sha512-p/ts6KBLjuk49Bp21XH77poQGt02iNz7ChgHep7tudPOaLinR/De/RHdxF8w8Yj4r/bF/bqXwH6PZrB2sA+Nvw==} + '@rolldown/binding-openharmony-arm64@1.1.4': + resolution: {integrity: sha512-KXMGoboq5cyaCQjDA4GLuRiOwBQ0EyFnJoVViLeZ45/3rFItRODEr+NdsBcVpll40hhNArlm/speWGRvj08LzA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.1.2': - resolution: {integrity: sha512-VMu/wmrZ9hJzYlRhbw7jK5PODlugyKZ5mOdX78+lS8OvuFkWNQdz1pFLrI2p3P0pjXOmUZ7B48o5VnMH9QOGtg==} + '@rolldown/binding-wasm32-wasi@1.1.4': + resolution: {integrity: sha512-5K83rb36oJiY7BCyE9zLZtGcPV4g5wvq+xwdO0XPIwDVZI8cyB/AUjkNXGb92/rnmezEkjMOpgY61rtwjQtFwg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.1.2': - resolution: {integrity: sha512-xtUJqs8qEkuSviS0n1tsohaPuz3a1SPhZywOji4Oo+sgrJs8daEDMZ0QtqL0OS7dx8PoVpg2J/ZZycPY5I2+Zg==} + '@rolldown/binding-win32-arm64-msvc@1.1.4': + resolution: {integrity: sha512-PnWBtw3TV5KOg69HQQDR0mnQuyCmSGR2pAB4DC1rPF808fgKeTUMj2EOEyKATpgiuxuR5APQmiDO7PDgEjTFSA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.1.2': - resolution: {integrity: sha512-85YiLQqjUKgSO/Zjnf9e0XIn5Ymrh1fLDWBeAkZqpuBR/3R8TpfoHXuyblqyQrftSSgWO9qpcHN8mkyKsLraoA==} + '@rolldown/binding-win32-x64-msvc@1.1.4': + resolution: {integrity: sha512-M1lpniBePobTfsa7Ks9a199e1akxsXn+GYBUKsEzv3YFzOm1HJAMNwKI3qr0Zq+mxwx9gOZoTdP1yXRYsZUocQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -3534,8 +3566,8 @@ packages: '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} - '@types/express-serve-static-core@4.19.8': - resolution: {integrity: sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==} + '@types/express-serve-static-core@4.19.9': + resolution: {integrity: sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==} '@types/express@4.17.25': resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} @@ -4104,6 +4136,10 @@ packages: resolution: {integrity: sha512-+Ut8d9LLqwEvHHJl1+PIHqoyDxFgVN847JTVM3Izi3xHDWPE4UtzzXysMZQs64DMcrJfBeS/uoEP4AD3HQHnQQ==} engines: {node: '>=12.0'} + adm-zip@0.5.18: + resolution: {integrity: sha512-ufJnssQGbxzLNS1Ho9bCtX4rQKCCvoVuDLHoJyc3F9dOGDB4BkWs2Ci0kv53lqocAEQ/Cbi+I2XCsNYGqVYqng==} + engines: {node: '>=12.0'} + agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -4410,9 +4446,6 @@ packages: peerDependencies: '@babel/core': ^7.11.0 || ^8.0.0-beta.1 - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - balanced-match@4.0.4: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} @@ -4451,14 +4484,8 @@ packages: bowser@2.14.1: resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} - brace-expansion@1.1.15: - resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==} - - brace-expansion@2.1.1: - resolution: {integrity: sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==} - - brace-expansion@5.0.6: - resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} + brace-expansion@5.0.7: + resolution: {integrity: sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==} engines: {node: 18 || 20 || >=22} braces@3.0.3: @@ -4787,9 +4814,6 @@ packages: compare-func@2.0.0: resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - concat-stream@2.0.0: resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} engines: {'0': node >= 6.0} @@ -5792,10 +5816,6 @@ packages: resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} engines: {node: '>= 14.17'} - form-data@4.0.4: - resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} - engines: {node: '>= 6'} - form-data@4.0.6: resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} engines: {node: '>= 6'} @@ -6765,6 +6785,10 @@ packages: resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==} hasBin: true + js-yaml@4.3.0: + resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} + hasBin: true + js2xmlparser@4.0.2: resolution: {integrity: sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==} @@ -7704,6 +7728,10 @@ packages: resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + pirates@4.0.7: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} @@ -7729,8 +7757,8 @@ packages: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} - postcss@8.5.15: - resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} + postcss@8.5.16: + resolution: {integrity: sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -7821,6 +7849,10 @@ packages: resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==} engines: {node: '>=0.6'} + qs@6.15.3: + resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==} + engines: {node: '>=0.6'} + querystring@0.2.1: resolution: {integrity: sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==} engines: {node: '>=0.4.x'} @@ -8119,8 +8151,8 @@ packages: engines: {node: 20 || >=22} hasBin: true - rolldown@1.1.2: - resolution: {integrity: sha512-x0CrQQqCXWGeI8dTvFfN/Dnv3yMKT9hv5jFjlOreKAx9wqLq9wz7VvLLHyaAXC90/CpggTu9SisSbsJJTPSjNQ==} + rolldown@1.1.4: + resolution: {integrity: sha512-IjZYiLxZwpnhwhdBH2ugdTGVSdhCQUmLxLoqyjiL0JxYjyRst+5a0P3xfrTxJ5F638j4Mvvw5FAX5XE6eHpXbA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -10366,7 +10398,7 @@ snapshots: '@contentstack/cli-auth@2.0.0-beta.13(@types/node@22.20.0)': dependencies: '@contentstack/cli-command': 2.0.0-beta.8(@types/node@22.20.0) - '@contentstack/cli-utilities': 2.0.0-beta.9(@types/node@22.20.0) + '@contentstack/cli-utilities': 2.0.0-beta.10(@types/node@22.20.0) '@oclif/core': 4.11.11 otplib: 12.0.1 transitivePeerDependencies: @@ -10384,6 +10416,16 @@ snapshots: - debug - supports-color + '@contentstack/cli-command@1.8.4(@types/node@20.19.43)': + dependencies: + '@contentstack/cli-utilities': 1.18.5(@types/node@20.19.43) + '@oclif/core': 4.11.14 + contentstack: 3.27.0 + transitivePeerDependencies: + - '@types/node' + - debug + - supports-color + '@contentstack/cli-command@2.0.0-beta.8(@types/node@14.18.63)': dependencies: '@contentstack/cli-utilities': 2.0.0-beta.9(@types/node@14.18.63) @@ -10437,7 +10479,7 @@ snapshots: '@contentstack/cli-config@2.0.0-beta.11(@types/node@18.19.130)': dependencies: '@contentstack/cli-command': 2.0.0-beta.8(@types/node@18.19.130) - '@contentstack/cli-utilities': 2.0.0-beta.9(@types/node@18.19.130) + '@contentstack/cli-utilities': 2.0.0-beta.10(@types/node@18.19.130) '@contentstack/utils': 1.9.1 '@oclif/core': 4.11.11 transitivePeerDependencies: @@ -10448,7 +10490,7 @@ snapshots: '@contentstack/cli-config@2.0.0-beta.11(@types/node@22.20.0)': dependencies: '@contentstack/cli-command': 2.0.0-beta.8(@types/node@22.20.0) - '@contentstack/cli-utilities': 2.0.0-beta.9(@types/node@22.20.0) + '@contentstack/cli-utilities': 2.0.0-beta.10(@types/node@22.20.0) '@contentstack/utils': 1.9.1 '@oclif/core': 4.11.11 transitivePeerDependencies: @@ -10474,25 +10516,25 @@ snapshots: transitivePeerDependencies: - supports-color - '@contentstack/cli-launch@1.11.0(@types/node@20.19.43)(tslib@2.8.1)(typescript@5.9.3)': + '@contentstack/cli-launch@1.11.1(@types/node@20.19.43)(tslib@2.8.1)(typescript@5.9.3)': dependencies: '@apollo/client': 3.14.1(graphql@16.14.2) - '@contentstack/cli-command': 1.8.3(@types/node@20.19.43) - '@contentstack/cli-utilities': 1.18.4(@types/node@20.19.43) - '@oclif/core': 4.11.11 - '@oclif/plugin-help': 6.2.52 + '@contentstack/cli-command': 1.8.4(@types/node@20.19.43) + '@contentstack/cli-utilities': 1.18.5(@types/node@20.19.43) + '@oclif/core': 4.11.14 + '@oclif/plugin-help': 6.2.53 '@rollup/plugin-commonjs': 28.0.9(rollup@4.62.2) '@rollup/plugin-json': 6.1.0(rollup@4.62.2) '@rollup/plugin-node-resolve': 16.0.3(rollup@4.62.2) '@rollup/plugin-typescript': 12.3.0(rollup@4.62.2)(tslib@2.8.1)(typescript@5.9.3) '@types/express': 4.17.25 - '@types/express-serve-static-core': 4.19.8 - adm-zip: 0.5.17 + '@types/express-serve-static-core': 4.19.9 + adm-zip: 0.5.18 chalk: 4.1.2 cross-fetch: 4.1.0 dotenv: 16.6.1 express: 4.22.2 - form-data: 4.0.4 + form-data: 4.0.6 graphql: 16.14.2 ini: 3.0.1 lodash: 4.18.1 @@ -10549,6 +10591,117 @@ snapshots: - debug - supports-color + '@contentstack/cli-utilities@1.18.5(@types/node@20.19.43)': + dependencies: + '@contentstack/management': 1.30.4 + '@contentstack/marketplace-sdk': 1.5.4 + '@oclif/core': 4.11.14 + axios: 1.18.1(debug@4.4.3) + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-progress: 3.12.0 + cli-table: 0.3.11 + conf: 10.2.0 + dotenv: 16.6.1 + figures: 3.2.0 + inquirer: 8.2.7(@types/node@20.19.43) + inquirer-search-checkbox: 1.0.0 + inquirer-search-list: 1.2.6 + js-yaml: 4.3.0 + klona: 2.0.6 + lodash: 4.18.1 + mkdirp: 1.0.4 + open: 8.4.2 + ora: 5.4.1 + papaparse: 5.5.4 + recheck: 4.4.5 + rxjs: 6.6.7 + short-uuid: 6.0.3 + traverse: 0.6.11 + tty-table: 4.2.3 + unique-string: 2.0.0 + uuid: 14.0.0 + winston: 3.19.0 + xdg-basedir: 4.0.0 + transitivePeerDependencies: + - '@types/node' + - debug + - supports-color + + '@contentstack/cli-utilities@2.0.0-beta.10(@types/node@18.19.130)': + dependencies: + '@contentstack/management': 1.30.4 + '@contentstack/marketplace-sdk': 1.5.4 + '@oclif/core': 4.11.11 + axios: 1.18.1(debug@4.4.3) + chalk: 5.6.2 + cli-cursor: 3.1.0 + cli-progress: 3.12.0 + cli-table: 0.3.11 + conf: 10.2.0 + dotenv: 16.6.1 + figures: 3.2.0 + inquirer: 12.11.1(@types/node@18.19.130) + inquirer-search-checkbox: 1.0.0 + inquirer-search-list: 1.2.6 + js-yaml: 4.3.0 + klona: 2.0.6 + lodash: 4.18.1 + mkdirp: 1.0.4 + open: 8.4.2 + ora: 5.4.1 + papaparse: 5.5.4 + recheck: 4.5.0 + rxjs: 6.6.7 + short-uuid: 6.0.3 + traverse: 0.6.11 + tty-table: 4.2.3 + unique-string: 2.0.0 + uuid: 14.0.0 + winston: 3.19.0 + xdg-basedir: 4.0.0 + transitivePeerDependencies: + - '@types/node' + - debug + - supports-color + + '@contentstack/cli-utilities@2.0.0-beta.10(@types/node@22.20.0)': + dependencies: + '@contentstack/management': 1.30.4 + '@contentstack/marketplace-sdk': 1.5.4 + '@oclif/core': 4.11.11 + axios: 1.18.1(debug@4.4.3) + chalk: 5.6.2 + cli-cursor: 3.1.0 + cli-progress: 3.12.0 + cli-table: 0.3.11 + conf: 10.2.0 + dotenv: 16.6.1 + figures: 3.2.0 + inquirer: 12.11.1(@types/node@22.20.0) + inquirer-search-checkbox: 1.0.0 + inquirer-search-list: 1.2.6 + js-yaml: 4.3.0 + klona: 2.0.6 + lodash: 4.18.1 + mkdirp: 1.0.4 + open: 8.4.2 + ora: 5.4.1 + papaparse: 5.5.4 + recheck: 4.5.0 + rxjs: 6.6.7 + short-uuid: 6.0.3 + traverse: 0.6.11 + tty-table: 4.2.3 + unique-string: 2.0.0 + uuid: 14.0.0 + winston: 3.19.0 + xdg-basedir: 4.0.0 + transitivePeerDependencies: + - '@types/node' + - debug + - supports-color + '@contentstack/cli-utilities@2.0.0-beta.9(@types/node@14.18.63)': dependencies: '@contentstack/management': 1.30.3(debug@4.4.3) @@ -10786,6 +10939,22 @@ snapshots: - debug - supports-color + '@contentstack/management@1.30.4': + dependencies: + '@contentstack/utils': 1.9.1 + assert: 2.1.0 + axios: 1.18.1(debug@4.4.3) + buffer: 6.0.3 + form-data: 4.0.6 + husky: 9.1.7 + lodash: 4.18.1 + otplib: 12.0.1 + qs: 6.15.3 + stream-browserify: 3.0.0 + transitivePeerDependencies: + - debug + - supports-color + '@contentstack/marketplace-sdk@1.5.3(debug@4.4.3)': dependencies: '@contentstack/utils': 1.9.1 @@ -10794,6 +10963,14 @@ snapshots: - debug - supports-color + '@contentstack/marketplace-sdk@1.5.4': + dependencies: + '@contentstack/utils': 1.9.1 + axios: 1.18.1(debug@4.4.3) + transitivePeerDependencies: + - debug + - supports-color + '@contentstack/types-generator@3.10.2(graphql@16.14.2)': dependencies: '@contentstack/delivery-sdk': 5.2.1 @@ -11785,14 +11962,14 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.19.43 + '@types/node': 22.20.0 jest-mock: 29.7.0 '@jest/environment@30.4.1': dependencies: '@jest/fake-timers': 30.4.1 '@jest/types': 30.4.1 - '@types/node': 20.19.43 + '@types/node': 18.19.130 jest-mock: 30.4.1 '@jest/expect-utils@29.7.0': @@ -11821,7 +11998,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.19.43 + '@types/node': 22.20.0 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -11830,7 +12007,7 @@ snapshots: dependencies: '@jest/types': 30.4.1 '@sinonjs/fake-timers': 15.4.0 - '@types/node': 20.19.43 + '@types/node': 18.19.130 jest-message-util: 30.4.1 jest-mock: 30.4.1 jest-util: 30.4.1 @@ -12073,7 +12250,7 @@ snapshots: '@tybys/wasm-util': 0.10.3 optional: true - '@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': dependencies: '@emnapi/core': 1.11.1 '@emnapi/runtime': 1.11.1 @@ -12146,10 +12323,35 @@ snapshots: wordwrap: 1.0.0 wrap-ansi: 7.0.0 + '@oclif/core@4.11.14': + dependencies: + ansi-escapes: 4.3.2 + ansis: 3.17.0 + clean-stack: 3.0.1 + cli-spinners: 2.9.2 + debug: 4.4.3(supports-color@8.1.1) + ejs: 3.1.10 + get-package-type: 0.1.0 + indent-string: 4.0.0 + is-wsl: 2.2.0 + lilconfig: 3.1.3 + minimatch: 10.2.5 + semver: 7.8.5 + string-width: 4.2.3 + supports-color: 8.1.1 + tinyglobby: 0.2.17 + widest-line: 3.1.0 + wordwrap: 1.0.0 + wrap-ansi: 7.0.0 + '@oclif/plugin-help@6.2.52': dependencies: '@oclif/core': 4.11.11 + '@oclif/plugin-help@6.2.53': + dependencies: + '@oclif/core': 4.11.14 + '@oclif/plugin-not-found@3.2.88(@types/node@14.18.63)': dependencies: '@inquirer/prompts': 7.10.1(@types/node@14.18.63) @@ -12213,6 +12415,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@oclif/test@4.1.20(@oclif/core@4.11.14)': + dependencies: + '@oclif/core': 4.11.14 + ansis: 3.17.0 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + '@otplib/core@12.0.1': {} '@otplib/plugin-crypto@12.0.1': @@ -12236,7 +12446,7 @@ snapshots: '@otplib/plugin-crypto': 12.0.1 '@otplib/plugin-thirty-two': 12.0.1 - '@oxc-project/types@0.137.0': {} + '@oxc-project/types@0.138.0': {} '@pkgjs/parseargs@0.11.0': optional: true @@ -12261,53 +12471,53 @@ snapshots: dependencies: nopt: 1.0.10 - '@rolldown/binding-android-arm64@1.1.2': + '@rolldown/binding-android-arm64@1.1.4': optional: true - '@rolldown/binding-darwin-arm64@1.1.2': + '@rolldown/binding-darwin-arm64@1.1.4': optional: true - '@rolldown/binding-darwin-x64@1.1.2': + '@rolldown/binding-darwin-x64@1.1.4': optional: true - '@rolldown/binding-freebsd-x64@1.1.2': + '@rolldown/binding-freebsd-x64@1.1.4': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.1.2': + '@rolldown/binding-linux-arm-gnueabihf@1.1.4': optional: true - '@rolldown/binding-linux-arm64-gnu@1.1.2': + '@rolldown/binding-linux-arm64-gnu@1.1.4': optional: true - '@rolldown/binding-linux-arm64-musl@1.1.2': + '@rolldown/binding-linux-arm64-musl@1.1.4': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.1.2': + '@rolldown/binding-linux-ppc64-gnu@1.1.4': optional: true - '@rolldown/binding-linux-s390x-gnu@1.1.2': + '@rolldown/binding-linux-s390x-gnu@1.1.4': optional: true - '@rolldown/binding-linux-x64-gnu@1.1.2': + '@rolldown/binding-linux-x64-gnu@1.1.4': optional: true - '@rolldown/binding-linux-x64-musl@1.1.2': + '@rolldown/binding-linux-x64-musl@1.1.4': optional: true - '@rolldown/binding-openharmony-arm64@1.1.2': + '@rolldown/binding-openharmony-arm64@1.1.4': optional: true - '@rolldown/binding-wasm32-wasi@1.1.2': + '@rolldown/binding-wasm32-wasi@1.1.4': dependencies: '@emnapi/core': 1.11.1 '@emnapi/runtime': 1.11.1 - '@napi-rs/wasm-runtime': 1.1.5(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) optional: true - '@rolldown/binding-win32-arm64-msvc@1.1.2': + '@rolldown/binding-win32-arm64-msvc@1.1.4': optional: true - '@rolldown/binding-win32-x64-msvc@1.1.2': + '@rolldown/binding-win32-x64-msvc@1.1.4': optional: true '@rolldown/pluginutils@1.0.1': {} @@ -12317,10 +12527,10 @@ snapshots: '@rollup/pluginutils': 5.4.0(rollup@4.62.2) commondir: 1.0.1 estree-walker: 2.0.2 - fdir: 6.5.0(picomatch@4.0.4) + fdir: 6.5.0(picomatch@4.0.5) is-reference: 1.2.1 magic-string: 0.30.21 - picomatch: 4.0.4 + picomatch: 4.0.5 optionalDependencies: rollup: 4.62.2 @@ -12353,7 +12563,7 @@ snapshots: dependencies: '@types/estree': 1.0.9 estree-walker: 2.0.2 - picomatch: 4.0.4 + picomatch: 4.0.5 optionalDependencies: rollup: 4.62.2 @@ -12617,7 +12827,7 @@ snapshots: eslint-visitor-keys: 4.2.1 espree: 10.4.0 estraverse: 5.3.0 - picomatch: 4.0.4 + picomatch: 4.0.5 '@stylistic/eslint-plugin@5.10.0(eslint@8.57.1)': dependencies: @@ -12627,7 +12837,7 @@ snapshots: eslint-visitor-keys: 4.2.1 espree: 10.4.0 estraverse: 5.3.0 - picomatch: 4.0.4 + picomatch: 4.0.5 '@stylistic/eslint-plugin@5.10.0(eslint@9.39.4)': dependencies: @@ -12637,7 +12847,7 @@ snapshots: eslint-visitor-keys: 4.2.1 espree: 10.4.0 estraverse: 5.3.0 - picomatch: 4.0.4 + picomatch: 4.0.5 '@szmarczak/http-timer@5.0.1': dependencies: @@ -12717,7 +12927,7 @@ snapshots: '@types/estree@1.0.9': {} - '@types/express-serve-static-core@4.19.8': + '@types/express-serve-static-core@4.19.9': dependencies: '@types/node': 20.19.43 '@types/qs': 6.15.1 @@ -12727,7 +12937,7 @@ snapshots: '@types/express@4.17.25': dependencies: '@types/body-parser': 1.19.6 - '@types/express-serve-static-core': 4.19.8 + '@types/express-serve-static-core': 4.19.9 '@types/qs': 6.15.1 '@types/serve-static': 1.15.10 @@ -12740,7 +12950,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.19.43 + '@types/node': 22.20.0 '@types/hogan.js@3.0.5': {} @@ -13907,6 +14117,8 @@ snapshots: adm-zip@0.5.17: {} + adm-zip@0.5.18: {} + agent-base@6.0.2: dependencies: debug: 4.4.3(supports-color@8.1.1) @@ -14257,8 +14469,6 @@ snapshots: babel-plugin-jest-hoist: 30.4.0 babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7) - balanced-match@1.0.2: {} - balanced-match@4.0.4: {} base64-js@1.5.1: {} @@ -14300,7 +14510,7 @@ snapshots: http-errors: 2.0.1 iconv-lite: 0.4.24 on-finished: 2.4.1 - qs: 6.15.2 + qs: 6.15.3 raw-body: 2.5.3 type-is: 1.6.18 unpipe: 1.0.0 @@ -14309,16 +14519,7 @@ snapshots: bowser@2.14.1: {} - brace-expansion@1.1.15: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.1.1: - dependencies: - balanced-match: 1.0.2 - - brace-expansion@5.0.6: + brace-expansion@5.0.7: dependencies: balanced-match: 4.0.4 @@ -14688,8 +14889,6 @@ snapshots: array-ify: 1.0.0 dot-prop: 5.3.0 - concat-map@0.0.1: {} - concat-stream@2.0.0: dependencies: buffer-from: 1.1.2 @@ -16579,7 +16778,7 @@ snapshots: parseurl: 1.3.3 path-to-regexp: 0.1.13 proxy-addr: 2.0.7 - qs: 6.15.2 + qs: 6.15.3 range-parser: 1.2.1 safe-buffer: 5.2.1 send: 0.19.2 @@ -16668,6 +16867,10 @@ snapshots: optionalDependencies: picomatch: 4.0.4 + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 + fecha@4.2.3: {} figures@1.7.0: @@ -16785,14 +16988,6 @@ snapshots: form-data-encoder@2.1.4: {} - form-data@4.0.4: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - es-set-tostringtag: 2.1.0 - hasown: 2.0.4 - mime-types: 2.1.35 - form-data@4.0.6: dependencies: asynckit: 0.4.0 @@ -17617,7 +17812,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.19.43 + '@types/node': 22.20.0 chalk: 4.1.2 co: 4.6.0 dedent: 1.7.2 @@ -17643,7 +17838,7 @@ snapshots: '@jest/expect': 30.4.1 '@jest/test-result': 30.4.1 '@jest/types': 30.4.1 - '@types/node': 20.19.43 + '@types/node': 18.19.130 chalk: 4.1.2 co: 4.6.0 dedent: 1.7.2 @@ -17958,7 +18153,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.19.43 + '@types/node': 22.20.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -17967,7 +18162,7 @@ snapshots: '@jest/environment': 30.4.1 '@jest/fake-timers': 30.4.1 '@jest/types': 30.4.1 - '@types/node': 20.19.43 + '@types/node': 18.19.130 jest-mock: 30.4.1 jest-util: 30.4.1 jest-validate: 30.4.1 @@ -18059,7 +18254,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.19.43 + '@types/node': 22.20.0 jest-util: 29.7.0 jest-mock@30.4.1: @@ -18335,14 +18530,14 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 20.19.43 + '@types/node': 22.20.0 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@30.4.1: dependencies: - '@types/node': 20.19.43 + '@types/node': 18.19.130 '@ungap/structured-clone': 1.3.2 jest-util: 30.4.1 merge-stream: 2.0.0 @@ -18396,6 +18591,10 @@ snapshots: dependencies: argparse: 2.0.1 + js-yaml@4.3.0: + dependencies: + argparse: 2.0.1 + js2xmlparser@4.0.2: dependencies: xmlcreate: 2.0.4 @@ -18863,23 +19062,23 @@ snapshots: minimatch@10.2.5: dependencies: - brace-expansion: 5.0.6 + brace-expansion: 5.0.7 minimatch@3.1.5: dependencies: - brace-expansion: 1.1.15 + brace-expansion: 5.0.7 minimatch@5.1.9: dependencies: - brace-expansion: 2.1.1 + brace-expansion: 5.0.7 minimatch@9.0.3: dependencies: - brace-expansion: 2.1.1 + brace-expansion: 5.0.7 minimatch@9.0.9: dependencies: - brace-expansion: 2.1.1 + brace-expansion: 5.0.7 minimist@1.2.8: {} @@ -19499,6 +19698,8 @@ snapshots: picomatch@4.0.4: {} + picomatch@4.0.5: {} + pirates@4.0.7: {} pkg-dir@4.2.0: @@ -19515,7 +19716,7 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss@8.5.15: + postcss@8.5.16: dependencies: nanoid: 3.3.15 picocolors: 1.1.1 @@ -19613,6 +19814,11 @@ snapshots: dependencies: side-channel: 1.1.1 + qs@6.15.3: + dependencies: + es-define-property: 1.0.1 + side-channel: 1.1.1 + querystring@0.2.1: {} querystringify@2.2.0: {} @@ -19904,26 +20110,26 @@ snapshots: glob: 13.0.6 package-json-from-dist: 1.0.1 - rolldown@1.1.2: + rolldown@1.1.4: dependencies: - '@oxc-project/types': 0.137.0 + '@oxc-project/types': 0.138.0 '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rolldown/binding-android-arm64': 1.1.2 - '@rolldown/binding-darwin-arm64': 1.1.2 - '@rolldown/binding-darwin-x64': 1.1.2 - '@rolldown/binding-freebsd-x64': 1.1.2 - '@rolldown/binding-linux-arm-gnueabihf': 1.1.2 - '@rolldown/binding-linux-arm64-gnu': 1.1.2 - '@rolldown/binding-linux-arm64-musl': 1.1.2 - '@rolldown/binding-linux-ppc64-gnu': 1.1.2 - '@rolldown/binding-linux-s390x-gnu': 1.1.2 - '@rolldown/binding-linux-x64-gnu': 1.1.2 - '@rolldown/binding-linux-x64-musl': 1.1.2 - '@rolldown/binding-openharmony-arm64': 1.1.2 - '@rolldown/binding-wasm32-wasi': 1.1.2 - '@rolldown/binding-win32-arm64-msvc': 1.1.2 - '@rolldown/binding-win32-x64-msvc': 1.1.2 + '@rolldown/binding-android-arm64': 1.1.4 + '@rolldown/binding-darwin-arm64': 1.1.4 + '@rolldown/binding-darwin-x64': 1.1.4 + '@rolldown/binding-freebsd-x64': 1.1.4 + '@rolldown/binding-linux-arm-gnueabihf': 1.1.4 + '@rolldown/binding-linux-arm64-gnu': 1.1.4 + '@rolldown/binding-linux-arm64-musl': 1.1.4 + '@rolldown/binding-linux-ppc64-gnu': 1.1.4 + '@rolldown/binding-linux-s390x-gnu': 1.1.4 + '@rolldown/binding-linux-x64-gnu': 1.1.4 + '@rolldown/binding-linux-x64-musl': 1.1.4 + '@rolldown/binding-openharmony-arm64': 1.1.4 + '@rolldown/binding-wasm32-wasi': 1.1.4 + '@rolldown/binding-win32-arm64-msvc': 1.1.4 + '@rolldown/binding-win32-x64-msvc': 1.1.4 rollup@4.62.2: dependencies: @@ -21167,9 +21373,9 @@ snapshots: vite@8.1.0(@types/node@20.19.43)(yaml@2.9.0): dependencies: lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.15 - rolldown: 1.1.2 + picomatch: 4.0.5 + postcss: 8.5.16 + rolldown: 1.1.4 tinyglobby: 0.2.17 optionalDependencies: '@types/node': 20.19.43 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 09942b8ba..30d01492e 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -5,3 +5,4 @@ overrides: follow-redirects: 1.16.0 uuid: 14.0.0 lodash: 4.18.1 + brace-expansion: 5.0.7 From 8e4d6c48f673e772379a39ce2df67ec711d5df82 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 16 Jul 2026 14:35:11 +0530 Subject: [PATCH 16/18] updated logs --- .talismanrc | 2 ++ packages/contentstack-import/src/import/modules/assets.ts | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.talismanrc b/.talismanrc index e93a2ed36..a4c73f7b4 100644 --- a/.talismanrc +++ b/.talismanrc @@ -56,4 +56,6 @@ fileignoreconfig: checksum: 5b2050b283ea3d990e8ad3207b054c6932b76d2bd82a9f659b287ef11dec9f83 - filename: packages/contentstack-export/src/utils/export-config-handler.ts checksum: 39a5f63dab167c6ed442391ed0528a457ef9f32a7d9e9972d1f8cc54289d67b3 +- filename: packages/contentstack-import/src/import/modules/assets.ts + checksum: 828b9ea0418a4fdcffc41bc8391e851215eef9b6cdb14ef4e11ea3e5b2538f65 version: "" diff --git a/packages/contentstack-import/src/import/modules/assets.ts b/packages/contentstack-import/src/import/modules/assets.ts index 6117a145a..e401c3222 100644 --- a/packages/contentstack-import/src/import/modules/assets.ts +++ b/packages/contentstack-import/src/import/modules/assets.ts @@ -205,13 +205,13 @@ export default class ImportAssets extends BaseClass { log.success('Assets imported successfully!', this.importConfig.context); if (this.importConfig.assetScanningEnabled) { - log.info(' Asset Scanning is enabled for this stack.', this.importConfig.context); + log.info('Asset Scanning is enabled for this stack.', this.importConfig.context); + log.info('Assets cannot be published immediately — scanning must complete first.', this.importConfig.context); + log.info('Once scanning is done, publish your assets using:', this.importConfig.context); log.info( - ' Assets cannot be published immediately — scanning must complete first.', + 'csdx cm:stacks:bulk-assets --data-dir ./content --stack-api-key --operation publish', this.importConfig.context, ); - log.info(' Once scanning is done, publish your assets using:', this.importConfig.context); - log.info(' csdx cm:stacks:bulk-assets --data-dir ./content --stack-api-key --operation publish', this.importConfig.context); } } catch (error) { this.completeProgress(false, error?.message || 'Asset import failed'); From c6d6e1eaa20ee0a96254fcc3f6552f038896e2e3 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 16 Jul 2026 17:30:04 +0530 Subject: [PATCH 17/18] added type --- packages/contentstack-import/src/import/modules/assets.ts | 6 +++--- packages/contentstack-import/src/types/import-config.ts | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/contentstack-import/src/import/modules/assets.ts b/packages/contentstack-import/src/import/modules/assets.ts index e401c3222..93e6bbc2a 100644 --- a/packages/contentstack-import/src/import/modules/assets.ts +++ b/packages/contentstack-import/src/import/modules/assets.ts @@ -8,7 +8,7 @@ import uniq from 'lodash/uniq'; import { existsSync } from 'node:fs'; import includes from 'lodash/includes'; import { resolve as pResolve, join } from 'node:path'; -import { FsUtility, log, handleAndLogError, generateUid } from '@contentstack/cli-utilities'; +import { FsUtility, log, handleAndLogError, generateUid, FeatureStatus } from '@contentstack/cli-utilities'; import { ImportSpaces, type SpaceMapping } from '@contentstack/cli-asset-management'; import { PATH_CONSTANTS } from '../../constants'; @@ -39,13 +39,13 @@ export default class ImportAssets extends BaseClass { private assetsUrlMap: Record = {}; private assetsFolderMap: Record = {}; private rootFolder: { uid: string; name: string; parent_uid: string; created_at: string }; - private planStatus: Record = {}; + private planStatus: Record = {}; constructor({ importConfig, stackAPIClient }: ModuleClassParams) { super({ importConfig, stackAPIClient }); this.importConfig.context.module = MODULE_CONTEXTS.ASSETS; this.currentModuleName = MODULE_NAMES[MODULE_CONTEXTS.ASSETS]; - this.planStatus = this.importConfig.planStatus; + this.planStatus = this.importConfig.planStatus || {}; this.assetsPath = join(this.importConfig.backupDir, PATH_CONSTANTS.CONTENT_DIRS.ASSETS); this.mapperDirPath = join(this.importConfig.backupDir, PATH_CONSTANTS.MAPPER, PATH_CONSTANTS.MAPPER_MODULES.ASSETS); diff --git a/packages/contentstack-import/src/types/import-config.ts b/packages/contentstack-import/src/types/import-config.ts index 6f8e06515..5fea67cce 100644 --- a/packages/contentstack-import/src/types/import-config.ts +++ b/packages/contentstack-import/src/types/import-config.ts @@ -1,3 +1,4 @@ +import { FeatureStatus } from '@contentstack/cli-utilities'; import { Context, Modules, Region } from '.'; import DefaultConfig from './default-config'; @@ -61,7 +62,7 @@ export default interface ImportConfig extends DefaultConfig, ExternalConfig { context: Context; csAssetsUrl?: string; csAssetsEnabled?: boolean; - planStatus: any; + planStatus?: Record; } type branch = { From af9140c3dd06e362124a82c8a432214f028599e2 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 16 Jul 2026 17:45:48 +0530 Subject: [PATCH 18/18] added type --- packages/contentstack-export/src/types/export-config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/contentstack-export/src/types/export-config.ts b/packages/contentstack-export/src/types/export-config.ts index acf43724c..33cf163c0 100644 --- a/packages/contentstack-export/src/types/export-config.ts +++ b/packages/contentstack-export/src/types/export-config.ts @@ -1,3 +1,4 @@ +import { FeatureStatus } from '@contentstack/cli-utilities'; import { Context, Modules, Region } from '.'; import DefaultConfig from './default-config'; @@ -36,7 +37,7 @@ export default interface ExportConfig extends DefaultConfig { skipDependencies?: boolean; authenticationMethod?: string; linkedWorkspaces?: Array<{ uid: string; space_uid: string; is_default: boolean }>; - planStatus: any; + planStatus?: Record; } type branch = {