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
package/lib/Deployer.js CHANGED
@@ -503,6 +503,9 @@ class Deployer {
503
503
  ) {
504
504
  contentType = 'triggered_send_journeybuilder';
505
505
  }
506
+ if (metadataType === 'asset' && folder.startsWith('CloudPages/')) {
507
+ contentType = 'cloudpages';
508
+ }
506
509
  folderMetadata[`on-the-fly-${i}`] = {
507
510
  Path: folder,
508
511
  Name: folder.split('/').pop(),
package/lib/Retriever.js CHANGED
@@ -181,14 +181,20 @@ class Retriever {
181
181
  cache.mergeMetadata(type, result_i.metadata);
182
182
  }
183
183
  }
184
- if (metadataTypes.includes(type) || metadataTypes.includes(type)) {
184
+ if (
185
+ metadataTypes.includes(type) ||
186
+ metadataTypes.some((el) => el.startsWith(type + '-'))
187
+ ) {
185
188
  retrieveChangelog[type] = result
186
189
  .filter((el) => !!el)
187
190
  .map((element) => element.metadata);
188
191
  }
189
192
  } else {
190
193
  cache.mergeMetadata(type, result.metadata);
191
- if (metadataTypes.includes(type) || metadataTypes.includes(type)) {
194
+ if (
195
+ metadataTypes.includes(type) ||
196
+ metadataTypes.some((el) => el.startsWith(type + '-'))
197
+ ) {
192
198
  retrieveChangelog[type] = result.metadata;
193
199
  }
194
200
  }
package/lib/cli.js CHANGED
@@ -1166,6 +1166,35 @@ yargs(hideBin(process.argv))
1166
1166
  }
1167
1167
  }
1168
1168
  )
1169
+ .command(
1170
+ ['audit <BU>'],
1171
+ 'shows audit log for the entity (journey etc.)',
1172
+ (yargs) =>
1173
+ yargs
1174
+ .positional('BU', {
1175
+ type: 'string',
1176
+ describe: 'the business unit where to start an item',
1177
+ })
1178
+ .option('metadata', {
1179
+ type: 'string',
1180
+ array: true,
1181
+ alias: 'm',
1182
+ group: 'Options for audit:',
1183
+ describe: 'type or type:key or type:i:id or type:n:name to fix',
1184
+ demandOption: true,
1185
+ })
1186
+ .option('like', {
1187
+ type: 'string',
1188
+ group: 'Options for audit:',
1189
+ describe:
1190
+ 'filter metadata components (can include % as wildcard or _ for a single character)',
1191
+ }),
1192
+ (argv) => {
1193
+ Mcdev.setOptions(argv);
1194
+ const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata);
1195
+ Mcdev.audit(argv.BU, typeKeyCombo);
1196
+ }
1197
+ )
1169
1198
  .command(
1170
1199
  ['fixKeys <BU> [TYPE] [KEY]', 'fx'],
1171
1200
  'changes the key of the items to match the name',
package/lib/index.js CHANGED
@@ -410,17 +410,7 @@ class Mcdev {
410
410
  cache.initCache(buObject);
411
411
  cred = buObject.credential;
412
412
  bu = buObject.businessUnit;
413
- // clean up old folders after types were renamed
414
- // TODO: Remove renamedTypes-logic 6 months after version 5 release
415
- const renamedTypes = {
416
- attributeSet: 'setDefinition',
417
- emailSend: 'emailSendDefinition',
418
- event: 'eventDefinition',
419
- fileLocation: 'ftpLocation',
420
- journey: 'interaction',
421
- triggeredSend: 'triggeredSendDefinition',
422
- user: 'accountUser',
423
- };
413
+
424
414
  Util.logger.info('');
425
415
  Util.logger.info(`:: Retrieving ${cred}/${bu}`);
426
416
  const retrieveTypesArr = [];
@@ -444,23 +434,11 @@ class Mcdev {
444
434
  retrieveTypesArr.push(type);
445
435
  }
446
436
  const areKeySet = Array.isArray(selectedTypesArr)
447
- ? keys
448
- : Object.values(selectedTypesArr).filter(Boolean).length;
437
+ ? !!keys
438
+ : selectedTypesArr[selectedType] !== null;
449
439
  if (!areKeySet) {
450
440
  // dont delete directories if we are just re-retrieving a single file
451
441
  await File.remove(File.normalizePath(removePathArr));
452
- // clean up old folders after types were renamed
453
- // TODO: Remove this with version 5.0.0
454
- if (renamedTypes[type]) {
455
- await File.remove(
456
- File.normalizePath([
457
- properties.directories.retrieve,
458
- cred,
459
- bu,
460
- renamedTypes[type],
461
- ])
462
- );
463
- }
464
442
  }
465
443
  }
466
444
  }
