@@ -9,11 +9,11 @@ import { existsSync } from 'node:fs';
99import includes from 'lodash/includes' ;
1010import { v4 as uuid } from 'uuid' ;
1111import { resolve as pResolve , join } from 'node:path' ;
12- import { FsUtility , log , handleAndLogError } from '@contentstack/cli-utilities' ;
12+ import { FsUtility , log , handleAndLogError , sanitizePath } from '@contentstack/cli-utilities' ;
1313
1414import config from '../../config' ;
1515import { ModuleClassParams } from '../../types' ;
16- import { formatDate } from '../../utils' ;
16+ import { formatDate , fsUtil } from '../../utils' ;
1717import BaseClass , { ApiOptions } from './base-class' ;
1818
1919export default class ImportAssets extends BaseClass {
@@ -29,6 +29,7 @@ export default class ImportAssets extends BaseClass {
2929 private assetsUidMap : Record < string , unknown > = { } ;
3030 private assetsUrlMap : Record < string , unknown > = { } ;
3131 private assetsFolderMap : Record < string , unknown > = { } ;
32+ private pendingPublishAssets : Array < { oldUid : string ; newUid : string } > = [ ] ;
3233 private rootFolder : { uid : string ; name : string ; parent_uid : string ; created_at : string } ;
3334
3435 constructor ( { importConfig, stackAPIClient } : ModuleClassParams ) {
@@ -54,11 +55,11 @@ export default class ImportAssets extends BaseClass {
5455 */
5556 async start ( ) : Promise < void > {
5657 try {
57- // NOTE Step 1: Import folders and create uid mapping file
58+ // NOTE Step 1: Import folders and create uid mapping file
5859 log . debug ( 'Starting folder import process...' , this . importConfig . context ) ;
5960 await this . importFolders ( ) ;
6061
61- // NOTE Step 2: Import versioned assets and create it mapping files (uid, url)
62+ // NOTE Step 2: Import versioned assets and create it mapping files (uid, url)
6263 if ( this . assetConfig . includeVersionedAssets ) {
6364 const versionsPath = `${ this . assetsPath } /versions` ;
6465 if ( existsSync ( versionsPath ) ) {
@@ -69,17 +70,15 @@ export default class ImportAssets extends BaseClass {
6970 }
7071 }
7172
72- // NOTE Step 3: Import Assets and create it mapping files (uid, url)
73+ // NOTE Step 3: Import Assets and create it mapping files (uid, url)
7374 log . debug ( 'Starting assets import...' , this . importConfig . context ) ;
7475 await this . importAssets ( ) ;
7576
76- // NOTE Step 4: Publish assets
77- if ( ! this . importConfig . skipAssetsPublish ) {
78- log . debug ( 'Starting assets publishing...' , this . importConfig . context ) ;
79- await this . publish ( ) ;
80- }
77+ // NOTE Step 4: Save publish details for deferred publishing
78+ log . debug ( 'Saving asset publish details for deferred publishing' , this . importConfig . context ) ;
79+ await this . savePublishDetails ( ) ;
8180
82- log . success ( 'Assets imported successfully! ' , this . importConfig . context ) ;
81+ log . success ( 'Assets imported successfully' , this . importConfig . context ) ;
8382 } catch ( error ) {
8483 handleAndLogError ( error , { ...this . importConfig . context } ) ;
8584 }
@@ -179,9 +178,18 @@ export default class ImportAssets extends BaseClass {
179178
180179 log . debug ( `Found ${ indexerCount } asset chunks to process` , this . importConfig . context ) ;
181180
182- const onSuccess = ( { response = { } , apiData : { uid, url, title } = undefined } : any ) => {
181+ const onSuccess = ( { response = { } , apiData : { uid, url, title, publish_details } = undefined } : any ) => {
183182 this . assetsUidMap [ uid ] = response . uid ;
184183 this . assetsUrlMap [ url ] = response . url ;
184+ // Track assets with valid publish_details for deferred publishing
185+ if ( ! isEmpty ( publish_details ) ) {
186+ const validPublishDetails = filter ( publish_details , ( { environment } : any ) =>
187+ this . environments ?. hasOwnProperty ( environment ) ,
188+ ) ;
189+ if ( validPublishDetails . length > 0 ) {
190+ this . pendingPublishAssets . push ( { oldUid : uid , newUid : response . uid } ) ;
191+ }
192+ }
185193 log . debug ( `Created asset: ${ title } (Mapped ${ uid } → ${ response . uid } )` , this . importConfig . context ) ;
186194 log . success ( `Created asset: '${ title } '` , this . importConfig . context ) ;
187195 } ;
@@ -387,6 +395,30 @@ export default class ImportAssets extends BaseClass {
387395 }
388396 }
389397
398+ /**
399+ * @method savePublishDetails
400+ * @description Saves pending asset UID mappings for deferred publishing
401+ * @returns {Promise<void> } Promise<void>
402+ */
403+ async savePublishDetails ( ) : Promise < void > {
404+ if ( this . pendingPublishAssets . length === 0 ) {
405+ log . info ( 'No assets with publish details to track' , this . importConfig . context ) ;
406+ return ;
407+ }
408+
409+ const publishConfig = this . importConfig . modules . publish ;
410+ const publishDirPath = join ( sanitizePath ( this . importConfig . backupDir ) , 'mapper' , publishConfig . dirName ) ;
411+ const pendingFilePath = join ( publishDirPath , publishConfig . pendingAssetsFileName ) ;
412+
413+ // Ensure the publish directory exists
414+ await fsUtil . makeDirectory ( publishDirPath ) ;
415+
416+ const assetCount = this . pendingPublishAssets . length ;
417+ log . debug ( `Writing ${ assetCount } pending asset UID mappings to file` , this . importConfig . context ) ;
418+ await fsUtil . writeFile ( pendingFilePath , this . pendingPublishAssets ) ;
419+ log . success ( `Saved ${ assetCount } assets for deferred publishing` , this . importConfig . context ) ;
420+ }
421+
390422 /**
391423 * @method constructFolderImportOrder
392424 * @param {Record<string, any>[] } folders object
0 commit comments