@@ -26,6 +26,7 @@ export default class ImportExtensions extends BaseClass {
2626 constructor ( { importConfig, stackAPIClient } : ModuleClassParams ) {
2727 super ( { importConfig, stackAPIClient } ) ;
2828 this . importConfig . context . module = 'extensions' ;
29+ this . currentModuleName = 'Extensions' ;
2930 this . extensionsConfig = importConfig . modules . extensions ;
3031 this . mapperDirPath = join ( this . importConfig . backupDir , 'mapper' , 'extensions' ) ;
3132 this . extensionsFolderPath = join ( this . importConfig . backupDir , this . extensionsConfig . dirName ) ;
@@ -45,82 +46,49 @@ export default class ImportExtensions extends BaseClass {
4546 * @returns {Promise<void> } Promise<void>
4647 */
4748 async start ( ) : Promise < void > {
48- log . debug ( 'Checking for extensions folder existence' , this . importConfig . context ) ;
49-
50- //Step1 check folder exists or not
51- if ( fileHelper . fileExistsSync ( this . extensionsFolderPath ) ) {
52- log . debug ( `Found extensions folder: ${ this . extensionsFolderPath } ` , this . importConfig . context ) ;
53-
54- this . extensions = fsUtil . readFile ( join ( this . extensionsFolderPath , 'extensions.json' ) , true ) as Record <
55- string ,
56- Record < string , unknown >
57- > ;
58-
59- // Check if extensions file was read successfully
60- if ( ! this . extensions ) {
61- log . info ( `No extensions found in file - '${ join ( this . extensionsFolderPath , 'extensions.json' ) } '` , this . importConfig . context ) ;
49+ try {
50+ log . debug ( 'Starting Create process...' , this . importConfig . context ) ;
51+ const [ extensionsCount ] = await this . analyzeExtensions ( ) ;
52+ if ( extensionsCount === 0 ) {
53+ log . info ( 'No extensions found to import' , this . importConfig . context ) ;
6254 return ;
6355 }
64-
65- const extensionsCount = Object . keys ( this . extensions || { } ) . length ;
66- log . debug ( `Loaded ${ extensionsCount } extension items from file` , this . importConfig . context ) ;
67- } else {
68- log . info ( `No Extensions Found - '${ this . extensionsFolderPath } '` , this . importConfig . context ) ;
69- return ;
70- }
7156
72- log . debug ( 'Creating extensions mapper directory' , this . importConfig . context ) ;
73- await fsUtil . makeDirectory ( this . mapperDirPath ) ;
74-
75- log . debug ( 'Loading existing extensions UID data' , this . importConfig . context ) ;
76- this . extUidMapper = fileHelper . fileExistsSync ( this . extUidMapperPath )
77- ? ( fsUtil . readFile ( join ( this . extUidMapperPath ) , true ) as Record < string , unknown > ) || { }
78- : { } ;
57+ const progress = this . createNestedProgress ( this . currentModuleName ) ;
58+ progress . addProcess ( 'Create' , extensionsCount ) ;
7959
80- if ( this . extUidMapper && Object . keys ( this . extUidMapper || { } ) . length > 0 ) {
81- const extUidCount = Object . keys ( this . extUidMapper || { } ) . length ;
82- log . debug ( `Loaded existing extensions UID data: ${ extUidCount } items` , this . importConfig . context ) ;
83- } else {
84- log . debug ( 'No existing extensions UID data found' , this . importConfig . context ) ;
85- }
60+ await this . prepareExtensionMapper ( ) ;
61+ log . debug ( 'Checking content types in extension scope' , this . importConfig . context ) ;
8662
87- // Check whether the scope of an extension contains content-types in scope
88- // Remove the scope and store the scope with uid in pending extensions
89- log . debug ( 'Checking content types in extension scope' , this . importConfig . context ) ;
90- this . getContentTypesInScope ( ) ;
91-
92- log . debug ( 'Starting extensions import' , this . importConfig . context ) ;
93- await this . importExtensions ( ) ;
94-
95- // Update the uid of the extension
96- log . debug ( 'Updating extension UIDs' , this . importConfig . context ) ;
97- this . updateUidExtension ( ) ;
98-
99- // Note: if any extensions present, then update it
100- if ( this . importConfig . replaceExisting && this . existingExtensions . length > 0 ) {
101- log . debug ( `Replacing ${ this . existingExtensions . length } existing extensions` , this . importConfig . context ) ;
102- await this . replaceExtensions ( ) . catch ( ( error : Error ) => {
103- log . debug ( 'Error replacing extensions' , this . importConfig . context ) ;
104- handleAndLogError ( error , { ...this . importConfig . context } ) ;
105- } ) ;
106- }
63+ this . getContentTypesInScope ( ) ;
10764
108- log . debug ( 'Processing extensions import results' , this . importConfig . context ) ;
109- if ( this . extSuccess ?. length ) {
110- fsUtil . writeFile ( this . extSuccessPath , this . extSuccess ) ;
111- log . debug ( `Written ${ this . extSuccess . length } successful extensions to file` , this . importConfig . context ) ;
112- }
65+ progress . startProcess ( 'Create' ) . updateStatus ( 'Importing extensions...' , 'Create' ) ;
66+ log . debug ( 'Starting Create' , this . importConfig . context ) ;
67+ await this . importExtensions ( ) ;
68+ progress . completeProcess ( 'Create' , true ) ;
11369
114- if ( this . extFailed ?. length ) {
115- fsUtil . writeFile ( this . extFailsPath , this . extFailed ) ;
116- log . debug ( `Written ${ this . extFailed . length } failed extensions to file` , this . importConfig . context ) ;
117- }
70+ log . debug ( 'Updating extension UIDs' , this . importConfig . context ) ;
71+ this . updateUidExtension ( ) ;
72+
73+ if ( this . importConfig . replaceExisting && this . existingExtensions . length > 0 ) {
74+ progress . addProcess ( 'Update' , this . existingExtensions . length ) ;
75+ progress . startProcess ( 'Update' ) . updateStatus ( 'Updating existing extensions...' , 'Update' ) ;
76+ await this . replaceExtensions ( ) ;
77+ progress . completeProcess ( 'Update' , true ) ;
78+ }
11879
80+ await this . processExtensionResults ( ) ;
81+
82+ this . completeProgress ( true ) ;
11983 log . success ( 'Extensions have been imported successfully!' , this . importConfig . context ) ;
84+ } catch ( error ) {
85+ this . completeProgress ( false , error ?. message || 'Create failed' ) ;
86+ handleAndLogError ( error , { ...this . importConfig . context } ) ;
87+ }
12088 }
12189
12290 async importExtensions ( ) : Promise < any > {
123- log . debug ( 'Starting extensions import process' , this . importConfig . context ) ;
91+ log . debug ( 'Starting Create process' , this . importConfig . context ) ;
12492 if ( this . extensions === undefined || isEmpty ( this . extensions ) ) {
12593 log . info ( 'No Extensions Found' , this . importConfig . context ) ;
12694 return ;
@@ -132,30 +100,48 @@ export default class ImportExtensions extends BaseClass {
132100 const onSuccess = ( { response, apiData : { uid, title } = { uid : null , title : '' } } : any ) => {
133101 this . extSuccess . push ( response ) ;
134102 this . extUidMapper [ uid ] = response . uid ;
103+ this . progressManager ?. tick ( true , `extension: ${ title || uid } ` , null , 'Create' ) ;
135104 log . success ( `Extension '${ title } ' imported successfully` , this . importConfig . context ) ;
136105 log . debug ( `Extension import completed: ${ title } (${ uid } )` , this . importConfig . context ) ;
137106 fsUtil . writeFile ( this . extUidMapperPath , this . extUidMapper ) ;
138107 } ;
139108
140109 const onReject = ( { error, apiData } : any ) => {
141- const { title } = apiData ;
110+ const { title, uid } = apiData ;
142111 log . debug ( `Extension '${ title } ' import failed` , this . importConfig . context ) ;
143-
112+
144113 if ( error ?. errors ?. title ) {
145114 if ( this . importConfig . replaceExisting ) {
146115 this . existingExtensions . push ( apiData ) ;
116+ this . progressManager ?. tick (
117+ true ,
118+ `extension: ${ title || uid } (marked for replacement)` ,
119+ null ,
120+ 'Create' ,
121+ ) ;
147122 log . debug ( `Extension '${ title } ' marked for replacement` , this . importConfig . context ) ;
123+ } else {
124+ this . progressManager ?. tick ( true , `extension: ${ title || uid } (already exists)` , null , 'Create' ) ;
148125 }
149126 if ( ! this . importConfig . skipExisting ) {
150127 log . info ( `Extension '${ title } ' already exists` , this . importConfig . context ) ;
151128 }
152129 } else {
153130 this . extFailed . push ( apiData ) ;
131+ this . progressManager ?. tick (
132+ false ,
133+ `extension: ${ title || uid } ` ,
134+ error ?. message || 'Failed to import extension' ,
135+ 'Create' ,
136+ ) ;
154137 handleAndLogError ( error , { ...this . importConfig . context , title } , `Extension '${ title } ' failed to be import` ) ;
155138 }
156139 } ;
157140
158- log . debug ( `Using concurrency limit: ${ this . importConfig . concurrency || this . importConfig . fetchConcurrency || 1 } ` , this . importConfig . context ) ;
141+ log . debug (
142+ `Using concurrency limit: ${ this . importConfig . concurrency || this . importConfig . fetchConcurrency || 1 } ` ,
143+ this . importConfig . context ,
144+ ) ;
159145 await this . makeConcurrentCall (
160146 {
161147 apiContent,
@@ -171,28 +157,35 @@ export default class ImportExtensions extends BaseClass {
171157 undefined ,
172158 false ,
173159 ) ;
174-
175- log . debug ( 'Extensions import process completed' , this . importConfig . context ) ;
160+
161+ log . debug ( 'Create process completed' , this . importConfig . context ) ;
176162 }
177163
178164 async replaceExtensions ( ) : Promise < any > {
179165 log . debug ( `Replacing ${ this . existingExtensions . length } existing extensions` , this . importConfig . context ) ;
180-
166+
181167 const onSuccess = ( { response, apiData : { uid, title } = { uid : null , title : '' } } : any ) => {
182168 this . extSuccess . push ( response ) ;
183169 this . extUidMapper [ uid ] = response . uid ;
184- log . success ( `Extension '${ title } ' replaced successfully` , this . importConfig . context ) ;
185- log . debug ( `Extension replacement completed: ${ title } (${ uid } )` , this . importConfig . context ) ;
170+ this . progressManager ?. tick ( true , `extension: ${ title || uid } (updated)` , null , 'Update' ) ;
171+ log . success ( `Extension '${ title } ' updated successfully` , this . importConfig . context ) ;
172+ log . debug ( `Extension update completed: ${ title } (${ uid } )` , this . importConfig . context ) ;
186173 fsUtil . writeFile ( this . extUidMapperPath , this . extUidMapper ) ;
187174 } ;
188175
189176 const onReject = ( { error, apiData } : any ) => {
190- log . debug ( `Extension ' ${ apiData . title } ' replacement failed` , this . importConfig . context ) ;
177+ const { title, uid } = apiData ;
191178 this . extFailed . push ( apiData ) ;
192- handleAndLogError ( error , { ...this . importConfig . context , title : apiData . title } , `Extension '${ apiData . title } ' failed to replace` ) ;
179+ this . progressManager ?. tick (
180+ false ,
181+ `extension: ${ title || uid } ` ,
182+ error ?. message || 'Failed to update extension' ,
183+ 'Update' ,
184+ ) ;
185+ log . debug ( `Extension '${ title } ' update failed` , this . importConfig . context ) ;
186+ handleAndLogError ( error , { ...this . importConfig . context , title } , `Extension '${ title } ' failed to be updated` ) ;
193187 } ;
194188
195- log . debug ( `Using concurrency limit for replacement: ${ this . importConfig . concurrency || this . importConfig . fetchConcurrency || 1 } ` , this . importConfig . context ) ;
196189 await this . makeConcurrentCall (
197190 {
198191 apiContent : this . existingExtensions ,
@@ -207,7 +200,7 @@ export default class ImportExtensions extends BaseClass {
207200 } ,
208201 this . replaceExtensionHandler . bind ( this ) ,
209202 ) ;
210-
203+
211204 log . debug ( 'Extensions replacement process completed' , this . importConfig . context ) ;
212205 }
213206
@@ -221,10 +214,10 @@ export default class ImportExtensions extends BaseClass {
221214 isLastRequest : boolean ;
222215 } ) {
223216 log . debug ( `Processing extension replacement: ${ extension . title } ` , this . importConfig . context ) ;
224-
217+
225218 return new Promise ( async ( resolve , reject ) => {
226219 log . debug ( `Searching for existing extension: ${ extension . title } ` , this . importConfig . context ) ;
227-
220+
228221 const { items : [ extensionsInStack ] = [ ] } : any = await this . stack
229222 . extension ( )
230223 . query ( { query : { title : extension . title } } )
@@ -237,18 +230,21 @@ export default class ImportExtensions extends BaseClass {
237230 } ) ;
238231 reject ( true ) ;
239232 } ) ;
240-
233+
241234 if ( extensionsInStack ) {
242- log . debug ( `Found existing extension in stack: ${ extension . title } (${ extensionsInStack . uid } )` , this . importConfig . context ) ;
243-
235+ log . debug (
236+ `Found existing extension in stack: ${ extension . title } (${ extensionsInStack . uid } )` ,
237+ this . importConfig . context ,
238+ ) ;
239+
244240 const extensionPayload = this . stack . extension ( extension . uid ) ;
245241 Object . assign ( extensionPayload , extensionsInStack , cloneDeep ( extension ) , {
246242 uid : extensionsInStack . uid ,
247243 urlPath : extensionsInStack . urlPath ,
248244 _version : extensionsInStack . _version ,
249245 stackHeaders : extensionsInStack . stackHeaders ,
250246 } ) ;
251-
247+
252248 log . debug ( `Updating extension: ${ extension . title } ` , this . importConfig . context ) ;
253249 return extensionPayload
254250 . update ( )
@@ -281,46 +277,113 @@ export default class ImportExtensions extends BaseClass {
281277
282278 getContentTypesInScope ( ) {
283279 log . debug ( 'Processing content types in extension scope' , this . importConfig . context ) ;
284-
280+
285281 const extension = values ( this . extensions ) ;
286282 let processedExtensions = 0 ;
287-
283+
288284 extension . forEach ( ( ext : ExtensionType ) => {
289285 let ct : any = ext ?. scope ?. content_types || [ ] ;
290286 if ( ( ct . length === 1 && ct [ 0 ] !== '$all' ) || ct ?. length > 1 ) {
291- log . info ( `Removing the content-types ${ ct . join ( ',' ) } from the extension ${ ext . title } ...` , this . importConfig . context ) ;
287+ log . info (
288+ `Removing the content-types ${ ct . join ( ',' ) } from the extension ${ ext . title } ...` ,
289+ this . importConfig . context ,
290+ ) ;
292291 log . debug ( `Extension '${ ext . title } ' has ${ ct . length } content types in scope` , this . importConfig . context ) ;
293-
292+
294293 const { uid, scope } = ext ;
295294 this . extensionObject . push ( { uid, scope } ) ;
296295 delete ext . scope ;
297296 this . extensions [ ext . uid ] = ext ;
298297 processedExtensions ++ ;
299298 }
300299 } ) ;
301-
300+
302301 log . debug ( `Processed ${ processedExtensions } extensions with content type scope` , this . importConfig . context ) ;
303302 log . debug ( `Total extensions with pending scope: ${ this . extensionObject . length } ` , this . importConfig . context ) ;
304303 }
305304
306305 updateUidExtension ( ) {
307306 log . debug ( 'Updating extension UIDs in pending extensions' , this . importConfig . context ) ;
308-
307+
309308 let updatedCount = 0 ;
310309 for ( let i in this . extensionObject ) {
311310 const originalUid = this . extensionObject [ i ] . uid as string ;
312311 this . extensionObject [ i ] . uid = this . extUidMapper [ originalUid ] ;
313312 if ( this . extUidMapper [ originalUid ] ) {
314313 updatedCount ++ ;
315- log . debug ( `Updated extension UID: ${ originalUid } → ${ this . extUidMapper [ originalUid ] } ` , this . importConfig . context ) ;
314+ log . debug (
315+ `Updated extension UID: ${ originalUid } → ${ this . extUidMapper [ originalUid ] } ` ,
316+ this . importConfig . context ,
317+ ) ;
316318 }
317319 }
318-
320+
319321 log . debug ( `Updated ${ updatedCount } extension UIDs in pending extensions` , this . importConfig . context ) ;
320-
322+
321323 if ( this . extensionObject . length > 0 ) {
322324 fsUtil . writeFile ( this . extPendingPath , this . extensionObject ) ;
323325 log . debug ( `Written ${ this . extensionObject . length } pending extensions to file` , this . importConfig . context ) ;
324326 }
325327 }
328+
329+ private async analyzeExtensions ( ) : Promise < [ number ] > {
330+ return this . withLoadingSpinner ( 'EXTENSIONS: Analyzing import data...' , async ( ) => {
331+ log . debug ( 'Checking for extensions folder existence' , this . importConfig . context ) ;
332+
333+ if ( ! fileHelper . fileExistsSync ( this . extensionsFolderPath ) ) {
334+ log . info ( `No Extensions Found - '${ this . extensionsFolderPath } '` , this . importConfig . context ) ;
335+ return [ 0 ] ;
336+ }
337+
338+ log . debug ( `Found extensions folder: ${ this . extensionsFolderPath } ` , this . importConfig . context ) ;
339+
340+ this . extensions = fsUtil . readFile ( join ( this . extensionsFolderPath , 'extensions.json' ) , true ) as Record <
341+ string ,
342+ Record < string , unknown >
343+ > ;
344+
345+ if ( ! this . extensions ) {
346+ log . info (
347+ `No extensions found in file - '${ join ( this . extensionsFolderPath , 'extensions.json' ) } '` ,
348+ this . importConfig . context ,
349+ ) ;
350+ return [ 0 ] ;
351+ }
352+
353+ const count = Object . keys ( this . extensions ) . length ;
354+ log . debug ( `Loaded ${ count } extension items from file` , this . importConfig . context ) ;
355+ return [ count ] ;
356+ } ) ;
357+ }
358+
359+ private async prepareExtensionMapper ( ) : Promise < void > {
360+ log . debug ( 'Creating extensions mapper directory' , this . importConfig . context ) ;
361+ await fsUtil . makeDirectory ( this . mapperDirPath ) ;
362+
363+ log . debug ( 'Loading existing extensions UID data' , this . importConfig . context ) ;
364+ this . extUidMapper = fileHelper . fileExistsSync ( this . extUidMapperPath )
365+ ? ( fsUtil . readFile ( this . extUidMapperPath , true ) as Record < string , unknown > ) || { }
366+ : { } ;
367+
368+ const count = Object . keys ( this . extUidMapper || { } ) . length ;
369+ if ( count > 0 ) {
370+ log . debug ( `Loaded existing extensions UID data: ${ count } items` , this . importConfig . context ) ;
371+ } else {
372+ log . debug ( 'No existing extensions UID data found' , this . importConfig . context ) ;
373+ }
374+ }
375+
376+ private async processExtensionResults ( ) : Promise < void > {
377+ log . debug ( 'Processing Create results' , this . importConfig . context ) ;
378+
379+ if ( this . extSuccess ?. length ) {
380+ fsUtil . writeFile ( this . extSuccessPath , this . extSuccess ) ;
381+ log . debug ( `Written ${ this . extSuccess . length } successful extensions to file` , this . importConfig . context ) ;
382+ }
383+
384+ if ( this . extFailed ?. length ) {
385+ fsUtil . writeFile ( this . extFailsPath , this . extFailed ) ;
386+ log . debug ( `Written ${ this . extFailed . length } failed extensions to file` , this . importConfig . context ) ;
387+ }
388+ }
326389}
0 commit comments