mcdev 7.10.1 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/.github/ISSUE_TEMPLATE/bug.yml +2 -0
  2. package/.github/workflows/code-test.yml +8 -100
  3. package/.github/workflows/coverage-base-update.yml +2 -2
  4. package/.github/workflows/coverage.yml +1 -1
  5. package/@types/lib/Deployer.d.ts.map +1 -1
  6. package/@types/lib/Retriever.d.ts.map +1 -1
  7. package/@types/lib/index.d.ts +17 -4
  8. package/@types/lib/index.d.ts.map +1 -1
  9. package/@types/lib/metadataTypes/Asset.d.ts +46 -8
  10. package/@types/lib/metadataTypes/Asset.d.ts.map +1 -1
  11. package/@types/lib/metadataTypes/Automation.d.ts +14 -4
  12. package/@types/lib/metadataTypes/Automation.d.ts.map +1 -1
  13. package/@types/lib/metadataTypes/DataExtension.d.ts +1 -0
  14. package/@types/lib/metadataTypes/DataExtension.d.ts.map +1 -1
  15. package/@types/lib/metadataTypes/DataExtensionField.d.ts.map +1 -1
  16. package/@types/lib/metadataTypes/DataExtract.d.ts +1 -0
  17. package/@types/lib/metadataTypes/DataExtract.d.ts.map +1 -1
  18. package/@types/lib/metadataTypes/Event.d.ts +8 -0
  19. package/@types/lib/metadataTypes/Event.d.ts.map +1 -1
  20. package/@types/lib/metadataTypes/FileTransfer.d.ts +1 -0
  21. package/@types/lib/metadataTypes/FileTransfer.d.ts.map +1 -1
  22. package/@types/lib/metadataTypes/Folder.d.ts +49 -12
  23. package/@types/lib/metadataTypes/Folder.d.ts.map +1 -1
  24. package/@types/lib/metadataTypes/ImportFile.d.ts +15 -0
  25. package/@types/lib/metadataTypes/ImportFile.d.ts.map +1 -1
  26. package/@types/lib/metadataTypes/Journey.d.ts +166 -6
  27. package/@types/lib/metadataTypes/Journey.d.ts.map +1 -1
  28. package/@types/lib/metadataTypes/MetadataType.d.ts +6 -3
  29. package/@types/lib/metadataTypes/MetadataType.d.ts.map +1 -1
  30. package/@types/lib/metadataTypes/MobileKeyword.d.ts +1 -0
  31. package/@types/lib/metadataTypes/MobileKeyword.d.ts.map +1 -1
  32. package/@types/lib/metadataTypes/Query.d.ts +1 -0
  33. package/@types/lib/metadataTypes/Query.d.ts.map +1 -1
  34. package/@types/lib/metadataTypes/Script.d.ts +1 -0
  35. package/@types/lib/metadataTypes/Script.d.ts.map +1 -1
  36. package/@types/lib/metadataTypes/definitions/Asset.definition.d.ts +45 -8
  37. package/@types/lib/metadataTypes/definitions/Automation.definition.d.ts +6 -0
  38. package/@types/lib/metadataTypes/definitions/Event.definition.d.ts +6 -0
  39. package/@types/lib/metadataTypes/definitions/Folder.definition.d.ts +49 -12
  40. package/@types/lib/metadataTypes/definitions/ImportFile.definition.d.ts +3 -0
  41. package/@types/lib/metadataTypes/definitions/Journey.definition.d.ts +159 -6
  42. package/@types/lib/util/cache.d.ts +2 -1
  43. package/@types/lib/util/cache.d.ts.map +1 -1
  44. package/@types/lib/util/devops.d.ts.map +1 -1
  45. package/@types/lib/util/util.d.ts +8 -1
  46. package/@types/lib/util/util.d.ts.map +1 -1
  47. package/@types/types/mcdev.d.d.ts +16 -0
  48. package/@types/types/mcdev.d.d.ts.map +1 -1
  49. package/boilerplate/files/.vscode/settings.json +5 -0
  50. package/eslint.config.js +2 -2
  51. package/lib/Deployer.js +3 -0
  52. package/lib/Retriever.js +8 -2
  53. package/lib/cli.js +29 -0
  54. package/lib/index.js +27 -31
  55. package/lib/metadataTypes/Asset.js +155 -17
  56. package/lib/metadataTypes/Automation.js +137 -40
  57. package/lib/metadataTypes/DataExtension.js +2 -10
  58. package/lib/metadataTypes/DataExtensionField.js +9 -15
  59. package/lib/metadataTypes/DataExtract.js +2 -0
  60. package/lib/metadataTypes/Event.js +63 -32
  61. package/lib/metadataTypes/FileTransfer.js +2 -0
  62. package/lib/metadataTypes/Folder.js +99 -27
  63. package/lib/metadataTypes/ImportFile.js +92 -29
  64. package/lib/metadataTypes/Journey.js +184 -24
  65. package/lib/metadataTypes/MetadataType.js +53 -25
  66. package/lib/metadataTypes/MobileKeyword.js +2 -0
  67. package/lib/metadataTypes/Query.js +2 -0
  68. package/lib/metadataTypes/Script.js +2 -0
  69. package/lib/metadataTypes/definitions/Asset.definition.js +196 -142
  70. package/lib/metadataTypes/definitions/Automation.definition.js +6 -0
  71. package/lib/metadataTypes/definitions/DataExtension.definition.js +7 -6
  72. package/lib/metadataTypes/definitions/Event.definition.js +6 -0
  73. package/lib/metadataTypes/definitions/Folder.definition.js +69 -22
  74. package/lib/metadataTypes/definitions/ImportFile.definition.js +3 -0
  75. package/lib/metadataTypes/definitions/Journey.definition.js +165 -11
  76. package/lib/util/cache.js +41 -8
  77. package/lib/util/devops.js +20 -5
  78. package/lib/util/file.js +10 -1
  79. package/lib/util/util.js +26 -12
  80. package/package.json +18 -19
  81. package/test/general.test.js +8 -8
  82. package/test/mockRoot/.mcdev-validations.js +2 -3
  83. package/test/mockRoot/.mcdevrc.json +1 -1
  84. package/test/mockRoot/deploy/testInstance/testBU/importFile/testExisting_importFile.importFile-meta.json +2 -1
  85. package/test/mockRoot/deploy/testInstance/testBU/importFile/testNew_importFile.importFile-meta.json +2 -1
  86. package/test/resourceFactory.js +31 -5
  87. package/test/resources/1111111/dataExtension/update-expected.json +1 -1
  88. package/test/resources/9999999/asset/test_coderesource_js-retrieve-expected.js +1 -0
  89. package/test/resources/9999999/asset/test_coderesource_js-retrieve-expected.json +45 -0
  90. package/test/resources/9999999/asset/test_coderesource_json-retrieve-expected.json +45 -0
  91. package/test/resources/9999999/asset/test_coderesource_json-retrieve-expected.jsonc +1 -0
  92. package/test/resources/9999999/asset/test_coderesource_xml-retrieve-expected.json +44 -0
  93. package/test/resources/9999999/asset/test_coderesource_xml-retrieve-expected.xml +1 -0
  94. package/test/resources/9999999/asset/test_interactivecontent-retrieve-expected.json +41 -0
  95. package/test/resources/9999999/asset/test_landingpage-retrieve-expected.json +40 -0
  96. package/test/resources/9999999/asset/test_microsite-retrieve-expected.json +41 -0
  97. package/test/resources/9999999/asset/v1/content/assets/9451/get-response.json +61 -0
  98. package/test/resources/9999999/asset/v1/content/assets/9456/get-response.json +56 -0
  99. package/test/resources/9999999/asset/v1/content/assets/9458/get-response.json +56 -0
  100. package/test/resources/9999999/asset/v1/content/assets/9460/get-response.json +59 -0
  101. package/test/resources/9999999/asset/v1/content/assets/9463/get-response.json +61 -0
  102. package/test/resources/9999999/asset/v1/content/assets/9465/get-response.json +54 -0
  103. package/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,3,4,14,15,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,210,211,212,213,214,215,216,217,218,219,220,221,222.json +94 -1
  104. package/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN219,220,221,222,223,224,225,226,227,228,230,232,240,241,242,243,244,245.json +168 -0
  105. package/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN240,241,242,243,244,245.json +144 -0
  106. package/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN246,247,248,249.json +132 -0
  107. package/test/resources/9999999/dataExtension/update-callout-afterCreatedViaEvent-expected.xml +1 -1
  108. package/test/resources/9999999/dataFolder/{retrieve-ContentTypeINasset,asset-sha,automatio,dataexten,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,triggered,triggered,useriniti-response.xml → retrieve-ContentTypeINasset,asset-sha,automatio,cloudpage,dataexten,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,triggered,triggered,useriniti-response.xml} +44 -1
  109. package/test/resources/9999999/dataFolder/{retrieve-ContentTypeINasset,asset-sha,automatio,dataexten,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,useriniti-response.xml → retrieve-ContentTypeINasset,asset-sha,automatio,cloudpage,dataexten,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,useriniti-response.xml} +44 -0
  110. package/test/resources/9999999/dataFolder/{retrieve-ContentTypeINasset,asset-shared,dataextension,hidden,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml → retrieve-ContentTypeINasset,asset-shared,cloudpages,dataextension,hidden,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml} +44 -0
  111. package/test/resources/9999999/dataFolder/{retrieve-ContentTypeINasset,asset-shared,journey-response.xml → retrieve-ContentTypeINasset,asset-shared,cloudpages,journey-response.xml} +44 -0
  112. package/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,cloudpages,ssjsactivity-response.xml +136 -0
  113. package/test/resources/9999999/dataFolder/{retrieve-ContentTypeINasset,asset-shared,ssjsactivity-response.xml → retrieve-ContentTypeINasset,asset-shared,cloudpages-response.xml} +29 -7
  114. package/test/resources/9999999/dataFolder/{+retrieve-response.xml → retrieve-response.xml} +23 -0
  115. package/test/resources/9999999/dataFolder/update-response.xml +31 -0
  116. package/test/resources/9999999/event/build-expected.json +0 -1
  117. package/test/resources/9999999/event/get-automation-expected.json +0 -1
  118. package/test/resources/9999999/event/get-expected.json +0 -2
  119. package/test/resources/9999999/event/get-published-expected.json +0 -2
  120. package/test/resources/9999999/event/post_withExistingDE-expected.json +0 -2
  121. package/test/resources/9999999/event/post_withSchema-callout-expected.json +3 -0
  122. package/test/resources/9999999/event/post_withSchema-expected.json +0 -2
  123. package/test/resources/9999999/event/put-callout-expected.json +3 -0
  124. package/test/resources/9999999/event/put-expected.json +0 -2
  125. package/test/resources/9999999/event/template-expected.json +0 -1
  126. package/test/resources/9999999/folder-deploy/Data Extensions/testExisting_folder.folder-meta.json +9 -0
  127. package/test/resources/9999999/importFile/get-dataImport-expected.json +1 -1
  128. package/test/resources/9999999/importFile/get-expected.json +4 -1
  129. package/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/audit/all/get-response-versionNumber=1.json +86 -0
  130. package/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/audit/all/get-response-versionNumber=2.json +101 -0
  131. package/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/audit/all/get-response-versionNumber=3.json +86 -0
  132. package/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/delete-response-versionNumber=1.txt +1 -0
  133. package/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/get-response-versionNumber=1.json +461 -0
  134. package/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/get-response-versionNumber=3.json +461 -0
  135. package/test/resources/9999999/interaction/v1/interactions/dsfdsafdsa-922c-4568-85a5-e5cc77efc3be/audit/all/get-response-versionNumber=1.json +38 -0
  136. package/test/resources/9999999/interaction/v1/interactions/dsfdsafdsa-922c-4568-85a5-e5cc77efc3be/audit/all/get-response-versionNumber=2.json +53 -0
  137. package/test/resources/9999999/interaction/v1/interactions/get-response.json +2 -2
  138. package/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Multistep/get-response-versionNumber=1.json +461 -0
  139. package/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Quicksend/get-response-versionNumber=1.json +253 -0
  140. package/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail/get-response-versionNumber=1.json +219 -0
  141. package/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail_notPublished/get-response-versionNumber=1.json +226 -0
  142. package/test/resources/9999999/interaction/v1/interactions/publishAsync/0175b971-71a3-4d8e-98ac-48121f3fbf4f/post-response-versionNumber=3.json +4 -0
  143. package/test/resources/9999999/journey/build-expected.json +0 -1
  144. package/test/resources/9999999/journey/create-transactionaEmail-publish-expected.json +0 -1
  145. package/test/resources/9999999/journey/get-multistep-expected.json +0 -4
  146. package/test/resources/9999999/journey/get-published-expected.json +0 -1
  147. package/test/resources/9999999/journey/get-quicksend-expected.json +0 -1
  148. package/test/resources/9999999/journey/get-quicksend-rcb-id-expected.json +0 -1
  149. package/test/resources/9999999/journey/get-quicksend-rcb-key-expected.json +0 -1
  150. package/test/resources/9999999/journey/get-quicksend-rcb-name-expected.json +0 -1
  151. package/test/resources/9999999/journey/get-transactionalEmail-expected.json +0 -1
  152. package/test/resources/9999999/journey/template-expected.json +0 -1
  153. package/test/resources/9999999/query/patch-expected.sql +1 -1
  154. package/test/resources/9999999/query/post-expected.sql +1 -1
  155. package/test/resources/9999999/script/patch-expected.ssjs +1 -0
  156. package/test/type.asset.test.js +123 -13
  157. package/test/type.automation.test.js +3 -1
  158. package/test/type.folder.test.js +12 -2
  159. package/test/type.journey.test.js +130 -1
  160. package/test/type.script.test.js +1 -0
  161. package/test/type.senderProfile.test.js +1 -0
  162. package/test/utils.js +2 -0
  163. package/types/mcdev.d.js +4 -0
  164. package/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN219,220,221,222,223,224,225,226,227,228,230,232.json +0 -32
  165. /package/test/resources/9999999/dataFolder/{+retrieve-QAA-response.xml → retrieve-QAA-response.xml} +0 -0
  166. /package/test/resources/9999999/interaction/v1/interactions/publishAsync/0175b971-71a3-4d8e-98ac-48121f3fbf4f/{post-response.json → post-response-versionNumber=1.json} +0 -0