@@ -877,6 +855,7 @@ class Mcdev {
877
855
  /**
878
856
  * Retrieve a specific metadata file and templatise.
879
857
  *
858
+ * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version.
880
859
  * @param {string} businessUnit references credentials from properties.json
881
860
  * @param {string} selectedType supported metadata type
882
861
  * @param {string[]} name name of the metadata
@@ -885,9 +864,7 @@ class Mcdev {
885
864
  */
886
865
  static async retrieveAsTemplate(businessUnit, selectedType, name, market) {
887
866
  Util.startLogger();
888
- Util.logger.warn(
889
- 'mcdev:: [DEPRECATED] Retrieve as Template [DEPRECATED] - use "retrieve" + "buildTemplate" instead'
890
- );
867
+ Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`);
891
868
  const properties = await config.getProperties();
892
869
  if (!properties) {
893
870
  return;
@@ -1555,6 +1532,17 @@ class Mcdev {
1555
1532
  return this.#runMethod('stop', businessUnit, selectedTypes, keys);
1556
1533
  }
1557
1534
 
1535
+ /**
1536
+ * stop an item
1537
+ *
1538
+ * @param {string} businessUnit name of BU
1539
+ * @param {TypeKeyCombo} selectedTypes limit to given metadata types
1540
+ * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys
1541
+ */
1542
+ static async audit(businessUnit, selectedTypes) {
1543
+ return this.#runMethod('audit', businessUnit, selectedTypes);
1544
+ }
1545
+
1558
1546
  /**
1559
1547
  * Updates the key to match the name field
1560
1548
  *
@@ -1738,7 +1726,7 @@ class Mcdev {
1738
1726
  /**
1739
1727
  * run a method across BUs
1740
1728
  *
1741
- * @param {'schedule'|'execute'|'pause'|'stop'|'publish'|'validate'|'fixKeys'|'replaceCbReference'|'refresh'} methodName what to run
1729
+ * @param {'schedule'|'execute'|'pause'|'stop'|'publish'|'validate'|'fixKeys'|'replaceCbReference'|'refresh'|'audit'} methodName what to run
1742
1730
  * @param {string} businessUnit name of BU
1743
1731
  * @param {string[] | TypeKeyCombo} [selectedTypes] limit to given metadata types
1744
1732
  * @param {string[]} [keys] customerkey of the metadata
@@ -1827,6 +1815,14 @@ class Mcdev {
1827
1815
  checkMetadataSupport = true;
1828
1816
  break;
1829
1817
  }
1818
+ case 'audit': {
1819
+ lang_past = 'audited';
1820
+ lang_present = 'auditing';
1821
+ requireType = true;
1822
+ requireKeyOrLike = true;
1823
+ checkMetadataSupport = true;
1824
+ break;
1825
+ }
1830
1826
  }
1831
1827
 
1832
1828
  /** @typedef {string[]} */
@@ -1987,7 +1983,7 @@ class Mcdev {
1987
1983
  /**
1988
1984
  * helper for Mcdev.#runMethod
1989
1985
  *
1990
- * @param {'schedule'|'execute'|'pause'|'stop'|'publish'|'validate'|'fixKeys'|'replaceCbReference'|'refresh'} methodName what to run
1986
+ * @param {'schedule'|'execute'|'pause'|'stop'|'publish'|'validate'|'fixKeys'|'replaceCbReference'|'refresh'|'audit'} methodName what to run
1991
1987
  * @param {string} cred name of Credential
1992
1988
  * @param {string} bu name of BU
1993
1989
  * @param {string} [type] limit execution to given metadata type
@@ -2097,7 +2093,7 @@ class Mcdev {
2097
2093
  for (const originalKey in metadataMap) {
2098
2094
  // hide postRetrieveOutput
2099
2095
  Util.setLoggingLevel({ silent: true });
2100
- metadataMap[originalKey] = MetadataTypeInfo[selectedType].postRetrieveTasks(
2096
+ metadataMap[originalKey] = await MetadataTypeInfo[selectedType].postRetrieveTasks(
2101
2097
  metadataMap[originalKey]
2102
2098
  );
2103
2099
  // reactivate logging
@@ -134,6 +134,7 @@ class Asset extends MetadataType {
134
134
  /**
135
135
  * Retrieves asset metadata for templating
136
136
  *
137
+ * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version.
137
138
  * @param {string} templateDir Directory where retrieved metadata directory will be saved
138
139
  * @param {string} name name of the metadata file
139
140
  * @param {TemplateMap} templateVariables variables to be replaced in the metadata
@@ -141,6 +142,7 @@ class Asset extends MetadataType {
141
142
  * @returns {Promise.<{metadata: AssetItem, type: string}>} Promise
142
143
  */
143
144
  static async retrieveAsTemplate(templateDir, name, templateVariables, selectedSubType) {
145
+ Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`);
144
146
  const items = [];
145
147
  const subTypes = selectedSubType ? [selectedSubType] : this._getSubTypes();
146
148
  await File.initPrettier();
@@ -410,6 +412,9 @@ class Asset extends MetadataType {
410
412
  'availableViews',
411
413
  'data',
412
414
  'tags',
415
+
416
+ 'meta',
417
+ 'content',
413
418
  ];
414
419
  }
