mcdev 5.1.0 → 5.3.0

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 (256) hide show
  1. package/.eslintrc.json +4 -4
  2. package/.fork/custom-commands.json +12 -0
  3. package/.github/ISSUE_TEMPLATE/bug.yml +2 -0
  4. package/.github/PULL_REQUEST_TEMPLATE/pr_template_release.md +19 -0
  5. package/.github/PULL_REQUEST_TEMPLATE.md +2 -2
  6. package/.github/workflows/coverage-develop-branch.yml +0 -2
  7. package/.github/workflows/coverage-main-branch.yml +0 -2
  8. package/.github/workflows/coverage.yml +0 -2
  9. package/.husky/post-checkout +1 -0
  10. package/.husky/post-merge +1 -0
  11. package/.vscode/extensions.json +4 -0
  12. package/docs/dist/documentation.md +1034 -296
  13. package/lib/Deployer.js +25 -25
  14. package/lib/MetadataTypeDefinitions.js +2 -1
  15. package/lib/MetadataTypeInfo.js +2 -1
  16. package/lib/Retriever.js +1 -1
  17. package/lib/cli.js +165 -10
  18. package/lib/index.js +398 -95
  19. package/lib/metadataTypes/Asset.js +10 -11
  20. package/lib/metadataTypes/AttributeGroup.js +76 -2
  21. package/lib/metadataTypes/AttributeSet.js +367 -0
  22. package/lib/metadataTypes/Automation.js +483 -137
  23. package/lib/metadataTypes/DataExtension.js +465 -68
  24. package/lib/metadataTypes/DataExtensionField.js +31 -14
  25. package/lib/metadataTypes/Event.js +2 -3
  26. package/lib/metadataTypes/Folder.js +1 -1
  27. package/lib/metadataTypes/Journey.js +13 -7
  28. package/lib/metadataTypes/MetadataType.js +212 -54
  29. package/lib/metadataTypes/MobileKeyword.js +9 -9
  30. package/lib/metadataTypes/MobileMessage.js +5 -5
  31. package/lib/metadataTypes/Query.js +26 -10
  32. package/lib/metadataTypes/Script.js +3 -3
  33. package/lib/metadataTypes/TransactionalEmail.js +94 -17
  34. package/lib/metadataTypes/TransactionalMessage.js +3 -2
  35. package/lib/metadataTypes/TransactionalSMS.js +5 -5
  36. package/lib/metadataTypes/TriggeredSend.js +25 -50
  37. package/lib/metadataTypes/User.js +7 -4
  38. package/lib/metadataTypes/Verification.js +230 -0
  39. package/lib/metadataTypes/definitions/AttributeGroup.definition.js +119 -108
  40. package/lib/metadataTypes/definitions/{SetDefinition.definition.js → AttributeSet.definition.js} +123 -43
  41. package/lib/metadataTypes/definitions/Automation.definition.js +23 -15
  42. package/lib/metadataTypes/definitions/ImportFile.definition.js +36 -6
  43. package/lib/metadataTypes/definitions/TransactionalEmail.definition.js +19 -1
  44. package/lib/metadataTypes/definitions/TriggeredSend.definition.js +1 -0
  45. package/lib/metadataTypes/definitions/Verification.definition.js +88 -0
  46. package/lib/util/cache.js +9 -4
  47. package/lib/util/cli.js +40 -0
  48. package/lib/util/file.js +2 -2
  49. package/lib/util/init.js +84 -0
  50. package/lib/util/util.js +121 -13
  51. package/package.json +13 -13
  52. package/test/mockRoot/.mcdevrc.json +1 -1
  53. package/test/mockRoot/deploy/testInstance/_ParentBU_/dataExtension/testExisting_dataExtensionShared.dataExtension-meta.json +59 -0
  54. package/test/mockRoot/deploy/testInstance/_ParentBU_/dataExtension/testNew_dataExtensionShared.dataExtension-meta.json +23 -0
  55. package/test/mockRoot/deploy/testInstance/testBU/automation/testExisting_automation.automation-meta.json +1 -2
  56. package/test/mockRoot/deploy/testInstance/testBU/automation/testNew_automation.automation-meta.json +9 -6
  57. package/test/mockRoot/deploy/testInstance/testBU/dataExtension/testExisting_dataExtension.dataExtension-meta.json +1 -0
  58. package/test/mockRoot/deploy/testInstance/testBU/dataExtract/testExisting_dataExtract.dataExtract-meta.json +35 -0
  59. package/test/mockRoot/deploy/testInstance/testBU/dataExtract/testNew_dataExtract.dataExtract-meta.json +35 -0
  60. package/test/mockRoot/deploy/testInstance/testBU/fileTransfer/testExisting_fileTransfer.fileTransfer-meta.json +17 -0
  61. package/test/mockRoot/deploy/testInstance/testBU/fileTransfer/testNew_fileTransfer.fileTransfer-meta.json +17 -0
  62. package/test/mockRoot/deploy/testInstance/testBU/importFile/testExisting_importFile.importFile-meta.json +29 -0
  63. package/test/mockRoot/deploy/testInstance/testBU/importFile/testNew_importFile.importFile-meta.json +29 -0
  64. package/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query_fixKeys.query-meta.json +11 -0
  65. package/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query_fixKeys.query-meta.sql +6 -0
  66. package/test/mockRoot/deploy/testInstance/testBU/script/testExisting_script.script-meta.json +6 -0
  67. package/test/mockRoot/deploy/testInstance/testBU/script/testExisting_script.script-meta.ssjs +1 -0
  68. package/test/mockRoot/deploy/testInstance/testBU/script/testNew_script.script-meta.json +6 -0
  69. package/test/mockRoot/deploy/testInstance/testBU/script/testNew_script.script-meta.ssjs +1 -0
  70. package/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json +3 -4
  71. package/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testNew_temail.transactionalEmail-meta.json +1 -6
  72. package/test/mockRoot/deploy/testInstance/testBU/triggeredSend/testExisting_triggeredSend.triggeredSend-meta.json +29 -0
  73. package/test/mockRoot/deploy/testInstance/testBU/triggeredSend/testNew_triggeredSend.triggeredSend-meta.json +29 -0
  74. package/test/mockRoot/deploy/testInstance/testBU/verification/testExisting_39f6a488-20eb-4ba0-b0b9.verification-meta.json +11 -0
  75. package/test/mockRoot/deploy/testInstance/testBU/verification/testNew_39f6a488-20eb-4ba0-b0b9.verification-meta.json +11 -0
  76. package/test/resourceFactory.js +77 -12
  77. package/test/resources/1111111/accountUser/retrieve-ActiveFlag=falseANDCustomerKey=testExisting_userANDEmaillike@-response.xml +27 -0
  78. package/test/resources/1111111/accountUser/retrieve-ActiveFlag=falseANDEmaillike@-response.xml +156 -0
  79. package/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDEmailisNullORNamelikeapp userANDMustChangePassword=false-response.xml +87 -0
  80. package/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDEmaillike@-response.xml +156 -0
  81. package/test/resources/1111111/accountUser/retrieve-CustomerKey=testExisting_userANDActiveFlag=trueANDEmailisNullORNamelikeapp userANDMustChangePassword=false-response.xml +27 -0
  82. package/test/resources/1111111/accountUserAccount/retrieve-AccountUser.AccountUserID=700301950-response.xml +60 -0
  83. package/test/resources/1111111/data/v1/customobjectdata/key/testExisting_dataExtensionShared/rowset/get-response.json +13 -0
  84. package/test/resources/1111111/dataExtension/create-expected.json +23 -0
  85. package/test/resources/1111111/dataExtension/create-response.xml +59 -0
  86. package/test/resources/1111111/dataExtension/retrieve-expected.json +55 -0
  87. package/test/resources/1111111/dataExtension/retrieve-expected.md +18 -0
  88. package/test/resources/1111111/dataExtension/retrieve-response.xml +27 -1
  89. package/test/resources/1111111/dataExtension/update-expected.json +55 -0
  90. package/test/resources/1111111/dataExtension/update-response.xml +57 -0
  91. package/test/resources/1111111/dataExtensionField/retrieve-CustomerKey=[testExisting_dataExtensionShared].[TriggerUpdate_randomNumber_]-response.xml +45 -0
  92. package/test/resources/1111111/dataExtensionField/retrieve-DataExtension.CustomerKey=testExisting_dataExtensionShared-response.xml +98 -0
  93. package/test/resources/1111111/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_dataExtensionSharedORDataExtension.CustomerKey=testExisting_dataExtensionShared-response.xml +98 -0
  94. package/test/resources/1111111/dataExtensionField/retrieve-response.xml +98 -0
  95. package/test/resources/1111111/dataExtensionTemplate/retrieve-response.xml +303 -0
  96. package/test/resources/1111111/dataFolder/retrieve-ContentType=synchronizeddataextensionORContentType=shared_salesforcedataextensionORContentType=shared_dataextensionORContentType=shared_dataORContentType=salesforcedataextensionORContentType=dataextensionORContentType=hidden-response.xml +387 -0
  97. package/test/resources/1111111/dataFolder/retrieve-response.xml +353 -9
  98. package/test/resources/1111111/user/retrieve-expected.md +4 -2
  99. package/test/resources/9999999/attributeGroup/retrieve-expected.json +25 -0
  100. package/test/resources/9999999/attributeSet/retrieve-expected.json +143 -0
  101. package/test/resources/9999999/automation/build-expected.json +5 -2
  102. package/test/resources/9999999/automation/create-expected.json +11 -8
  103. package/test/resources/9999999/automation/create-testNew_automation-expected.md +5 -4
  104. package/test/resources/9999999/automation/patch_fixKeys-pause-expected.json +44 -0
  105. package/test/resources/9999999/automation/patch_fixKeys-schedule-expected.json +44 -0
  106. package/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml +42 -0
  107. package/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-fixKey_pause-response.xml +42 -0
  108. package/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-fixKey_schedule-response.xml +42 -0
  109. package/test/resources/9999999/automation/perform-a8afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml +42 -0
  110. package/test/resources/9999999/automation/retrieve-expected.json +5 -2
  111. package/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md +3 -2
  112. package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml +52 -0
  113. package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-ad2e-pause-response.xml +38 -0
  114. package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-fixKey_pause-response.xml +52 -0
  115. package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-fixKey_schedule-response.xml +52 -0
  116. package/test/resources/9999999/automation/schedule-a8afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml +52 -0
  117. package/test/resources/9999999/automation/template-expected.json +5 -2
  118. package/test/resources/9999999/automation/update-expected.json +1 -2
  119. package/test/resources/9999999/automation/update-testExisting_automation-expected.md +2 -2
  120. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json +7 -0
  121. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-pause/get-response.json +85 -0
  122. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-pause/patch-response.json +85 -0
  123. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_pause/get-response.json +85 -0
  124. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_pause/patch-response.json +85 -0
  125. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_schedule/get-response.json +85 -0
  126. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_schedule/patch-response.json +85 -0
  127. package/test/resources/9999999/automation/v1/automations/a8afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json +1 -1
  128. package/test/resources/9999999/automation/v1/automations/post-response.json +27 -19
  129. package/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/patch-response.json +38 -0
  130. package/test/resources/9999999/automation/v1/dataextracts/post-response.json +38 -0
  131. package/test/resources/9999999/automation/v1/dataextracttypes/get-response.json +50 -0
  132. package/test/resources/9999999/automation/v1/dataverifications/post-response.json +12 -0
  133. package/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/delete-response.json +0 -0
  134. package/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/get-response.json +12 -0
  135. package/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/patch-response.json +12 -0
  136. package/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/patch-response.json +18 -0
  137. package/test/resources/9999999/automation/v1/filetransfers/post-response.json +18 -0
  138. package/test/resources/9999999/automation/v1/ftplocations/get-response.json +18 -0
  139. package/test/resources/9999999/automation/v1/imports/9d16f42c-2260-ed11-b849-48df37d1de8b/patch-response.json +31 -0
  140. package/test/resources/9999999/automation/v1/imports/get-response.json +1 -1
  141. package/test/resources/9999999/automation/v1/imports/post-response.json +30 -0
  142. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dae/actions/start/post-response.txt +1 -0
  143. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeys/get-response.json +17 -0
  144. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeys/patch-response.json +18 -0
  145. package/test/resources/9999999/automation/v1/queries/get-response.json +18 -1
  146. package/test/resources/9999999/automation/v1/scripts/39f6a488-20eb-4ba0-b0b9-023725b574e4/patch-response.json +10 -0
  147. package/test/resources/9999999/automation/v1/scripts/get-response.json +12 -2
  148. package/test/resources/9999999/automation/v1/scripts/post-response.json +10 -0
  149. package/test/resources/9999999/dataExtension/build-expected.json +16 -0
  150. package/test/resources/9999999/dataExtension/delete-response.xml +42 -0
  151. package/test/resources/9999999/dataExtension/retrieve-Name=testExisting_dataExtension-response.xml +52 -0
  152. package/test/resources/9999999/dataExtension/retrieve-expected.json +16 -0
  153. package/test/resources/9999999/dataExtension/retrieve-expected.md +3 -1
  154. package/test/resources/9999999/dataExtension/template-expected.json +16 -0
  155. package/test/resources/9999999/dataExtension/update-expected.json +17 -1
  156. package/test/resources/9999999/dataExtensionField/retrieve-CustomerKey=[testExisting_dataExtension].[LastName]-response.xml +44 -0
  157. package/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testExisting_dataExtension-response.xml +133 -0
  158. package/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_dataExtensionORDataExtension.CustomerKey=testExisting_dataExtension-response.xml +99 -0
  159. package/test/resources/9999999/dataExtensionField/retrieve-response.xml +36 -1
  160. package/test/resources/9999999/dataExtract/build-expected.json +35 -0
  161. package/test/resources/9999999/dataExtract/get-expected.json +39 -0
  162. package/test/resources/9999999/dataExtract/patch-expected.json +37 -0
  163. package/test/resources/9999999/dataExtract/post-expected.json +37 -0
  164. package/test/resources/9999999/dataExtract/template-expected.json +35 -0
  165. package/test/resources/9999999/dataFolder/retrieve-ContentType=contextual_suppression_listORContentType=publicationORContentType=suppression_listORContentType=mysubsORContentType=list-response.xml +136 -0
  166. package/test/resources/9999999/dataFolder/retrieve-ContentType=ssjsactivity-response.xml +48 -0
  167. package/test/resources/9999999/dataFolder/retrieve-ContentType=synchronizeddataextensionORContentType=shared_salesforcedataextensionORContentType=shared_dataextensionORContentType=shared_dataORContentType=salesforcedataextensionORContentType=dataextensionORContentType=hidden-response.xml +117 -0
  168. package/test/resources/9999999/dataFolder/retrieve-ContentType=triggered_send_journeybuilderORContentType=triggered_sendORContentType=hidden-response.xml +276 -0
  169. package/test/resources/9999999/dataFolder/retrieve-response.xml +23 -0
  170. package/test/resources/9999999/email/retrieve-response.xml +203 -0
  171. package/test/resources/9999999/fileTransfer/build-expected.json +15 -0
  172. package/test/resources/9999999/fileTransfer/get-expected.json +17 -0
  173. package/test/resources/9999999/fileTransfer/patch-expected.json +17 -0
  174. package/test/resources/9999999/fileTransfer/post-expected.json +17 -0
  175. package/test/resources/9999999/fileTransfer/template-expected.json +15 -0
  176. package/test/resources/9999999/hub/v1/contacts/schema/attributeGroups/get-response.json +628 -0
  177. package/test/resources/9999999/hub/v1/contacts/schema/setDefinitions/get-response.json +20194 -0
  178. package/test/resources/9999999/importFile/build-expected.json +27 -0
  179. package/test/resources/9999999/importFile/get-expected.json +29 -0
  180. package/test/resources/9999999/importFile/patch-expected.json +29 -0
  181. package/test/resources/9999999/importFile/post-expected.json +29 -0
  182. package/test/resources/9999999/importFile/template-expected.json +27 -0
  183. package/test/resources/9999999/interaction/v1/interactions/233d4413-922c-4568-85a5-e5cc77efc3be/delete-response.json +1 -0
  184. package/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/get-response.json +1 -1
  185. package/test/resources/9999999/messaging/v1/email/definitions/post-response.json +1 -1
  186. package/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/delete-response.json +6 -0
  187. package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixKey_pause-response.xml +32 -0
  188. package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixKey_schedule-response.xml +32 -0
  189. package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixedKey_paused-response.xml +32 -0
  190. package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixedKey_scheduled-response.xml +32 -0
  191. package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_pause-response.xml +30 -0
  192. package/test/resources/9999999/program/retrieve-response.xml +21 -3
  193. package/test/resources/9999999/query/patch_fixKeys-expected.json +11 -0
  194. package/test/resources/9999999/query/patch_fixKeys-expected.sql +6 -0
  195. package/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixKeysANDStatus=Active-response.xml +30 -0
  196. package/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixedKeysANDStatus=Active-response.xml +30 -0
  197. package/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testNew_queryANDStatus=Active-response.xml +30 -0
  198. package/test/resources/9999999/script/build-expected.json +6 -0
  199. package/test/resources/9999999/script/build-expected.ssjs +1 -0
  200. package/test/resources/9999999/script/get-expected.json +8 -0
  201. package/test/resources/9999999/script/get-expected.ssjs +1 -0
  202. package/test/resources/9999999/script/get_noScriptTag-expected.html +1 -0
  203. package/test/resources/9999999/script/get_noScriptTag-expected.json +8 -0
  204. package/test/resources/9999999/script/patch-expected.json +8 -0
  205. package/test/resources/9999999/script/patch-expected.ssjs +1 -0
  206. package/test/resources/9999999/script/post-expected.json +8 -0
  207. package/test/resources/9999999/script/post-expected.ssjs +1 -0
  208. package/test/resources/9999999/script/template-expected.json +6 -0
  209. package/test/resources/9999999/script/template-expected.ssjs +1 -0
  210. package/test/resources/9999999/transactionalEmail/build-expected.json +3 -7
  211. package/test/resources/9999999/transactionalEmail/get-expected.json +3 -7
  212. package/test/resources/9999999/transactionalEmail/patch-expected.json +3 -7
  213. package/test/resources/9999999/transactionalEmail/post-expected.json +3 -7
  214. package/test/resources/9999999/transactionalEmail/template-expected.json +3 -7
  215. package/test/resources/9999999/triggeredSend/build-expected.json +29 -0
  216. package/test/resources/9999999/triggeredSend/get-expected.json +29 -0
  217. package/test/resources/9999999/triggeredSend/patch-expected.json +29 -0
  218. package/test/resources/9999999/triggeredSend/post-expected.json +29 -0
  219. package/test/resources/9999999/triggeredSend/template-expected.json +29 -0
  220. package/test/resources/9999999/triggeredSendDefinition/create-response.xml +75 -0
  221. package/test/resources/9999999/triggeredSendDefinition/delete-response.xml +36 -0
  222. package/test/resources/9999999/triggeredSendDefinition/{retrieve-response.xml → retrieve-TriggeredSendStatusINNew,Active,Inactive,Moved,Canceled-response.xml} +4 -4
  223. package/test/resources/9999999/triggeredSendDefinition/update-response.xml +74 -0
  224. package/test/resources/9999999/verification/build-expected.json +11 -0
  225. package/test/resources/9999999/verification/get-expected.json +11 -0
  226. package/test/resources/9999999/verification/patch-expected.json +11 -0
  227. package/test/resources/9999999/verification/post-expected.json +11 -0
  228. package/test/resources/9999999/verification/template-expected.json +11 -0
  229. package/test/type.attributeGroup.test.js +55 -0
  230. package/test/type.attributeSet.test.js +55 -0
  231. package/test/type.automation.test.js +650 -17
  232. package/test/type.dataExtension.test.js +205 -46
  233. package/test/type.dataExtract.test.js +194 -0
  234. package/test/type.fileTransfer.test.js +192 -0
  235. package/test/type.importFile.test.js +193 -0
  236. package/test/type.journey.test.js +38 -11
  237. package/test/type.mobileKeyword.test.js +6 -5
  238. package/test/type.mobileMessage.test.js +6 -4
  239. package/test/type.query.test.js +470 -17
  240. package/test/type.script.test.js +372 -0
  241. package/test/type.transactionalEmail.test.js +12 -11
  242. package/test/type.transactionalPush.test.js +2 -4
  243. package/test/type.transactionalSMS.test.js +2 -4
  244. package/test/type.triggeredSend.test.js +154 -0
  245. package/test/type.user.test.js +22 -10
  246. package/test/type.verification.test.js +173 -0
  247. package/test/utils.js +11 -2
  248. package/types/mcdev.d.js +14 -0
  249. package/lib/metadataTypes/SetDefinition.js +0 -37
  250. /package/test/resources/1111111/accountUser/{retrieve-response.xml → retrieve-ActiveFlag=trueANDCustomerKey=testExisting_userANDEmaillike@-response.xml} +0 -0
  251. /package/test/resources/1111111/accountUserAccount/{retrieve-response.xml → retrieve-AccountUser.AccountUserIDIN700301950,700301951,7471228-response.xml} +0 -0
  252. /package/test/resources/1111111/businessUnit/{retrieve-response.xml → retrieve-ID=1111111-response.xml} +0 -0
  253. /package/test/resources/1111111/list/{retrieve-response.xml → retrieve-CustomerKey=All SubscribersORListName=All Subscribers-response.xml} +0 -0
  254. /package/test/resources/1111111/role/{retrieve-response.xml → retrieve-IsPrivate=false-response.xml} +0 -0
  255. /package/test/resources/9999999/emailSendDefinition/{retrieve-response.xml → retrieve-IsPlatformObject=falseANDDescriptionnotEqualsSFSendDefinition-response.xml} +0 -0
  256. /package/test/resources/9999999/queryDefinition/{retrieve-response.xml → retrieve-CustomerKey=testExisting_queryANDStatus=Active-response.xml} +0 -0