@@ -101,8 +101,8 @@ class Folder extends MetadataType {
101
101
  idMap[id].Path = idMap[id].Name;
102
102
  }
103
103
  } else {
104
- Util.logger.warn(
105
- ` - Skipping folder ${idMap[id].Name} (${id}, type: ${idMap[id].ContentType}): Cannot find parent folder (${idMap[id].ParentFolder.ID})`
104
+ Util.logger.info(
105
+ ` skipping folder ${idMap[id].Name} (${id}, type: ${idMap[id].ContentType}): Cannot find parent folder (${idMap[id].ParentFolder.ID})`
106
106
  );
107
107
  }
108
108
  }
@@ -110,7 +110,7 @@ class Folder extends MetadataType {
110
110
  else if (idMap[id].Name !== '<ROOT>') {
111
111
  idMap[id].Path = '';
112
112
  Util.logger.warn(
113
- ` - Skipping folder ${idMap[id].Name} (${id}, type: ${idMap[id].ContentType}): Does not have a parent folder`
113
+ ` skipping folder ${idMap[id].Name} (${id}, type: ${idMap[id].ContentType}): Does not have a parent folder`
114
114
  );
115
115
  }
116
116
  }
@@ -220,21 +220,11 @@ class Folder extends MetadataType {
220
220
  let existingId;
221
221
  try {
222
222
  // perform a secondary check based on path
223
- existingId = cache.searchForField(
224
- 'folder',
225
- deployableMetadata.Path,
226
- 'Path',
227
- 'ID'
228
- );
229
- const cachedVersion = cache.getByKey(
230
- 'folder',
231
- cache.searchForField(
232
- 'folder',
233
- deployableMetadata.Path,
234
- 'Path',
235
- this.definition.keyField
236
- )
223
+
224
+ const cachedVersion = cache.getFolderByPath(
225
+ deployableMetadata.Path
237
226
  );
227
+ existingId = cachedVersion?.ID;
238
228
  if (
239
229
  existingId &&
240
230
  !this.hasChangedGeneric(
@@ -371,7 +361,7 @@ class Folder extends MetadataType {
371
361
  }
372
362
  const path = metadataEntry.Path;
373
363
  try {
374
- if (this.definition.deployFolderTypesRest.includes(metadataEntry.ContentType)) {
364
+ if (this.definition.deployFolderTypesEmailRest.includes(metadataEntry.ContentType)) {
375
365
  // * The SOAP endpoint for creating folders does not support folders for automations nor journeys. The Rest endpoint on the other hand errors out on certain characters in the folder names that are actually valid. We therefore only use Rest for the folder types that are not supported by SOAP.
376
366
  const restPayload = {
377
367
  parentCatId: metadataEntry.ParentFolder.ID,
@@ -379,7 +369,7 @@ class Folder extends MetadataType {
379
369
  catType: metadataEntry.ContentType,
380
370
  };
381
371
  const response = await super.createREST(restPayload, '/email/v1/category', true);
382
- if (response?.objectId) {
372
+ if (response?.categoryId) {
383
373
  // convert the response to the same format as the SOAP response
384
374
 
385
375
  // set the new folder ID
@@ -400,7 +390,48 @@ class Folder extends MetadataType {
400
390
  Util.logger.info(` - created folder: ${path}`);
401
391
  return returnObject;
402
392
  } else {
403
- throw new Error(response);
393
+ throw new Error(JSON.stringify(response));
394
+ }
395
+ } else if (
396
+ this.definition.deployFolderTypesAssetRest.includes(metadataEntry.ContentType)
397
+ ) {
398
+ // * The SOAP endpoint for creating folders does not support folders for automations nor journeys. The Rest endpoint on the other hand errors out on certain characters in the folder names that are actually valid. We therefore only use Rest for the folder types that are not supported by SOAP.
399
+ const restPayload = {
400
+ parentId: metadataEntry.ParentFolder.ID,
401
+ categoryType: metadataEntry.ContentType,
402
+ extendable: 1,
403
+ editable: 1,
404
+ name: metadataEntry.Name,
405
+ description: '',
406
+ };
407
+
408
+ const response = await super.createREST(
409
+ restPayload,
410
+ '/asset/v1/content/categories',
411
+ true
412
+ );
413
+ if (response?.id) {
414
+ // convert the response to the same format as the SOAP response
415
+
416
+ // set the new folder ID
417
+ metadataEntry.ID = response.id;
418
+ // set the client ID to ensure we can find the newly created folders as parents for folders created afterwards inside of it
419
+ metadataEntry.Client = {
420
+ ID: metadataEntry.Client?.ID || this.buObject.mid,
421
+ };
422
+ // the following is a bit of a hack to make the response look like the SOAP response; not sure if we actually need that anywhere like this --> future developers feel free to double check
423
+ const returnObject = {
424
+ Results: [
425
+ {
426
+ Object: metadataEntry,
427
+ },
428
+ ],
429
+ };
430
+
431
+ Util.logger.info(` - created folder: ${path}`);
432
+ return returnObject;
433
+ } else {
434
+ throw new Error(JSON.stringify(response));
404
435
  }
405
436
  } else {
406
437
  const response = await super.createSOAP(metadataEntry, true);
@@ -446,13 +477,54 @@ class Folder extends MetadataType {
446
477
  }
447
478
  const path = metadataEntry.Path;
448
479
  try {
449
- const response = await super.updateSOAP(metadataEntry, true);
450
- if (response.Results?.[0]?.StatusCode === 'OK') {
451
- response.Results[0].Object = metadataEntry;
452
- response.Results[0].Object.CustomerKey = metadataEntry.CustomerKey;
453
- delete response.Results[0].Object.$;
454
- Util.logger.info(` - updated folder: ${path}`);
455
- return response;
480
+ let response;
481
+ if (this.definition.deployFolderTypesAssetRest.includes(metadataEntry.ContentType)) {
482
+ // * The SOAP endpoint for creating folders does not support folders for automations nor journeys. The Rest endpoint on the other hand errors out on certain characters in the folder names that are actually valid. We therefore only use Rest for the folder types that are not supported by SOAP.
483
+ const restPayload = {
484
+ id: metadataEntry.ID,
485
+ parentId: metadataEntry.ParentFolder.ID,
486
+ // categoryType: metadataEntry.ContentType,
487
+ extendable: 1, // ?
488
+ editable: 1, // ?
489
+ name: metadataEntry.Name,
490
+ description: '',
491
+ };
492
+ response = await super.updateREST(
493
+ restPayload,
494
+ '/asset/v1/content/categories/' + metadataEntry.ID,
495
+ 'put',
496
+ true
497
+ );
498
+ if (response?.id) {
499
+ // convert the response to the same format as the SOAP response
500
+
501
+ // set the client ID to ensure we can find the newly created folders as parents for folders created afterwards inside of it
502
+ metadataEntry.Client = {
503
+ ID: metadataEntry.Client?.ID || this.buObject.mid,
504
+ };
505
+ // the following is a bit of a hack to make the response look like the SOAP response; not sure if we actually need that anywhere like this --> future developers feel free to double check
506
+ const returnObject = {
507
+ Results: [
508
+ {
509
+ Object: metadataEntry,
510
+ },
511
+ ],
512
+ };
513
+
514
+ Util.logger.info(` - updated folder: ${path}`);
515
+ return returnObject;
516
+ } else {
517
+ throw new Error(JSON.stringify(response));
518
+ }
519
+ } else {
520
+ response = await super.updateSOAP(metadataEntry, true);
521
+ if (response.Results?.[0]?.StatusCode === 'OK') {
522
+ response.Results[0].Object = metadataEntry;
523
+ response.Results[0].Object.CustomerKey = metadataEntry.CustomerKey;
524
+ delete response.Results[0].Object.$;
525
+ Util.logger.info(` - updated folder: ${path}`);
526
+ return response;
527
+ }
456
528
  }
457
529
  } catch (ex) {
458
530
  if (ex?.results) {
@@ -16,6 +16,7 @@ import cache from '../util/cache.js';
16
16
  * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj
17
17
  * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams
18
18
  * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap
19
+ * @typedef {import('../../types/mcdev.d.js').SDKError} SDKError
19
20
  */
20
21
 
21
22
  /**
@@ -85,6 +86,38 @@ class ImportFile extends MetadataType {
85
86
  );
86
87
  }
87
88
 
89
+ /**
90
+ * helper for {@link MetadataType.retrieveRESTcollection}
91
+ *
92
+ * @param {SDKError} ex exception
93
+ * @param {string} key id or key of item
94
+ * @param {string} url url to call for retry
95
+ * @returns {Promise.<any>} can return retry-result
96
+ */
97
+ static async handleRESTErrors(ex, key, url) {
98
+ try {
99
+ if (ex.code == 'ERR_BAD_RESPONSE') {
100
+ // one more retry; it's a rare case but retrying again should solve the issue gracefully
101
+ Util.logger.info(
102
+ ` - Connection problem (Code: ${ex.code}). Retrying once${
103
+ ex.endpoint
104
+ ? Util.getGrayMsg(
105
+ ' - ' + ex.endpoint.split('rest.marketingcloudapis.com')[1]
106
+ )
107
+ : ''
108
+ }`
109
+ );
110
+ Util.logger.errorStack(ex);
111
+ return await this.client.rest.get(url);
112
+ }
113
+ } catch {
114
+ // no extra action needed, handled below
115
+ }
116
+ // if we do get here, we should log the error and continue instead of failing to download all automations
117
+ Util.logger.error(` ☇ skipping ${this.definition.type} ${key}: ${ex.message} ${ex.code}`);
118
+ return null;
119
+ }
120
+
88
121
  /**
89
122
  * Retrieves import definition metadata for caching
90
123
  *
@@ -100,12 +133,14 @@ class ImportFile extends MetadataType {
100
133
  /**
101
134
  * Retrieve a specific Import Definition by Name
102
135
  *
136
+ * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version.
103
137
  * @param {string} templateDir Directory where retrieved metadata directory will be saved
104
138
  * @param {string} name name of the metadata file
105
139
  * @param {TemplateMap} templateVariables variables to be replaced in the metadata
106
140
  * @returns {Promise.<MetadataTypeItemObj>} Promise
107
141
  */
108
142
  static async retrieveAsTemplate(templateDir, name, templateVariables) {
143
+ Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`);
109
144
  // using '?$filter=name%20eq%20' + encodeURIComponent(name) would also work but that just retrieves more data for no reason
110
145
  const cache = await this.retrieveForCache(null, null, 'name:' + name);
111
146
  const metadataArr = Object.values(cache?.metadata);
@@ -228,16 +263,21 @@ class ImportFile extends MetadataType {
228
263
  * @returns {Promise.<MetadataTypeItem>} Promise
229
264
  */
230
265
  static async preDeployTasks(metadata) {
231
- const fileLocation = cache.getByKey('fileLocation', metadata.source?.r__fileLocation_name);
232
- if (!fileLocation) {
233
- throw new Error(
234
- `fileLocation ${metadata.source?.r__fileLocation_name} not found in cache`
266
+ if (metadata.source?.r__fileLocation_name) {
267
+ const fileLocation = cache.getByKey(
268
+ 'fileLocation',
269
+ metadata.source?.r__fileLocation_name
235
270
  );
236
- }
271
+ if (!fileLocation) {
272
+ throw new Error(
273
+ `fileLocation ${metadata.source?.r__fileLocation_name} not found in cache`
274
+ );
275
+ }
237
276
 
238
- metadata.fileTransferLocationId = fileLocation.id;
239
- metadata.fileTransferLocationTypeId = fileLocation.locationTypeId;
240
- delete metadata.source.r__fileLocation_name;
277
+ metadata.fileTransferLocationId = fileLocation.id;
278
+ metadata.fileTransferLocationTypeId = fileLocation.locationTypeId;
279
+ delete metadata.source.r__fileLocation_name;
280
+ }
241
281
 
242
282
  switch (metadata.destination.c__type) {
243
283
  case 'DataExtension': {
@@ -332,18 +372,14 @@ class ImportFile extends MetadataType {
332
372
  delete metadata.source.r__dataExtension_key;
333
373
  }
334
374
 
335
- Util.logger.debug(
336
- ` - importFile ${metadata[this.definition.keyField]}: Import Destination Type ${
337
- metadata.destination.c__type
338
- } not fully supported. Deploy might fail.`
375
+ throw new Error(
376
+ `Import Destination Type ${metadata.destination.c__type} not fully supported.`
339
377
  );
340
- break;
341
378
  }
342
379
  default: {
343
- Util.logger.debug(
344
- ` - importFile ${metadata[this.definition.keyField]}: Import Destination Type ${
345
- metadata.destination.c__type
346
- } not fully supported. Deploy might fail.`
380
+ // e.g. WhatsApp
381
+ throw new Error(
382
+ `Import Destination Type ${metadata.destination.c__type} not fully supported.`
347
383
  );
348
384
  }
349
385
  }
@@ -381,18 +417,24 @@ class ImportFile extends MetadataType {
381
417
  // destination.c__type SMS & DataExtension both set fileNamingPattern to _CustomObject and they both define a DE as source
382
418
  metadata.source = {
383
419
  c__type:
384
- metadata.fileNamingPattern === '_CustomObject' ? 'DataExtension' : 'File Location',
420
+ metadata.fileNamingPattern === '_CustomObject' ||
421
+ metadata.fileSpec === '_CustomObject'
422
+ ? 'DataExtension'
423
+ : 'File Location',
385
424
  };
386
- try {
387
- metadata.source.r__fileLocation_name = cache.searchForField(
388
- 'fileLocation',
389
- metadata.fileTransferLocationId,
390
- 'id',
391
- 'name'
392
- );
393
- delete metadata.fileTransferLocationId;
394
- } catch (ex) {
395
- Util.logger.warn(` - importFile ${metadata.customerKey}: ${ex.message}`);
425
+
426
+ if (metadata.fileTransferLocationId !== '00000000-0000-0000-0000-000000000000') {
427
+ try {
428
+ metadata.source.r__fileLocation_name = cache.searchForField(
429
+ 'fileLocation',
430
+ metadata.fileTransferLocationId,
431
+ 'id',
432
+ 'name'
433
+ );
434
+ delete metadata.fileTransferLocationId;
435
+ } catch (ex) {
436
+ Util.logger.warn(` - importFile ${metadata.customerKey}: ${ex.message}`);
437
+ }
396
438
  }
397
439
 
398
440
  switch (metadata.destination.c__type) {
@@ -481,6 +523,27 @@ class ImportFile extends MetadataType {
481
523
 
482
524
  break;
483
525
  }
526
+ case 'WhatsApp': {
527
+ if (
528
+ metadata.source.c__type === 'DataExtension' &&
529
+ metadata.sourceCustomObjectId !== ''
530
+ ) {
531
+ // only happens for dataimport activities (summer24 release)
532
+ try {
533
+ metadata.source.r__dataExtension_key = cache.searchForField(
534
+ 'dataExtension',
535
+ metadata.sourceCustomObjectId,
536
+ 'ObjectID',
537
+ 'CustomerKey'
538
+ );
539
+ delete metadata.sourceCustomObjectId;
540
+ delete metadata.sourceDataExtensionName;
541
+ } catch (ex) {
542
+ Util.logger.warn(` - importFile ${metadata.customerKey}: ${ex.message}`);
543
+ }
544
+ }
545
+ break;
546
+ }
484
547
  default: {
485
548
  Util.logger.debug(
486
549
  ` - importFile ${metadata.customerKey}: Destination Type ${metadata.destinationObjectTypeId} not fully supported. Deploy might fail.`
@@ -489,7 +552,7 @@ class ImportFile extends MetadataType {
489
552
  }
490
553
  delete metadata.destinationObjectTypeId;
491
554
 
492
- if (metadata.blankFileProcessingType) {
555
+ if (metadata.blankFileProcessingType !== undefined) {
493
556
  // omit this if not set
494
557
  metadata.c__blankFileProcessing = Util.inverseGet(
495
558
  this.definition.blankFileProcessingTypeMapping,