415
420
 
@@ -502,7 +507,7 @@ class Asset extends MetadataType {
502
507
  await this.requestAndSaveExtended(items, subType, retrieveDir, templateVariables);
503
508
  }
504
509
  // always show the summary even if we already had the progress bar in the console
505
- Util.logger.info(` Downloaded asset-${subType}: ${items.length}`);
510
+ Util.logger.info(` Downloaded asset${subType ? '-' + subType : ''}: ${items.length}`);
506
511
  }
507
512
 
508
513
  return items;
@@ -766,6 +771,44 @@ class Asset extends MetadataType {
766
771
  }
767
772
  }
768
773
 
774
+ // get asset-asset
775
+ try {
776
+ if (metadata.meta?.thumbnailRefAssetId) {
777
+ // cloudpages', 'landingpage', 'microsite', 'interactivecontent'
778
+ metadata.meta.r__asset_key = cache.searchForField(
779
+ 'asset',
780
+ metadata.meta?.thumbnailRefAssetId,
781
+ 'id',
782
+ 'customerKey'
783
+ );
784
+ delete metadata.meta.thumbnailRefAssetId;
785
+ }
786
+ } catch {
787
+ Util.logger.warn(
788
+ ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${
789
+ metadata[this.definition.keyField]
790
+ }): Could not find associated cloudpage content with id (${metadata.meta.thumbnailRefAssetId})`
791
+ );
792
+ }
793
+ if (
794
+ ['landingpage', 'microsite', 'interactivecontent'].includes(metadata.assetType.name) &&
795
+ typeof metadata.content === 'string'
796
+ ) {
797
+ // cloudpages', 'landingpage', 'microsite', 'interactivecontent'
798
+ metadata.content = JSON.parse(metadata.content);
799
+ }
800
+
801
+ if (typeof metadata.data?.site?.content === 'string') {
802
+ // for all xx-coderesource types
803
+ metadata.data.site.content = JSON.parse(metadata.data.site.content);
804
+ }
805
+
806
+ if (metadata.meta?.cloudPages) {
807
+ metadata.meta.cloudPages.c__published = metadata.meta.cloudPages.publishDate
808
+ ? true
809
+ : false;
810
+ }
811
+
769
812
  // extract HTML for selected subtypes and convert payload for easier processing in MetadataType.saveResults()
770
813
  return this._extractCode(metadata);
771
814
  }
@@ -858,14 +901,22 @@ class Asset extends MetadataType {
858
901
  // folder
859
902
  this.setFolderId(metadata);
860
903
 
861
- if (
862
- metadata.assetType.name === 'webpage' &&
863
- !cache.getByKey(this.definition.type, metadata[this.definition.keyField])
864
- ) {
865
- // we are attempting to CREATE a cloudpage asset which needs to be prevented.
866
- throw new Error(
867
- 'CloudPages cannot be created via mcdev. Please create it via the UI first, then change its key to the value required by you, and finally, re-run this deployment.'
868
- );
904
+ if (!cache.getByKey(this.definition.type, metadata[this.definition.keyField])) {
905
+ if (metadata.assetType.name === 'webpage') {
906
+ // we are attempting to CREATE a cloudpage asset which needs to be prevented.
907
+ throw new Error(
908
+ 'CloudPage content cannot be created via mcdev. Please create it via the UI first, then you can update the content or key.'
909
+ );
910
+ }
911
+ if (
912
+ this.definition.extendedSubTypes.cloudpage.includes(metadata.assetType.name) ||
913
+ this.definition.extendedSubTypes.coderesource.includes(metadata.assetType.name)
914
+ ) {
915
+ // if we do create those, we get the error "Asset <id> not found" because the internal endpoint internal/v2/cloudpages/sites won't find it.
916
+ throw new Error(
917
+ 'CloudPage assets cannot be created via mcdev. Please create it via the UI first, then you can update the content or key.'
918
+ );
919
+ }
869
920
  }
870
921
 
871
922
  // template-based emails
@@ -901,6 +952,33 @@ class Asset extends MetadataType {
901
952
  delete metadata.views.html.template.r__asset_key;
902
953
  }
903
954
 
955
+ if (metadata.meta?.r__asset_key) {
956
+ // cloudpages: 'landingpage', 'microsite', 'interactivecontent'
957
+ // get asset-asset
958
+ metadata.meta.thumbnailRefAssetId = cache.searchForField(
959
+ 'asset',
960
+ metadata.meta.r__asset_key,
961
+ 'customerKey',
962
+ 'id'
963
+ );
964
+ delete metadata.meta.r__asset_key;
965
+ }
966
+ if (metadata.meta?.cloudPages?.c__published) {
967
+ // TODO: removal should be done via asset.definition instead
968
+ delete metadata.meta.cloudPages.c__published;
969
+ }
970
+ if (
971
+ ['landingpage', 'microsite', 'interactivecontent'].includes(metadata.assetType.name) &&
972
+ typeof metadata.content === 'object'
973
+ ) {
974
+ // cloudpages: 'landingpage', 'microsite', 'interactivecontent'
975
+ metadata.content = JSON.stringify(metadata.content);
976
+ }
977
+ if (typeof metadata.data?.site?.content === 'object') {
978
+ // coderesource: for all xx-coderesource types
979
+ metadata.data.site.content = JSON.stringify(metadata.data.site.content);
980
+ }
981
+
904
982
  // restore asset type id which is needed for deploy
905
983
  metadata.assetType.id = this.definition.typeMapping[metadata.assetType.name];
906
984
 
@@ -1166,13 +1244,33 @@ class Asset extends MetadataType {
1166
1244
  */
1167
1245
  static setFolderPath(metadata, hideWarning = false) {
1168
1246
  try {
1169
- metadata.r__folder_Path = cache.searchForField(
1170
- 'folder',
1171
- metadata.category.id,
1172
- 'ID',
1173
- 'Path'
1174
- );
1175
- delete metadata.category;
1247
+ // we get folders type "asset" from EID and MID to accomodate for shared assets. That however is an issue if we are retrieving a local asset with the same folder.
1248
+ const folderId = metadata.category.id;
1249
+ const folderMap = cache.getCache().folder;
1250
+ if (!folderMap) {
1251
+ throw new Error('No folders found in cache');
1252
+ }
1253
+ const potentialFolders = [];
1254
+ for (const folder of Object.values(folderMap)) {
1255
+ if (folder.ID === folderId) {
1256
+ if (
1257
+ (metadata.memberId && metadata.memberId === folder?.Client?.ID) ||
1258
+ folder?.Client?.ID === this.buObject.mid
1259
+ ) {
1260
+ metadata.r__folder_Path = folder.Path;
1261
+ delete metadata.category;
1262
+ return;
1263
+ } else {
1264
+ potentialFolders.push(folder);
1265
+ }
1266
+ }
1267
+ }
1268
+ if (potentialFolders.length >= 1) {
1269
+ metadata.r__folder_Path = potentialFolders[0].Path;
1270
+ delete metadata.category;
1271
+ } else {
1272
+ throw new Error(`No folders found with ID ${folderId}`);
1273
+ }
1176
1274
  } catch (ex) {
1177
1275
  if (!hideWarning) {
1178
1276
  Util.logger.warn(
@@ -1575,6 +1673,12 @@ class Asset extends MetadataType {
1575
1673
 
1576
1674
  break;
1577
1675
  }
1676
+ case 'jscoderesource': // coderesource
1677
+ case 'csscoderesource': // coderesource
1678
+ case 'jsoncoderesource': // coderesource
1679
+ case 'rsscoderesource': // coderesource
1680
+ case 'textcoderesource': // coderesource
1681
+ case 'xmlcoderesource': // coderesource
1578
1682
  case 'buttonblock': // block - Button Block
1579
1683
  case 'freeformblock': // block
1580
1684
  case 'htmlblock': // block
@@ -1587,7 +1691,17 @@ class Asset extends MetadataType {
1587
1691
  // metadata.content
1588
1692
  subDirArr = [this.definition.type, subType];
1589
1693
  readDirArr = [deployDir, ...subDirArr];
1590
- const fileExtArr = ['html', 'ssjs', 'amp'];
1694
+ const fileExtArr = [
1695
+ 'html',
1696
+ 'ssjs',
1697
+ 'amp',
1698
+ 'js',
1699
+ 'css',
1700
+ 'rss',
1701
+ 'txt',
1702
+ 'xml',
1703
+ 'jsonc',
1704
+ ];
1591
1705
  for (const ext of fileExtArr) {
1592
1706
  if (
1593
1707
  await File.pathExists(
@@ -1858,6 +1972,30 @@ class Asset extends MetadataType {
1858
1972
  subFolder: [customerKey],
1859
1973
  };
1860
1974
  }
1975
+ case 'jscoderesource': // coderesource
1976
+ case 'csscoderesource': // coderesource
1977
+ case 'jsoncoderesource': // coderesource
1978
+ case 'rsscoderesource': // coderesource
1979
+ case 'textcoderesource': // coderesource
1980
+ case 'xmlcoderesource': {
1981
+ // metadata.content
1982
+ const content = metadata?.content;
1983
+ const fileExt = metadata.assetType.name
1984
+ .replace('coderesource', '')
1985
+ .replace('text', 'txt')
1986
+ .replace('json', 'jsonc');
1987
+
1988
+ if (content?.length) {
1989
+ codeArr.push({
1990
+ subFolder: null,
1991
+ fileName: customerKey,
1992
+ fileExt: fileExt,
1993
+ content: content,
1994
+ });
1995
+ delete metadata.content;
1996
+ }
1997
+ return { json: metadata, codeArr: codeArr, subFolder: null };
1998
+ }
1861
1999
  case 'buttonblock': // block-buttonblock
1862
2000
  case 'freeformblock': // block-freeformblock
1863
2001
  case 'htmlblock': // block-htmlblock