@@ -32,6 +32,7 @@ class Cloner {
3232 * @param {* } options.includeSubmissionRevisions - Include submission revisions when cloning submissions.
3333 * @param {* } options.updateExistingSubmissions - Update existing submissions when found in the destination (performs a complete re-clone).
3434 * @param {* } options.forms - A comma-separated value of all the Form ID's you wish to clone. If included, then only the provided forms will be cloned.
35+ * @param {* } options.exclude - A comma-separated value of all the Form ID's you wish to exclude from cloning.
3536 * @param {* } options.submissionsOnly - Only clone submissions.
3637 * @param {* } options.apiSource - Flag to define if we need to clone from an API.
3738 * @param {* } options.key - API Key to be used to authenticate in source.
@@ -48,6 +49,7 @@ class Cloner {
4849 this . src = null ;
4950 this . dest = null ;
5051 this . cloneState = { } ;
52+ this . exclude = this . options . exclude ? this . options . exclude . split ( ',' ) : [ ] ;
5153
5254 if ( this . options . apiSource ) {
5355 this . requestHeaders = {
@@ -230,14 +232,26 @@ class Cloner {
230232 * Determine if we should clone the given item.
231233 * @param {* } srcItem - The source item to check.
232234 */
233- shouldClone ( collection , srcItem ) {
235+ shouldClone ( collection , srcItem , updatedItem ) {
234236 if ( this . options . submissionsOnly && collection !== 'submissions' ) {
235237 return false ;
236238 }
237- if ( this . options . createdAfter && srcItem . created < parseInt ( this . options . createdAfter , 10 ) ) {
239+ const srcCreated = ( srcItem . created instanceof Date ) ? srcItem . created . getTime ( ) : parseInt ( srcItem . created , 10 ) ;
240+ if ( this . options . createdAfter && srcCreated < parseInt ( this . options . createdAfter , 10 ) ) {
238241 return false ;
239242 }
240- if ( this . options . modifiedAfter && srcItem . modified < parseInt ( this . options . modifiedAfter , 10 ) ) {
243+ // eslint-disable-next-line max-len
244+ const srcModified = ( srcItem . modified instanceof Date ) ? srcItem . modified . getTime ( ) : parseInt ( srcItem . modified , 10 ) ;
245+ if ( this . options . modifiedAfter && srcModified < parseInt ( this . options . modifiedAfter , 10 ) ) {
246+ return false ;
247+ }
248+
249+ // Make sure to not re-clone the same item it if has not been modified.
250+ // eslint-disable-next-line max-len
251+ const updatedCreated = ( updatedItem . created instanceof Date ) ? updatedItem . created . getTime ( ) : parseInt ( updatedItem . created , 10 ) ;
252+ // eslint-disable-next-line max-len
253+ const updatedModified = ( updatedItem . modified instanceof Date ) ? updatedItem . modified . getTime ( ) : parseInt ( updatedItem . modified , 10 ) ;
254+ if ( srcCreated === updatedCreated && srcModified === updatedModified ) {
241255 return false ;
242256 }
243257 return true ;
@@ -324,6 +338,10 @@ class Cloner {
324338 }
325339 }
326340
341+ if ( collection === 'forms' && this . exclude . includes ( srcItem . _id . toString ( ) ) ) {
342+ return ;
343+ }
344+
327345 if ( eachItem ) {
328346 eachItem ( srcItem ) ;
329347 }
@@ -340,7 +358,7 @@ class Cloner {
340358
341359 // Call before handler and then update if it says we should.
342360 if (
343- this . shouldClone ( collection , srcItem ) &&
361+ this . shouldClone ( collection , srcItem , updatedItem ) &&
344362 await this . before ( collection , beforeEach , srcItem , updatedItem , destItem ) !== false
345363 ) {
346364 if ( destItem ) {
@@ -869,6 +887,8 @@ class Cloner {
869887 const srcId = update . settings . role ;
870888 update . settings . role = await this . getDestinationRoleId ( srcId , destForm . project ) ;
871889 }
890+ } , null , ( current ) => {
891+ return { $or : [ { _id : current . _id } , { machineName : current . machineName } ] } ;
872892 } ) ;
873893 }
874894
@@ -883,7 +903,7 @@ class Cloner {
883903 let compsWithEncryptedData = [ ] ;
884904 await this . upsertAll ( 'forms' , this . formQuery ( srcProject ) , ( form ) => {
885905 process . stdout . write ( '\n' ) ;
886- process . stdout . write ( `- Form: ${ form . title } ` ) ;
906+ process . stdout . write ( `- Form: ${ form . title } ( ${ form . _id } ) ` ) ;
887907 } , async ( src , update , dest ) => {
888908 if ( this . options . submissionsOnly ) {
889909 return false ;
@@ -1030,6 +1050,9 @@ class Cloner {
10301050 return ;
10311051 }
10321052 const decryptedDstSettings = dest ? this . decrypt ( this . options . dstDbSecret , dest [ 'settings_encrypted' ] , true ) : { } ;
1053+ if ( ! decryptedDstSettings ) {
1054+ return ;
1055+ }
10331056 if ( decryptedDstSettings . secret ) {
10341057 this . dstSecret = decryptedDstSettings . secret ;
10351058 }
0 commit comments