@@ -35,7 +35,7 @@ class MetadataType {
35
35
  * Returns file contents mapped to their filename without '.json' ending
36
36
  *
37
37
  * @param {string} dir directory that contains '.json' files to be read
38
- * @param {boolean} [listBadKeys=false] do not print errors, used for badKeys()
38
+ * @param {boolean} [listBadKeys] do not print errors, used for badKeys()
39
39
  * @returns {TYPE.MetadataTypeMap} fileName => fileContent map
40
40
  */
41
41
  static getJsonFromFS(dir, listBadKeys) {
@@ -108,11 +108,10 @@ class MetadataType {
108
108
  * @param {TYPE.MetadataTypeMap} metadata metadata mapped by their keyField
109
109
  * @param {string} deployDir directory where deploy metadata are saved
110
110
  * @param {string} retrieveDir directory where metadata after deploy should be saved
111
- * @param {boolean} [isRefresh] optional flag to indicate that triggeredSend should be refreshed after deployment of assets
112
111
  * @returns {Promise.<TYPE.MetadataTypeMap>} Promise of keyField => metadata map
113
112
  */
114
- static async deploy(metadata, deployDir, retrieveDir, isRefresh) {
115
- const upsertResults = await this.upsert(metadata, deployDir, isRefresh);
113
+ static async deploy(metadata, deployDir, retrieveDir) {
114
+ const upsertResults = await this.upsert(metadata, deployDir);
116
115
  const savedMetadata = await this.saveResults(upsertResults, retrieveDir, null);
117
116
  if (
118
117
  this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type) &&
@@ -131,22 +130,22 @@ class MetadataType {
131
130
  * @param {TYPE.MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create
132
131
  * @param {TYPE.MetadataTypeMap} originalMetadata metadata to be updated (contains additioanl fields)
133
132
  * @param {{created: number, updated: number}} createdUpdated counter representing successful creates/updates
134
- * @param {boolean} [isRefresh] optional flag to indicate that triggeredSend should be refreshed after deployment of assets
135
133
  * @returns {void}
136
134
  */
137
- static postDeployTasks(upsertResults, originalMetadata, createdUpdated, isRefresh) {}
135
+ static postDeployTasks(upsertResults, originalMetadata, createdUpdated) {}
138
136
 
139
137
  /**
140
- * helper for {@link createREST}
138
+ * helper for {@link MetadataType.createREST}
141
139
  *
142
140
  * @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
143
141
  * @param {object} apiResponse varies depending on the API call
142
+ * @param {TYPE.MetadataTypeItem} metadataEntryWithAllFields like metadataEntry but before non-creatable fields were stripped
144
143
  * @returns {void}
145
144
  */
146
- static postCreateTasks(metadataEntry, apiResponse) {}
145
+ static postCreateTasks(metadataEntry, apiResponse, metadataEntryWithAllFields) {}
147
146
 
148
147
  /**
149
- * helper for {@link updateREST}
148
+ * helper for {@link MetadataType.updateREST}
150
149
  *
151
150
  * @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
152
151
  * @param {object} apiResponse varies depending on the API call
@@ -155,7 +154,7 @@ class MetadataType {
155
154
  static postUpdateTasks(metadataEntry, apiResponse) {}
156
155
 
157
156
  /**
158
- * helper for {@link createREST} when legacy API endpoints as these do not return the created item but only their new id
157
+ * helper for {@link MetadataType.createREST} when legacy API endpoints as these do not return the created item but only their new id
159
158
  *
160
159
  * @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
161
160
  * @param {object} apiResponse varies depending on the API call
@@ -267,11 +266,10 @@ class MetadataType {
267
266
  *
268
267
  * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true
269
268
  * @param {string[]} [subTypeArr] optionally limit to a single subtype
270
- * @param {string} [key] customer key of single item to retrieve
271
269
  * @returns {Promise.<TYPE.MetadataTypeMapObj>} metadata
272
270
  */
273
- static async retrieveForCache(additionalFields, subTypeArr, key) {
274
- return this.retrieve(null, additionalFields, subTypeArr, key);
271
+ static async retrieveForCache(additionalFields, subTypeArr) {
272
+ return this.retrieve(null, additionalFields, subTypeArr);
275
273
  }
276
274
  /**
277
275
  * Gets metadata cache with limited fields and does not store value to disk
@@ -463,7 +461,18 @@ class MetadataType {
463
461
  Util.logger.error(
464
462
  ` ☇ skipping ${this.definition.type}: execute is not supported yet for ${this.definition.type}`
465
463
  );
466
- return;
464
+ return [];
465
+ }
466
+ /**
467
+ * Abstract pause method that needs to be implemented in child metadata type
468
+ *
469
+ * @returns {void}
470
+ */
471
+ static pause() {
472
+ Util.logger.error(
473
+ ` ☇ skipping ${this.definition.type}: pause is not supported yet for ${this.definition.type}`
474
+ );
475
+ return [];
467
476
  }
468
477
 
469
478
  /**
@@ -537,10 +546,9 @@ class MetadataType {
537
546
  *
538
547
  * @param {TYPE.MetadataTypeMap} metadataMap metadata mapped by their keyField
539
548
  * @param {string} deployDir directory where deploy metadata are saved
540
- * @param {boolean} [isRefresh] optional flag to indicate that triggeredSend should be refreshed after deployment of assets
541
549
  * @returns {Promise.<TYPE.MetadataTypeMap>} keyField => metadata map
542
550
  */
543
- static async upsert(metadataMap, deployDir, isRefresh) {
551
+ static async upsert(metadataMap, deployDir) {
544
552
  const orignalMetadataMap = JSON.parse(JSON.stringify(metadataMap));
545
553
  const metadataToUpdate = [];
546
554
  const metadataToCreate = [];
@@ -632,12 +640,10 @@ class MetadataType {
632
640
  const metadataResults = createResults.concat(updateResults).filter(Boolean);
633
641
  upsertResults = this.parseResponseBody(metadataResults);
634
642
  }
635
- await this.postDeployTasks(
636
- upsertResults,
637
- orignalMetadataMap,
638
- { created: createResults.length, updated: updateResults.length },
639
- isRefresh
640
- );
643
+ await this.postDeployTasks(upsertResults, orignalMetadataMap, {
644
+ created: createResults.length,
645
+ updated: updateResults.length,
646
+ });
641
647
  return upsertResults;
642
648
  }
643
649
 
@@ -802,11 +808,12 @@ class MetadataType {
802
808
  * @returns {Promise.<object> | null} Promise of API response or null in case of an error
803
809
  */
804
810
  static async createREST(metadataEntry, uri) {
811
+ const metadataClone = JSON.parse(JSON.stringify(metadataEntry));
805
812
  this.removeNotCreateableFields(metadataEntry);
806
813
  try {
807
814
  // set to empty object in case API returned nothing to be able to update it in helper classes
808
815
  const response = (await this.client.rest.post(uri, metadataEntry)) || {};
809
- await this.postCreateTasks(metadataEntry, response);
816
+ await this.postCreateTasks(metadataEntry, response, metadataClone);
810
817
  Util.logger.info(
811
818
  ` - created ${this.definition.type}: ${
812
819
  metadataEntry[this.definition.keyField] ||
@@ -815,7 +822,7 @@ class MetadataType {
815
822
  );
816
823
  return response;
817
824
  } catch (ex) {
818
- const parsedErrors = this.checkForErrors(ex);
825
+ const parsedErrors = this.getErrorsREST(ex);
819
826
  Util.logger.error(
820
827
  ` ☇ error creating ${this.definition.type} ${
821
828
  metadataEntry[this.definition.keyField] ||
@@ -845,7 +852,7 @@ class MetadataType {
845
852
  this.removeNotCreateableFields(metadataEntry);
846
853
  try {
847
854
  const response = await this.client.soap.create(
848
- soapType.charAt(0).toUpperCase() + soapType.slice(1),
855
+ Util.capitalizeFirstLetter(soapType),
849
856
  metadataEntry,
850
857
  null
851
858
  );
@@ -869,7 +876,7 @@ class MetadataType {
869
876
  *
870
877
  * @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
871
878
  * @param {string} uri rest endpoint for PATCH
872
- * @param {'patch'|'post'|'put'} [httpMethod='patch'] defaults to 'patch'; some update requests require PUT instead of PATCH
879
+ * @param {'patch'|'post'|'put'} [httpMethod] defaults to 'patch'; some update requests require PUT instead of PATCH
873
880
  * @returns {Promise.<object> | null} Promise of API response or null in case of an error
874
881
  */
875
882
  static async updateREST(metadataEntry, uri, httpMethod = 'patch') {
@@ -878,7 +885,7 @@ class MetadataType {
878
885
  // set to empty object in case API returned nothing to be able to update it in helper classes
879
886
  const response = (await this.client.rest[httpMethod](uri, metadataEntry)) || {};
880
887
  await this._postChangeKeyTasks(metadataEntry);
881
- this.checkForErrors(response);
888
+ this.getErrorsREST(response);
882
889
  await this.postUpdateTasks(metadataEntry, response);
883
890
  // some times, e.g. automation dont return a key in their update response and hence we need to fall back to name
884
891
  Util.logger.info(
@@ -889,7 +896,7 @@ class MetadataType {
889
896
  );
890
897
  return response;
891
898
  } catch (ex) {
892
- const parsedErrors = this.checkForErrors(ex);
899
+ const parsedErrors = this.getErrorsREST(ex);
893
900
  Util.logger.error(
894
901
  ` ☇ error updating ${this.definition.type} ${
895
902
  metadataEntry[this.definition.keyField] ||
@@ -904,7 +911,7 @@ class MetadataType {
904
911
  }
905
912
 
906
913
  /**
907
- * helper for {@link updateREST} and {@link updateSOAP} that removes old files after the key was changed
914
+ * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} that removes old files after the key was changed
908
915
  *
909
916
  * @private
910
917
  * @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
@@ -950,7 +957,7 @@ class MetadataType {
950
957
  this.removeNotUpdateableFields(metadataEntry);
951
958
  try {
952
959
  const response = await this.client.soap.update(
953
- soapType.charAt(0).toUpperCase() + soapType.slice(1),
960
+ Util.capitalizeFirstLetter(soapType),
954
961
  metadataEntry,
955
962
  null
956
963
  );
@@ -985,15 +992,20 @@ class MetadataType {
985
992
  }
986
993
  }
987
994
  /**
988
- * helper for {@link _handleSOAPErrors}
995
+ * helper for {@link MetadataType._handleSOAPErrors}
989
996
  *
990
997
  * @param {Error} ex error that occured
991
998
  * @returns {string} error message
992
999
  */
993
1000
  static getSOAPErrorMsg(ex) {
994
- return ex?.json?.Results?.length
995
- ? `${ex.json.Results[0].StatusMessage} (Code ${ex.json.Results[0].ErrorCode})`
996
- : ex.message;
1001
+ if (ex?.json?.Results?.length) {
1002
+ if (ex?.json?.Results[0].StatusMessage) {
1003
+ return `${ex.json.Results[0].StatusMessage} (Code ${ex.json.Results[0].ErrorCode})`;
1004
+ } else if (ex?.json?.Results[0].Result.StatusMessage) {
1005
+ return `${ex.json.Results[0].Result.StatusMessage} (Code ${ex.json.Results[0].Result.ErrorCode})`;
1006
+ }
1007
+ }
1008
+ return ex.message;
997
1009
  }
998
1010
  /**
999
1011
  * Retrieves SOAP via generic fuel-soap wrapper based metadata of metadata type into local filesystem. executes callback with retrieved metadata
@@ -1010,7 +1022,11 @@ class MetadataType {
1010
1022
  const soapType = this.definition.soapType || this.definition.type;
1011
1023
  let response;
1012
1024
  try {
1013
- response = await this.client.soap.retrieveBulk(soapType, fields, requestParams);
1025
+ response = await this.client.soap.retrieveBulk(
1026
+ Util.capitalizeFirstLetter(soapType),
1027
+ fields,
1028
+ requestParams
1029
+ );
1014
1030
  } catch (ex) {
1015
1031
  this._handleSOAPErrors(ex, 'retrieving');
1016
1032
  return {};
@@ -1045,6 +1061,7 @@ class MetadataType {
1045
1061
  const results = this.parseResponseBody(response, singleRetrieve);
1046
1062
  // get extended metadata if applicable
1047
1063
  if (this.definition.hasExtended) {
1064
+ Util.logger.debug(' - retrieving extended metadata');
1048
1065
  const extended = await this.client.rest.getCollection(
1049
1066
  Object.keys(results).map((key) => uri + results[key][this.definition.idField])
1050
1067
  );
@@ -1073,29 +1090,117 @@ class MetadataType {
1073
1090
  type: this.definition.type,
1074
1091
  };
1075
1092
  }
1093
+ /**
1094
+ *
1095
+ * @param {object[]} urlArray {uri: string, id: string} combo of URL and ID/key of metadata
1096
+ * @param {number} [concurrentRequests] optionally set a different amount of concurrent requests
1097
+ * @param {boolean} [logAmountOfUrls] if true, prints an info message about to-be loaded amount of metadata
1098
+ * @returns {Promise.<{metadata: (TYPE.MetadataTypeMap | TYPE.MetadataTypeItem), type: string}>} Promise of item map (single item for templated result)
1099
+ */
1100
+ static async retrieveRESTcollection(urlArray, concurrentRequests = 10, logAmountOfUrls = true) {
1101
+ if (logAmountOfUrls) {
1102
+ Util.logger.info(
1103
+ Util.getGrayMsg(
1104
+ ` - ${urlArray?.length} ${this.definition.type}${
1105
+ urlArray?.length === 1 ? '' : 's'
1106
+ } found. Retrieving details...`
1107
+ )
1108
+ );
1109
+ }
1110
+ const rateLimit = pLimit(concurrentRequests);
1111
+
1112
+ const metadataArr = urlArray.length
1113
+ ? await Promise.all(
1114
+ urlArray.map(async (item) =>
1115
+ rateLimit(async () => {
1116
+ try {
1117
+ return await this.client.rest.get(item.uri);
1118
+ } catch (ex) {
1119
+ return this.handleRESTErrors(ex, item.id);
1120
+ }
1121
+ })
1122
+ )
1123
+ )
1124
+ : [];
1125
+ const results = {};
1126
+ for (const item of metadataArr) {
1127
+ const key = item[this.definition.keyField];
1128
+ results[key] = item;
1129
+ }
1130
+ return {
1131
+ metadata: results,
1132
+ type: this.definition.type,
1133
+ };
1134
+ }
1135
+
1136
+ /**
1137
+ * helper for {@link this.retrieveRESTcollection}
1138
+ *
1139
+ * @param {Error} ex exception
1140
+ * @param {string} id id or key of item
1141
+ * @returns {null} -
1142
+ */
1143
+ static handleRESTErrors(ex, id) {
1144
+ // if the ID is too short, the system will throw the 400 error
1145
+ Util.logger.debug(` ☇ skipping ${this.definition.type} ${id}: ${ex.message} ${ex.code}`);
1146
+
1147
+ return null;
1148
+ }
1076
1149
  /**
1077
1150
  * Used to execute a query/automation etc.
1078
1151
  *
1079
1152
  * @param {string} uri REST endpoint where the POST request should be sent
1080
1153
  * @param {string} key item key
1081
- * @returns {Promise.<string>} 'OK' if started execution successfully, otherwise - 'Error'
1154
+ * @returns {Promise.<{key:string, response:string}>} metadata key and API response (OK or error)
1082
1155
  */
1083
1156
  static async executeREST(uri, key) {
1084
1157
  try {
1085
1158
  const response = await this.client.rest.post(uri, {}); // payload is empty for this request
1086
1159
  if (response === 'OK') {
1087
- Util.logger.info(`Executed ${this.definition.type}: ${key}`);
1160
+ Util.logger.info(` - executed ${this.definition.type}: ${key}`);
1088
1161
  } else {
1089
1162
  throw new Error(response);
1090
1163
  }
1091
- return response;
1164
+ return { key, response };
1092
1165
  } catch (ex) {
1093
1166
  Util.logger.error(`Failed to execute ${this.definition.type} ${key}: ${ex.message}`);
1094
1167
  }
1095
1168
  }
1096
1169
 
1097
1170
  /**
1098
- * helper for {@link retrieveREST} and {@link retrieveSOAP}
1171
+ * Used to execute a query/automation etc.
1172
+ *
1173
+ * @param {TYPE.MetadataTypeItem} [metadataEntry] single metadata entry
1174
+ * @returns {Promise.<{key:string, response:object}>} metadata key and API response
1175
+ */
1176
+ static async executeSOAP(metadataEntry) {
1177
+ const soapType = this.definition.soapType || this.definition.type;
1178
+ try {
1179
+ const response = await this.client.soap.perform(
1180
+ Util.capitalizeFirstLetter(soapType),
1181
+ 'start',
1182
+ {
1183
+ ObjectID: metadataEntry[this.definition.idField],
1184
+ }
1185
+ );
1186
+ if (response?.OverallStatus === 'OK') {
1187
+ Util.logger.info(
1188
+ ` - executed ${this.definition.type}: ${
1189
+ metadataEntry[this.definition.keyField]
1190
+ }`
1191
+ );
1192
+ } else {
1193
+ throw new Error(response?.OverallStatus);
1194
+ }
1195
+ return { key: metadataEntry[this.definition.keyField], response };
1196
+ } catch (ex) {
1197
+ this._handleSOAPErrors(ex, 'executing', metadataEntry);
1198
+ return null;
1199
+ }
1200
+ }
1201
+
1202
+ /**
1203
+ * helper for {@link MetadataType.retrieveREST} and {@link MetadataType.retrieveSOAP}
1099
1204
  *
1100
1205
  * @param {string|number} [singleRetrieve] key of single item to filter by
1101
1206
  * @param {TYPE.MetadataTypeMap} metadataMap saved metadata
@@ -1298,7 +1403,7 @@ class MetadataType {
1298
1403
  *
1299
1404
  * @static
1300
1405
  * @param {TYPE.MetadataTypeItem} metadataEntry metadata entry
1301
- * @param {boolean} [include=false] true: use definition.include / options.include; false=exclude: use definition.filter / options.exclude
1406
+ * @param {boolean} [include] true: use definition.include / options.include; false=exclude: use definition.filter / options.exclude
1302
1407
  * @returns {boolean} true: skip saving == filtered; false: continue with saving
1303
1408
  * @memberof MetadataType
1304
1409
  */
@@ -1343,7 +1448,7 @@ class MetadataType {
1343
1448
  *
1344
1449
  * @static
1345
1450
  * @param {object} metadataEntry metadata entry
1346
- * @param {boolean} [include=false] true: use definition.include / options.include; false=exclude: use definition.filter / options.exclude
1451
+ * @param {boolean} [include] true: use definition.include / options.include; false=exclude: use definition.filter / options.exclude
1347
1452
  * @returns {boolean} true: filtered == do NOT save; false: not filtered == do save
1348
1453
  * @memberof MetadataType
1349
1454
  */
@@ -1575,6 +1680,10 @@ class MetadataType {
1575
1680
  }
1576
1681
  }
1577
1682
 
1683
+ if (Util.OPTIONS.like && !Util.fieldsLike(results[originalKey])) {
1684
+ Util.logger.debug(`Filtered ${originalKey} because of --like option`);
1685
+ continue;
1686
+ }
1578
1687
  // we dont store Id on local disk, but we need it for caching logic,
1579
1688
  // so its in retrieve but not in save. Here we put into the clone so that the original
1580
1689
  // object used for caching doesnt have the Id removed.
@@ -1621,7 +1730,7 @@ class MetadataType {
1621
1730
  return savedResults;
1622
1731
  }
1623
1732
  /**
1624
- * helper for {@link buildDefinitionForNested}
1733
+ * helper for {@link MetadataType.buildDefinitionForNested}
1625
1734
  * searches extracted file for template variable names and applies the market values
1626
1735
  *
1627
1736
  * @param {string} code code from extracted code
@@ -1633,7 +1742,7 @@ class MetadataType {
1633
1742
  return Mustache.render(code, templateVariables, {}, ['{{{', '}}}']);
1634
1743
  }
1635
1744
  /**
1636
- * helper for {@link buildTemplateForNested}
1745
+ * helper for {@link MetadataType.buildTemplateForNested}
1637
1746
  * searches extracted file for template variable values and applies the market variable names
1638
1747
  *
1639
1748
  * @param {string} code code from extracted code
@@ -1645,7 +1754,7 @@ class MetadataType {
1645
1754
  return Util.replaceByObject(code, templateVariables);
1646
1755
  }
1647
1756
  /**
1648
- * helper for {@link buildDefinition}
1757
+ * helper for {@link MetadataType.buildDefinition}
1649
1758
  * handles extracted code if any are found for complex types (e.g script, asset, query)
1650
1759
  *
1651
1760
  * @param {string} templateDir Directory where metadata templates are stored
@@ -1666,7 +1775,7 @@ class MetadataType {
1666
1775
  return null;
1667
1776
  }
1668
1777
  /**
1669
- * helper for {@link buildTemplate}
1778
+ * helper for {@link MetadataType.buildTemplate}
1670
1779
  * handles extracted code if any are found for complex types
1671
1780
  *
1672
1781
  * @param {string} templateDir Directory where metadata templates are stored
@@ -1812,7 +1921,7 @@ class MetadataType {
1812
1921
  * @param {object} ex response payload from REST API
1813
1922
  * @returns {string[] | void} formatted Error Message
1814
1923
  */
1815
- static checkForErrors(ex) {
1924
+ static getErrorsREST(ex) {
1816
1925
  const errors = [];
1817
1926
  if (ex?.response?.status >= 400 && ex?.response?.status < 600) {
1818
1927
  if (ex.response.data.errors) {
@@ -1835,11 +1944,13 @@ class MetadataType {
1835
1944
  }
1836
1945
  } else if (ex.response.data.message) {
1837
1946
  errors.push(ex.response.data.message);
1838
- } else {
1947
+ } else if (ex.response.data) {
1839
1948
  errors.push(`Undefined Errors: ${JSON.stringify(ex.response.data)}`);
1949
+ Util.logger.debug(JSON.stringify(ex.response.data));
1950
+ } else {
1951
+ errors.push(`${ex.response.status} ${ex.response.statusText}`);
1840
1952
  }
1841
1953
  Util.logger.debug(JSON.stringify(ex.config));
1842
- Util.logger.debug(JSON.stringify(ex.response.data));
1843
1954
  }
1844
1955
  return errors;
1845
1956
  }
@@ -1902,11 +2013,7 @@ class MetadataType {
1902
2013
  metadata[overrideKeyField || this.definition.keyField] = customerKey;
1903
2014
  const soapType = this.definition.soapType || this.definition.type;
1904
2015
  try {
1905
- await this.client.soap.delete(
1906
- soapType.charAt(0).toUpperCase() + soapType.slice(1),
1907
- metadata,
1908
- null
1909
- );
2016
+ await this.client.soap.delete(Util.capitalizeFirstLetter(soapType), metadata, null);
1910
2017
  if (!handleOutside) {
1911
2018
  Util.logger.info(` - deleted ${this.definition.type}: ${customerKey}`);
1912
2019
  }
@@ -1959,7 +2066,7 @@ class MetadataType {
1959
2066
  * Returns metadata of a business unit that is saved locally
1960
2067
  *
1961
2068
  * @param {string} readDir root directory of metadata.
1962
- * @param {boolean} [listBadKeys=false] do not print errors, used for badKeys()
2069
+ * @param {boolean} [listBadKeys] do not print errors, used for badKeys()
1963
2070
  * @param {object} [buMetadata] Metadata of BU in local directory
1964
2071
  * @returns {object} Metadata of BU in local directory
1965
2072
  */
@@ -1997,6 +2104,57 @@ class MetadataType {
1997
2104
  const fileList = keyArr.map((key) => File.normalizePath([path, key + typeExtension]));
1998
2105
  return fileList;
1999
2106
  }
2107
+
2108
+ /**
2109
+ *
2110
+ * @param {TYPE.MetadataTypeMap} metadataMap metadata mapped by their keyField
2111
+ * @returns {string[]} list of keys
2112
+ */
2113
+ static getKeysForFixing(metadataMap) {
2114
+ const keysForDeploy = [];
2115
+ if (Object.keys(metadataMap).length) {
2116
+ Util.logger.info(
2117
+ `Searching for ${this.definition.type} keys among downloaded items that need fixing:`
2118
+ );
2119
+ for (const item of Object.values(metadataMap)) {
2120
+ if (item[this.definition.nameField].length > this.definition.maxKeyLength) {
2121
+ Util.logger.warn(
2122
+ `Name of the item ${
2123
+ item[this.definition.keyField]
2124
+ } is too long for a key. Consider renaming your item. Key will be equal first ${
2125
+ this.definition.maxKeyLength
2126
+ } characters of the name`
2127
+ );
2128
+ item[this.definition.nameField] = item[this.definition.nameField].slice(
2129
+ 0,
2130
+ this.definition.maxKeyLength
2131
+ );
2132
+ }
2133
+
2134
+ if (
2135
+ item[this.definition.nameField] != item[this.definition.keyField] &&
2136
+ !this.definition.keyIsFixed
2137
+ ) {
2138
+ keysForDeploy.push(item[this.definition.keyField]);
2139
+ Util.logger.info(
2140
+ ` - added ${this.definition.type} to fixKey queue: ${
2141
+ item[this.definition.keyField]
2142
+ }`
2143
+ );
2144
+ } else {
2145
+ Util.logger.info(
2146
+ Util.getGrayMsg(
2147
+ ` ☇ skipping ${this.definition.type} ${
2148
+ item[this.definition.keyField]
2149
+ }: key does not need to be updated`
2150
+ )
2151
+ );
2152
+ }
2153
+ }
2154
+ Util.logger.info(`Found ${keysForDeploy.length} ${this.definition.type} keys to fix`);
2155
+ }
2156
+ return keysForDeploy;
2157
+ }
2000
2158
  }
2001
2159
 
2002
2160
  MetadataType.definition = {
@@ -96,7 +96,7 @@ class MobileKeyword extends MetadataType {
96
96
  }
97
97
 
98
98
  /**
99
- * helper for {@link parseResponseBody} that creates a custom key field for this type based on mobileCode and keyword
99
+ * helper for {@link MobileKeyword.parseResponseBody} that creates a custom key field for this type based on mobileCode and keyword
100
100
  *
101
101
  * @private
102
102
  * @param {TYPE.MetadataType} metadata single item
@@ -106,7 +106,7 @@ class MobileKeyword extends MetadataType {
106
106
  }
107
107
 
108
108
  /**
109
- * helper for {@link preDeployTasks} and {@link createOrUpdate} to ensure we have code & keyword properly set
109
+ * helper for {@link MobileKeyword.preDeployTasks} and {@link MobileKeyword.createOrUpdate} to ensure we have code & keyword properly set
110
110
  *
111
111
  * @private
112
112
  * @param {TYPE.MetadataType} metadata single item
@@ -192,7 +192,7 @@ class MobileKeyword extends MetadataType {
192
192
  }
193
193
 
194
194
  /**
195
- * helper for {@link retrieve} and {@link retrieveAsTemplate}
195
+ * helper for {@link MobileKeyword.retrieve} and {@link MobileKeyword.retrieveAsTemplate}
196
196
  *
197
197
  * @private
198
198
  * @param {string} key customer key of single item to retrieve / name of the metadata file
@@ -281,7 +281,7 @@ class MobileKeyword extends MetadataType {
281
281
  }
282
282
  }
283
283
  /**
284
- * helper for {@link parseMetadata} and {@link _buildForNested}
284
+ * helper for {@link MobileKeyword.postRetrieveTasks} and {@link MobileKeyword._buildForNested}
285
285
  *
286
286
  * @param {string} metadataScript the code of the file
287
287
  * @returns {{fileExt:string,code:string}} returns found extension and file content
@@ -349,7 +349,7 @@ class MobileKeyword extends MetadataType {
349
349
  }
350
350
 
351
351
  /**
352
- * helper for {@link buildTemplateForNested} / {@link buildDefinitionForNested}
352
+ * helper for {@link MobileKeyword.buildTemplateForNested} / {@link MobileKeyword.buildDefinitionForNested}
353
353
  * handles extracted code if any are found for complex types
354
354
  *
355
355
  * @param {string} templateDir Directory where metadata templates are stored
@@ -445,7 +445,7 @@ class MobileKeyword extends MetadataType {
445
445
  return metadata;
446
446
  }
447
447
  /**
448
- * helper for {@link createREST}
448
+ * helper for {@link MetadataType.createREST}
449
449
  *
450
450
  * @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
451
451
  * @param {object} apiResponse varies depending on the API call
@@ -455,7 +455,7 @@ class MobileKeyword extends MetadataType {
455
455
  await super.postDeployTasks_legacyApi(metadataEntry, apiResponse);
456
456
  }
457
457
  /**
458
- * helper for {@link updateREST}
458
+ * helper for {@link MetadataType.updateREST}
459
459
  *
460
460
  * @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
461
461
  * @param {object} apiResponse varies depending on the API call
@@ -466,7 +466,7 @@ class MobileKeyword extends MetadataType {
466
466
  }
467
467
 
468
468
  /**
469
- * helper for {@link preDeployTasks} that loads extracted code content back into JSON
469
+ * helper for {@link MobileKeyword.preDeployTasks} that loads extracted code content back into JSON
470
470
  *
471
471
  * @param {TYPE.MetadataTypeItem} metadata a single definition
472
472
  * @param {string} deployDir directory of deploy files
@@ -501,7 +501,7 @@ class MobileKeyword extends MetadataType {
501
501
  */
502
502
  static async deleteByKey(key) {
503
503
  // get id from cache
504
- const { metadata } = await this.retrieveForCache(key);
504
+ const { metadata } = await this.retrieveForCache(undefined, undefined, key);
505
505
  if (!metadata[key]) {
506
506
  Util.logger.error(`Could not find ${this.definition.type} with key ${key}.`);
507
507
  return false;
@@ -83,7 +83,7 @@ class MobileMessage extends MetadataType {
83
83
  return super.createREST(metadata, '/legacy/v1/beta/mobile/message/');
84
84
  }
85
85
  /**
86
- * helper for {@link preDeployTasks} that loads extracted code content back into JSON
86
+ * helper for {@link MobileMessage.preDeployTasks} that loads extracted code content back into JSON
87
87
  *
88
88
  * @param {TYPE.MetadataTypeItem} metadata a single definition
89
89
  * @param {string} deployDir directory of deploy files
@@ -110,7 +110,7 @@ class MobileMessage extends MetadataType {
110
110
  }
111
111
  }
112
112
  /**
113
- * helper for {@link parseMetadata} and {@link _buildForNested}
113
+ * helper for {@link MobileMessage.postRetrieveTasks} and {@link MobileMessage._buildForNested}
114
114
  *
115
115
  * @param {string} code the code of the file
116
116
  * @returns {{fileExt:string,code:string}} returns found extension and file content
@@ -304,7 +304,7 @@ class MobileMessage extends MetadataType {
304
304
  return metadata;
305
305
  }
306
306
  /**
307
- * helper for {@link createREST}
307
+ * helper for {@link MetadataType.createREST}
308
308
  *
309
309
  * @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
310
310
  * @param {object} apiResponse varies depending on the API call
@@ -314,7 +314,7 @@ class MobileMessage extends MetadataType {
314
314
  await super.postDeployTasks_legacyApi(metadataEntry, apiResponse);
315
315
  }
316
316
  /**
317
- * helper for {@link updateREST}
317
+ * helper for {@link MetadataType.updateREST}
318
318
  *
319
319
  * @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
320
320
  * @param {object} apiResponse varies depending on the API call
@@ -380,7 +380,7 @@ class MobileMessage extends MetadataType {
380
380
  }
381
381
 
382
382
  /**
383
- * helper for {@link buildTemplateForNested} / {@link buildDefinitionForNested}
383
+ * helper for {@link MobileMessage.buildTemplateForNested} / {@link MobileMessage.buildDefinitionForNested}
384
384
  * handles extracted code if any are found for complex types
385
385
  *
386
386
  * @param {string} templateDir Directory where metadata templates are stored