mcdev 5.0.2 → 5.2.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 (237) hide show
  1. package/.coverage-comment-template.svelte +177 -161
  2. package/.eslintrc.json +4 -4
  3. package/.github/ISSUE_TEMPLATE/bug.yml +2 -0
  4. package/.github/PULL_REQUEST_TEMPLATE.md +2 -2
  5. package/.github/dependabot.yml +8 -0
  6. package/.github/workflows/coverage-base-update.yml +6 -2
  7. package/.github/workflows/coverage-develop-branch.yml +7 -8
  8. package/.github/workflows/coverage-main-branch.yml +7 -8
  9. package/.github/workflows/coverage.yml +7 -4
  10. package/.husky/post-checkout +4 -2
  11. package/.husky/post-merge +1 -0
  12. package/.vscode/extensions.json +4 -0
  13. package/docs/dist/documentation.md +756 -294
  14. package/lib/Deployer.js +28 -28
  15. package/lib/MetadataTypeDefinitions.js +1 -1
  16. package/lib/MetadataTypeInfo.js +1 -1
  17. package/lib/Retriever.js +1 -1
  18. package/lib/cli.js +184 -6
  19. package/lib/index.js +493 -22
  20. package/lib/metadataTypes/Asset.js +10 -11
  21. package/lib/metadataTypes/AttributeGroup.js +76 -2
  22. package/lib/metadataTypes/AttributeSet.js +260 -0
  23. package/lib/metadataTypes/Automation.js +771 -247
  24. package/lib/metadataTypes/DataExtension.js +7 -7
  25. package/lib/metadataTypes/DataExtensionField.js +1 -1
  26. package/lib/metadataTypes/Event.js +2 -3
  27. package/lib/metadataTypes/Folder.js +1 -1
  28. package/lib/metadataTypes/Journey.js +5 -6
  29. package/lib/metadataTypes/MetadataType.js +187 -60
  30. package/lib/metadataTypes/MobileKeyword.js +8 -8
  31. package/lib/metadataTypes/MobileMessage.js +5 -5
  32. package/lib/metadataTypes/Query.js +47 -5
  33. package/lib/metadataTypes/Script.js +3 -3
  34. package/lib/metadataTypes/TransactionalSMS.js +5 -5
  35. package/lib/metadataTypes/TriggeredSend.js +25 -50
  36. package/lib/metadataTypes/User.js +7 -4
  37. package/lib/metadataTypes/definitions/Asset.definition.js +1 -0
  38. package/lib/metadataTypes/definitions/AttributeGroup.definition.js +117 -106
  39. package/lib/metadataTypes/definitions/{SetDefinition.definition.js → AttributeSet.definition.js} +54 -27
  40. package/lib/metadataTypes/definitions/Automation.definition.js +74 -21
  41. package/lib/metadataTypes/definitions/DataExtension.definition.js +1 -0
  42. package/lib/metadataTypes/definitions/DataExtract.definition.js +1 -0
  43. package/lib/metadataTypes/definitions/EmailSend.definition.js +1 -0
  44. package/lib/metadataTypes/definitions/Event.definition.js +1 -0
  45. package/lib/metadataTypes/definitions/Filter.definition.js +1 -0
  46. package/lib/metadataTypes/definitions/ImportFile.definition.js +37 -6
  47. package/lib/metadataTypes/definitions/MobileKeyword.definition.js +1 -0
  48. package/lib/metadataTypes/definitions/Query.definition.js +1 -0
  49. package/lib/metadataTypes/definitions/Role.definition.js +1 -0
  50. package/lib/metadataTypes/definitions/TriggeredSend.definition.js +2 -0
  51. package/lib/metadataTypes/definitions/User.definition.js +1 -0
  52. package/lib/util/cache.js +9 -4
  53. package/lib/util/cli.js +40 -0
  54. package/lib/util/devops.js +13 -11
  55. package/lib/util/file.js +2 -2
  56. package/lib/util/init.js +84 -0
  57. package/lib/util/util.js +268 -137
  58. package/package.json +11 -11
  59. package/test/general.test.js +26 -0
  60. package/test/mockRoot/.mcdevrc.json +1 -1
  61. package/test/mockRoot/deploy/testInstance/testBU/automation/testExisting_automation.automation-meta.json +52 -0
  62. package/test/mockRoot/deploy/testInstance/testBU/automation/testNew_automation.automation-meta.json +45 -0
  63. package/test/mockRoot/deploy/testInstance/testBU/dataExtract/testExisting_dataExtract.dataExtract-meta.json +35 -0
  64. package/test/mockRoot/deploy/testInstance/testBU/dataExtract/testNew_dataExtract.dataExtract-meta.json +35 -0
  65. package/test/mockRoot/deploy/testInstance/testBU/fileTransfer/testExisting_fileTransfer.fileTransfer-meta.json +17 -0
  66. package/test/mockRoot/deploy/testInstance/testBU/fileTransfer/testNew_fileTransfer.fileTransfer-meta.json +17 -0
  67. package/test/mockRoot/deploy/testInstance/testBU/importFile/testExisting_importFile.importFile-meta.json +29 -0
  68. package/test/mockRoot/deploy/testInstance/testBU/importFile/testNew_importFile.importFile-meta.json +29 -0
  69. package/test/mockRoot/deploy/testInstance/testBU/query/{testExistingQuery.query-meta.json → testExisting_query.query-meta.json} +2 -2
  70. package/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query_fixKeys.query-meta.json +11 -0
  71. package/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query_fixKeys.query-meta.sql +6 -0
  72. package/test/mockRoot/deploy/testInstance/testBU/query/{testNewQuery.query-meta.json → testNew_query.query-meta.json} +2 -2
  73. package/test/mockRoot/deploy/testInstance/testBU/script/testExisting_script.script-meta.json +6 -0
  74. package/test/mockRoot/deploy/testInstance/testBU/script/testExisting_script.script-meta.ssjs +1 -0
  75. package/test/mockRoot/deploy/testInstance/testBU/script/testNew_script.script-meta.json +6 -0
  76. package/test/mockRoot/deploy/testInstance/testBU/script/testNew_script.script-meta.ssjs +1 -0
  77. package/test/mockRoot/deploy/testInstance/testBU/triggeredSend/testExisting_triggeredSend.triggeredSend-meta.json +29 -0
  78. package/test/mockRoot/deploy/testInstance/testBU/triggeredSend/testNew_triggeredSend.triggeredSend-meta.json +29 -0
  79. package/test/resourceFactory.js +132 -24
  80. package/test/resources/1111111/accountUser/retrieve-ActiveFlag=falseANDCustomerKey=testExisting_userANDEmaillike@-response.xml +27 -0
  81. package/test/resources/1111111/accountUser/retrieve-ActiveFlag=falseANDEmaillike@-response.xml +156 -0
  82. package/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDEmailisNullORNamelikeapp userANDMustChangePassword=false-response.xml +87 -0
  83. package/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDEmaillike@-response.xml +156 -0
  84. package/test/resources/1111111/accountUser/retrieve-CustomerKey=testExisting_userANDActiveFlag=trueANDEmailisNullORNamelikeapp userANDMustChangePassword=false-response.xml +27 -0
  85. package/test/resources/1111111/accountUserAccount/retrieve-AccountUser.AccountUserID=700301950-response.xml +60 -0
  86. package/test/resources/1111111/user/retrieve-expected.md +4 -2
  87. package/test/resources/9999999/attributeGroup/retrieve-expected.json +25 -0
  88. package/test/resources/9999999/attributeSet/retrieve-expected.json +748 -0
  89. package/test/resources/9999999/automation/build-expected.json +57 -0
  90. package/test/resources/9999999/automation/create-expected.json +45 -0
  91. package/test/resources/9999999/automation/create-testNew_automation-expected.md +28 -0
  92. package/test/resources/9999999/automation/delete-response.xml +40 -0
  93. package/test/resources/9999999/automation/patch_fixKeys-pause-expected.json +44 -0
  94. package/test/resources/9999999/automation/patch_fixKeys-schedule-expected.json +44 -0
  95. package/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml +42 -0
  96. package/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-fixKey_pause-response.xml +42 -0
  97. package/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-fixKey_schedule-response.xml +42 -0
  98. package/test/resources/9999999/automation/perform-a8afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml +42 -0
  99. package/test/resources/9999999/automation/retrieve-expected.json +57 -0
  100. package/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md +30 -0
  101. package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml +52 -0
  102. package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-ad2e-pause-response.xml +38 -0
  103. package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-fixKey_pause-response.xml +52 -0
  104. package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-fixKey_schedule-response.xml +52 -0
  105. package/test/resources/9999999/automation/schedule-a8afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml +52 -0
  106. package/test/resources/9999999/automation/template-expected.json +57 -0
  107. package/test/resources/9999999/automation/update-expected.json +45 -0
  108. package/test/resources/9999999/automation/update-testExisting_automation-expected.md +28 -0
  109. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json +85 -0
  110. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/patch-response.json +85 -0
  111. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-pause/get-response.json +85 -0
  112. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-pause/patch-response.json +85 -0
  113. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_pause/get-response.json +85 -0
  114. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_pause/patch-response.json +85 -0
  115. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_schedule/get-response.json +85 -0
  116. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_schedule/patch-response.json +85 -0
  117. package/test/resources/9999999/automation/v1/automations/a8afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json +85 -0
  118. package/test/resources/9999999/automation/v1/automations/post-response.json +86 -0
  119. package/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/get-response.json +38 -0
  120. package/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/patch-response.json +38 -0
  121. package/test/resources/9999999/automation/v1/dataextracts/get-response.json +20 -0
  122. package/test/resources/9999999/automation/v1/dataextracts/post-response.json +38 -0
  123. package/test/resources/9999999/automation/v1/dataextracttypes/get-response.json +50 -0
  124. package/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/get-response.json +18 -0
  125. package/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/patch-response.json +18 -0
  126. package/test/resources/9999999/automation/v1/filetransfers/get-response.json +15 -0
  127. package/test/resources/9999999/automation/v1/filetransfers/post-response.json +18 -0
  128. package/test/resources/9999999/automation/v1/ftplocations/get-response.json +18 -0
  129. package/test/resources/9999999/automation/v1/imports/9d16f42c-2260-ed11-b849-48df37d1de8b/patch-response.json +31 -0
  130. package/test/resources/9999999/automation/v1/imports/get-response.json +38 -0
  131. package/test/resources/9999999/automation/v1/imports/post-response.json +30 -0
  132. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dae/actions/start/post-response.txt +1 -0
  133. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/actions/start/post-response.txt +1 -0
  134. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/get-response.json +2 -2
  135. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/patch-response.json +2 -2
  136. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeys/get-response.json +17 -0
  137. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeys/patch-response.json +18 -0
  138. package/test/resources/9999999/automation/v1/queries/get-response.json +22 -5
  139. package/test/resources/9999999/automation/v1/queries/post-response.json +2 -2
  140. package/test/resources/9999999/automation/v1/scripts/39f6a488-20eb-4ba0-b0b9-023725b574e4/patch-response.json +10 -0
  141. package/test/resources/9999999/automation/v1/scripts/get-response.json +27 -0
  142. package/test/resources/9999999/automation/v1/scripts/post-response.json +10 -0
  143. package/test/resources/9999999/dataExtension/retrieve-Name=testExisting_dataExtension-response.xml +52 -0
  144. package/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testExisting_dataExtension-response.xml +98 -0
  145. package/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_dataExtensionORDataExtension.CustomerKey=testExisting_dataExtension-response.xml +99 -0
  146. package/test/resources/9999999/dataExtract/build-expected.json +35 -0
  147. package/test/resources/9999999/dataExtract/get-expected.json +39 -0
  148. package/test/resources/9999999/dataExtract/patch-expected.json +37 -0
  149. package/test/resources/9999999/dataExtract/post-expected.json +37 -0
  150. package/test/resources/9999999/dataExtract/template-expected.json +35 -0
  151. package/test/resources/9999999/dataFolder/retrieve-ContentType=automations-response.xml +48 -0
  152. package/test/resources/9999999/dataFolder/retrieve-ContentType=contextual_suppression_listORContentType=publicationORContentType=suppression_listORContentType=mysubsORContentType=list-response.xml +136 -0
  153. package/test/resources/9999999/dataFolder/retrieve-ContentType=queryactivity-response.xml +48 -0
  154. package/test/resources/9999999/dataFolder/retrieve-ContentType=ssjsactivity-response.xml +48 -0
  155. package/test/resources/9999999/dataFolder/retrieve-ContentType=triggered_send_journeybuilderORContentType=triggered_sendORContentType=hidden-response.xml +276 -0
  156. package/test/resources/9999999/dataFolder/retrieve-response.xml +45 -0
  157. package/test/resources/9999999/email/retrieve-response.xml +203 -0
  158. package/test/resources/9999999/emailSendDefinition/retrieve-IsPlatformObject=falseANDDescriptionnotEqualsSFSendDefinition-response.xml +85 -0
  159. package/test/resources/9999999/fileTransfer/build-expected.json +15 -0
  160. package/test/resources/9999999/fileTransfer/get-expected.json +17 -0
  161. package/test/resources/9999999/fileTransfer/patch-expected.json +17 -0
  162. package/test/resources/9999999/fileTransfer/post-expected.json +17 -0
  163. package/test/resources/9999999/fileTransfer/template-expected.json +15 -0
  164. package/test/resources/9999999/hub/v1/contacts/schema/attributeGroups/get-response.json +585 -0
  165. package/test/resources/9999999/hub/v1/contacts/schema/setDefinitions/get-response.json +19807 -0
  166. package/test/resources/9999999/importFile/build-expected.json +27 -0
  167. package/test/resources/9999999/importFile/get-expected.json +29 -0
  168. package/test/resources/9999999/importFile/patch-expected.json +29 -0
  169. package/test/resources/9999999/importFile/post-expected.json +29 -0
  170. package/test/resources/9999999/importFile/template-expected.json +27 -0
  171. package/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/get-response.json +21 -0
  172. package/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/post-response.json +0 -0
  173. package/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/get-response.json +30 -0
  174. package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation-response.xml +30 -0
  175. package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixKey_pause-response.xml +32 -0
  176. package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixKey_schedule-response.xml +32 -0
  177. package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixedKey_paused-response.xml +32 -0
  178. package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixedKey_scheduled-response.xml +32 -0
  179. package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_pause-response.xml +30 -0
  180. package/test/resources/9999999/program/retrieve-CustomerKey=testNew_automation-response.xml +30 -0
  181. package/test/resources/9999999/program/retrieve-Name=testExisting_automation-response.xml +31 -0
  182. package/test/resources/9999999/program/retrieve-response.xml +50 -0
  183. package/test/resources/9999999/query/build-expected.json +2 -2
  184. package/test/resources/9999999/query/get-expected.json +2 -2
  185. package/test/resources/9999999/query/get2-expected.json +2 -2
  186. package/test/resources/9999999/query/patch-expected.json +2 -2
  187. package/test/resources/9999999/query/patch_fixKeys-expected.json +11 -0
  188. package/test/resources/9999999/query/patch_fixKeys-expected.sql +6 -0
  189. package/test/resources/9999999/query/post-expected.json +2 -2
  190. package/test/resources/9999999/query/template-expected.json +2 -2
  191. package/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixKeysANDStatus=Active-response.xml +30 -0
  192. package/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixedKeysANDStatus=Active-response.xml +30 -0
  193. package/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testNew_queryANDStatus=Active-response.xml +30 -0
  194. package/test/resources/9999999/script/build-expected.json +6 -0
  195. package/test/resources/9999999/script/build-expected.ssjs +1 -0
  196. package/test/resources/9999999/script/get-expected.json +8 -0
  197. package/test/resources/9999999/script/get-expected.ssjs +1 -0
  198. package/test/resources/9999999/script/get_noScriptTag-expected.html +1 -0
  199. package/test/resources/9999999/script/get_noScriptTag-expected.json +8 -0
  200. package/test/resources/9999999/script/patch-expected.json +8 -0
  201. package/test/resources/9999999/script/patch-expected.ssjs +1 -0
  202. package/test/resources/9999999/script/post-expected.json +8 -0
  203. package/test/resources/9999999/script/post-expected.ssjs +1 -0
  204. package/test/resources/9999999/script/template-expected.json +6 -0
  205. package/test/resources/9999999/script/template-expected.ssjs +1 -0
  206. package/test/resources/9999999/triggeredSend/build-expected.json +29 -0
  207. package/test/resources/9999999/triggeredSend/get-expected.json +29 -0
  208. package/test/resources/9999999/triggeredSend/patch-expected.json +29 -0
  209. package/test/resources/9999999/triggeredSend/post-expected.json +29 -0
  210. package/test/resources/9999999/triggeredSend/template-expected.json +29 -0
  211. package/test/resources/9999999/triggeredSendDefinition/create-response.xml +75 -0
  212. package/test/resources/9999999/triggeredSendDefinition/delete-response.xml +36 -0
  213. package/test/resources/9999999/triggeredSendDefinition/{retrieve-response.xml → retrieve-TriggeredSendStatusINNew,Active,Inactive,Moved,Canceled-response.xml} +4 -4
  214. package/test/resources/9999999/triggeredSendDefinition/update-response.xml +74 -0
  215. package/test/type.attributeGroup.test.js +55 -0
  216. package/test/type.attributeSet.test.js +55 -0
  217. package/test/type.automation.test.js +886 -0
  218. package/test/type.dataExtension.test.js +3 -1
  219. package/test/type.dataExtract.test.js +187 -0
  220. package/test/type.fileTransfer.test.js +185 -0
  221. package/test/type.importFile.test.js +186 -0
  222. package/test/type.mobileKeyword.test.js +0 -1
  223. package/test/type.query.test.js +497 -33
  224. package/test/type.script.test.js +367 -0
  225. package/test/type.triggeredSend.test.js +152 -0
  226. package/test/type.user.test.js +37 -11
  227. package/test/utils.js +10 -6
  228. package/.coverage-comment-template.md +0 -20
  229. package/lib/metadataTypes/SetDefinition.js +0 -37
  230. /package/test/mockRoot/deploy/testInstance/testBU/query/{testExistingQuery.query-meta.sql → testExisting_query.query-meta.sql} +0 -0
  231. /package/test/mockRoot/deploy/testInstance/testBU/query/{testNewQuery.query-meta.sql → testNew_query.query-meta.sql} +0 -0
  232. /package/test/resources/1111111/accountUser/{retrieve-response.xml → retrieve-ActiveFlag=trueANDCustomerKey=testExisting_userANDEmaillike@-response.xml} +0 -0
  233. /package/test/resources/1111111/accountUserAccount/{retrieve-response.xml → retrieve-AccountUser.AccountUserIDIN700301950,700301951,7471228-response.xml} +0 -0
  234. /package/test/resources/1111111/businessUnit/{retrieve-response.xml → retrieve-ID=1111111-response.xml} +0 -0
  235. /package/test/resources/1111111/list/{retrieve-response.xml → retrieve-CustomerKey=All SubscribersORListName=All Subscribers-response.xml} +0 -0
  236. /package/test/resources/1111111/role/{retrieve-response.xml → retrieve-IsPrivate=false-response.xml} +0 -0
  237. /package/test/resources/9999999/queryDefinition/{retrieve-response.xml → retrieve-CustomerKey=testExisting_queryANDStatus=Active-response.xml} +0 -0
package/lib/util/util.js CHANGED
@@ -3,10 +3,10 @@
3
3
  const TYPE = require('../../types/mcdev.d');
4
4
  const MetadataDefinitions = require('./../MetadataTypeDefinitions');
5
5
  const packageJsonMcdev = require('../../package.json');
6
+ const child_process = require('node:child_process');
6
7
  const process = require('node:process');
7
8
  const toposort = require('toposort');
8
9
  const winston = require('winston');
9
- const child_process = require('node:child_process');
10
10
 
11
11
  /**
12
12
  * Util that contains logger and simple util methods
@@ -80,12 +80,12 @@ const Util = {
80
80
  return false;
81
81
  }
82
82
  },
83
+
83
84
  /**
84
85
  * ensure provided MarketList exists and it's content including markets and BUs checks out
85
86
  *
86
87
  * @param {string} mlName name of marketList
87
88
  * @param {TYPE.Mcdevrc} properties General configuration to be used in retrieve
88
- * @returns {void} throws errors if problems were found
89
89
  */
90
90
  verifyMarketList(mlName, properties) {
91
91
  if (properties.marketList[mlName]) {
@@ -131,29 +131,32 @@ const Util = {
131
131
  * @returns {void}
132
132
  */
133
133
  signalFatalError() {
134
- Util.logger.debug('Util.signalFataError() sets process.exitCode = 1');
135
- process.exitCode = 1;
134
+ Util.logger.debug('Util.signalFataError() sets process.exitCode = 1 unless already set');
135
+ process.exitCode ||= 1;
136
136
  },
137
137
  /**
138
- * SFMC accepts multiple true values for Boolean attributes for which we are checking here
138
+ * SFMC accepts multiple true values for Boolean attributes for which we are checking here.
139
+ * The same problem occurs when evaluating boolean CLI flags
139
140
  *
140
141
  * @param {*} attrValue value
141
142
  * @returns {boolean} attribute value == true ? true : false
142
143
  */
143
144
  isTrue(attrValue) {
144
- return ['true', 'TRUE', 'True', '1', 1, 'Y', true].includes(attrValue);
145
+ return ['true', 'TRUE', 'True', '1', 1, 'Y', 'y', true].includes(attrValue);
145
146
  },
146
147
  /**
147
- * SFMC accepts multiple false values for Boolean attributes for which we are checking here
148
+ * SFMC accepts multiple false values for Boolean attributes for which we are checking here.
149
+ * The same problem occurs when evaluating boolean CLI flags
148
150
  *
149
151
  * @param {*} attrValue value
150
152
  * @returns {boolean} attribute value == false ? true : false
151
153
  */
152
154
  isFalse(attrValue) {
153
- return ['false', 'FALSE', 'False', '0', 0, 'N', false].includes(attrValue);
155
+ return ['false', 'FALSE', 'False', '0', 0, 'N', 'n', false].includes(attrValue);
154
156
  },
157
+
155
158
  /**
156
- * helper for {@link Mcdev.retrieve}, {@link Mcdev.retrieveAsTemplate} and {@link Mcdev.deploy}
159
+ * helper for Mcdev.retrieve, Mcdev.retrieveAsTemplate and Mcdev.deploy
157
160
  *
158
161
  * @param {TYPE.SupportedMetadataTypes} selectedType type or type-subtype
159
162
  * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method
@@ -227,6 +230,76 @@ const Util = {
227
230
 
228
231
  return typeChoices;
229
232
  },
233
+ /**
234
+ * wrapper around our standard winston logging to console and logfile
235
+ *
236
+ * @param {boolean} [noLogFile] optional flag to indicate if we should log to file; CLI logs are always on
237
+ * @returns {object} initiated logger for console and file
238
+ */
239
+ _createNewLoggerTransport: function (noLogFile = false) {
240
+ // {
241
+ // error: 0,
242
+ // warn: 1,
243
+ // info: 2,
244
+ // http: 3,
245
+ // verbose: 4,
246
+ // debug: 5,
247
+ // silly: 6
248
+ // }
249
+ if (
250
+ process.env.VSCODE_AMD_ENTRYPOINT === 'vs/workbench/api/node/extensionHostProcess' ||
251
+ process.env.VSCODE_CRASH_REPORTER_PROCESS_TYPE === 'extensionHost'
252
+ ) {
253
+ Util.OPTIONS.noLogColors = true;
254
+ }
255
+ const logFileName = new Date().toISOString().split(':').join('.');
256
+ const transports = {
257
+ console: new winston.transports.Console({
258
+ // Write logs to Console
259
+ level: Util.OPTIONS.loggerLevel || 'info',
260
+ format: winston.format.combine(
261
+ Util.OPTIONS.noLogColors
262
+ ? winston.format.uncolorize()
263
+ : winston.format.colorize(),
264
+ winston.format.timestamp({ format: 'HH:mm:ss' }),
265
+ winston.format.simple(),
266
+ winston.format.printf(
267
+ (info) => `${info.timestamp} ${info.level}: ${info.message}`
268
+ )
269
+ ),
270
+ }),
271
+ };
272
+ if (!noLogFile) {
273
+ transports.file = new winston.transports.File({
274
+ // Write logs to logfile
275
+ filename: 'logs/' + logFileName + '.log',
276
+ level: 'debug', // log everything
277
+ format: winston.format.combine(
278
+ winston.format.uncolorize(),
279
+ winston.format.timestamp({ format: 'HH:mm:ss.SSS' }),
280
+ winston.format.simple(),
281
+ winston.format.printf(
282
+ (info) => `${info.timestamp} ${info.level}: ${info.message}`
283
+ )
284
+ ),
285
+ });
286
+ transports.fileError = new winston.transports.File({
287
+ // Write logs to additional error-logfile for better visibility of errors
288
+ filename: 'logs/' + logFileName + '-errors.log',
289
+ level: 'error', // only log errors
290
+ lazy: true, // if true, log files will be created on demand, not at the initialization time.
291
+ format: winston.format.combine(
292
+ winston.format.uncolorize(),
293
+ winston.format.timestamp({ format: 'HH:mm:ss.SSS' }),
294
+ winston.format.simple(),
295
+ winston.format.printf(
296
+ (info) => `${info.timestamp} ${info.level}: ${info.message}`
297
+ )
298
+ ),
299
+ });
300
+ }
301
+ return transports;
302
+ },
230
303
 
231
304
  loggerTransports: null,
232
305
  /**
@@ -235,7 +308,91 @@ const Util = {
235
308
  * @type {TYPE.Logger}
236
309
  */
237
310
  logger: null,
238
- restartLogger: startLogger,
311
+ /**
312
+ * initiate winston logger
313
+ *
314
+ * @param {boolean} [restart] if true, logger will be restarted; otherwise, an existing logger will be used
315
+ * @param {boolean} [noLogFile] if false, logger will log to file; otherwise, only to console
316
+ * @returns {void}
317
+ */
318
+ startLogger: function (restart = false, noLogFile = false) {
319
+ if (
320
+ !(
321
+ Util.loggerTransports === null ||
322
+ restart ||
323
+ (!Util.loggerTransports?.file && !noLogFile && !Util.OPTIONS?.noLogFile)
324
+ )
325
+ ) {
326
+ // logger already started
327
+ return;
328
+ }
329
+ Util.loggerTransports = this._createNewLoggerTransport(
330
+ noLogFile || Util.OPTIONS?.noLogFile
331
+ );
332
+ const myWinston = winston.createLogger({
333
+ level: Util.OPTIONS.loggerLevel,
334
+ levels: winston.config.npm.levels,
335
+ transports: Object.values(Util.loggerTransports),
336
+ });
337
+ const winstonError = myWinston.error;
338
+ const winstonExtension = {
339
+ /**
340
+ * helper that prints better stack trace for errors
341
+ *
342
+ * @param {Error} ex the error
343
+ * @param {string} [message] optional custom message to be printed as error together with the exception's message
344
+ * @returns {void}
345
+ */
346
+ errorStack: function (ex, message) {
347
+ if (message) {
348
+ // ! this method only sets exitCode=1 if message-param was set
349
+ // if not, then this method purely outputs debug information and should not change the exitCode
350
+ winstonError(message + ':');
351
+ winstonError(` ${ex.message} (${ex.code})`);
352
+ if (ex.endpoint) {
353
+ // ex.endpoint is only available if 'ex' is of type RestError
354
+ winstonError(' endpoint: ' + ex.endpoint);
355
+ }
356
+ Util.signalFatalError();
357
+ }
358
+ let stack;
359
+ /* eslint-disable unicorn/prefer-ternary */
360
+ if (
361
+ [
362
+ 'ETIMEDOUT',
363
+ 'EHOSTUNREACH',
364
+ 'ENOTFOUND',
365
+ 'ECONNRESET',
366
+ 'ECONNABORTED',
367
+ ].includes(ex.code)
368
+ ) {
369
+ // the stack would just return a one-liner that does not help
370
+ stack = new Error().stack; // eslint-disable-line unicorn/error-message
371
+ } else {
372
+ stack = ex.stack;
373
+ }
374
+ /* eslint-enable unicorn/prefer-ternary */
375
+ myWinston.debug(stack);
376
+ },
377
+ /**
378
+ * errors should cause surrounding applications to take notice
379
+ * hence we overwrite the default error function here
380
+ *
381
+ * @param {string} msg - the message to log
382
+ * @returns {void}
383
+ */
384
+ error: function (msg) {
385
+ winstonError(msg);
386
+ Util.signalFatalError();
387
+ },
388
+ };
389
+ Util.logger = Object.assign(myWinston, winstonExtension);
390
+
391
+ const processArgv = process.argv.slice(2);
392
+ Util.logger.debug(
393
+ `:: mcdev ${packageJsonMcdev.version} :: ⚡ mcdev ${processArgv.join(' ')}`
394
+ );
395
+ },
239
396
  /**
240
397
  * Logger helper for Metadata functions
241
398
  *
@@ -296,6 +453,7 @@ const Util = {
296
453
  }
297
454
  return str;
298
455
  },
456
+
299
457
  /**
300
458
  * get key of an object based on the first matching value
301
459
  *
@@ -312,6 +470,31 @@ const Util = {
312
470
  throw new Error(`${val} not found in object`);
313
471
  },
314
472
 
473
+ /**
474
+ *helper for Mcdev.fixKeys. Retrieve dependent metadata
475
+ *
476
+ * @param {string} fixedType type of the metadata passed as a parameter to fixKeys function
477
+ * @returns {string[]} array of types that depend on the given type
478
+ */
479
+ getDependentMetadata(fixedType) {
480
+ const dependencies = new Set();
481
+
482
+ for (const dependentType of Object.keys(MetadataDefinitions)) {
483
+ if (MetadataDefinitions[dependentType].dependencies.includes(fixedType)) {
484
+ // fixedType was found as a dependency of dependentType
485
+ dependencies.add(dependentType);
486
+ } else if (
487
+ MetadataDefinitions[dependentType].dependencies.some((dependency) =>
488
+ dependency.startsWith(fixedType + '-')
489
+ )
490
+ ) {
491
+ // if MetadataTypeDefinitions[dependentType].dependencies start with type then also add dependentType to the set; use some to check if any of the dependencies start with type
492
+ dependencies.add(dependentType);
493
+ }
494
+ }
495
+ return [...dependencies];
496
+ },
497
+
315
498
  /**
316
499
  * Returns Order in which metadata needs to be retrieved/deployed
317
500
  *
@@ -416,7 +599,7 @@ const Util = {
416
599
  * @param {string} cmd to be executed command
417
600
  * @param {string[]} [args] list of arguments
418
601
  * @param {boolean} [hideOutput] if true, output of command will be hidden from CLI
419
- * @returns {string} output of command if hideOutput is true
602
+ * @returns {string|void} output of command if hideOutput is true
420
603
  */
421
604
  execSync(cmd, args, hideOutput) {
422
605
  args ||= [];
@@ -471,34 +654,30 @@ const Util = {
471
654
  * @returns {void}
472
655
  */
473
656
  setLoggingLevel(argv) {
474
- Util.loggerTransports.console.file = 'debug';
475
657
  if (argv.silent) {
476
658
  // only errors printed to CLI
477
- Util.logger.level = 'error';
478
659
  Util.OPTIONS.loggerLevel = 'error';
479
- Util.loggerTransports.console.level = 'error';
480
660
  Util.logger.debug('CLI logger set to: silent');
481
661
  } else if (argv.verbose) {
482
662
  // chatty user cli logs
483
- Util.logger.level = 'verbose';
484
663
  Util.OPTIONS.loggerLevel = 'verbose';
485
- Util.loggerTransports.console.level = 'verbose';
486
664
  Util.logger.debug('CLI logger set to: verbose');
487
665
  } else {
488
666
  // default user cli logs
489
- // TODO to be switched to "warn" when cli-process is integrated
490
- Util.logger.level = 'info';
491
667
  Util.OPTIONS.loggerLevel = 'info';
492
- Util.loggerTransports.console.level = 'info';
493
668
  Util.logger.debug('CLI logger set to: info / default');
494
669
  }
495
670
  if (argv.debug) {
496
671
  // enables developer output & features. no change to actual logs
497
- Util.logger.level = 'debug';
498
672
  Util.OPTIONS.loggerLevel = 'debug';
499
- Util.loggerTransports.console.level = 'debug';
500
673
  Util.logger.debug('CLI logger set to: debug');
501
674
  }
675
+ if (Util.loggerTransports?.console) {
676
+ Util.loggerTransports.console.level = Util.OPTIONS.loggerLevel;
677
+ }
678
+ if (Util.logger) {
679
+ Util.logger.level = Util.OPTIONS.loggerLevel;
680
+ }
502
681
  },
503
682
  /**
504
683
  * outputs a warning that the given type is still in beta
@@ -598,7 +777,7 @@ const Util = {
598
777
  });
599
778
  },
600
779
  /**
601
- * helper for {@link Asset._extractCode} and {@link Script.prepExtractedCode} to determine if a code block is a valid SSJS block
780
+ * helper for Asset.extractCode and Script.prepExtractedCode to determine if a code block is a valid SSJS block
602
781
  *
603
782
  * @example the following is invalid:
604
783
  * <script runat="server">
@@ -642,123 +821,75 @@ const Util = {
642
821
  // no script found
643
822
  return null;
644
823
  },
645
- };
646
- /**
647
- * wrapper around our standard winston logging to console and logfile
648
- *
649
- * @returns {object} initiated logger for console and file
650
- */
651
- function createNewLoggerTransport() {
652
- // {
653
- // error: 0,
654
- // warn: 1,
655
- // info: 2,
656
- // http: 3,
657
- // verbose: 4,
658
- // debug: 5,
659
- // silly: 6
660
- // }
661
- const logFileName = new Date().toISOString().split(':').join('.');
662
- return {
663
- console: new winston.transports.Console({
664
- // Write logs to Console
665
- level: 'info', // log error, warn, info
666
- format: winston.format.combine(
667
- winston.format.colorize(),
668
- winston.format.timestamp({ format: 'HH:mm:ss' }),
669
- winston.format.simple(),
670
- winston.format.printf((info) => `${info.timestamp} ${info.level}: ${info.message}`)
671
- ),
672
- }),
673
- file: new winston.transports.File({
674
- // Write logs to logfile
675
- filename: 'logs/' + logFileName + '.log',
676
- level: 'debug', // log everything
677
- format: winston.format.combine(
678
- winston.format.timestamp({ format: 'HH:mm:ss.SSS' }),
679
- winston.format.simple(),
680
- winston.format.printf((info) => `${info.timestamp} ${info.level}: ${info.message}`)
681
- ),
682
- }),
683
- fileError: new winston.transports.File({
684
- // Write logs to additional error-logfile for better visibility of errors
685
- filename: 'logs/' + logFileName + '-errors.log',
686
- level: 'error', // only log errors
687
- format: winston.format.combine(
688
- winston.format.timestamp({ format: 'HH:mm:ss.SSS' }),
689
- winston.format.simple(),
690
- winston.format.printf((info) => `${info.timestamp} ${info.level}: ${info.message}`)
691
- ),
692
- }),
693
- };
694
- }
695
- /**
696
- * initiate winston logger
697
- *
698
- * @returns {void}
699
- */
700
- function startLogger() {
701
- Util.loggerTransports = createNewLoggerTransport();
702
- const myWinston = winston.createLogger({
703
- levels: winston.config.npm.levels,
704
- transports: [
705
- Util.loggerTransports.console,
706
- Util.loggerTransports.file,
707
- Util.loggerTransports.fileError,
708
- ],
709
- });
710
- const winstonError = myWinston.error;
711
- const winstonExtension = {
712
- /**
713
- * helper that prints better stack trace for errors
714
- *
715
- * @param {Error} ex the error
716
- * @param {string} [message] optional custom message to be printed as error together with the exception's message
717
- * @returns {void}
718
- */
719
- errorStack: function (ex, message) {
720
- if (message) {
721
- // ! this method only sets exitCode=1 if message-param was set
722
- // if not, then this method purely outputs debug information and should not change the exitCode
723
- winstonError(message + ':');
724
- winstonError(` ${ex.message} (${ex.code})`);
725
- if (ex.endpoint) {
726
- // ex.endpoint is only available if 'ex' is of type RestError
727
- winstonError(' endpoint: ' + ex.endpoint);
728
- }
729
- Util.signalFatalError();
730
- }
731
- let stack;
732
- /* eslint-disable unicorn/prefer-ternary */
733
- if (
734
- ['ETIMEDOUT', 'EHOSTUNREACH', 'ENOTFOUND', 'ECONNRESET', 'ECONNABORTED'].includes(
735
- ex.code
736
- )
737
- ) {
738
- // the stack would just return a one-liner that does not help
739
- stack = new Error().stack; // eslint-disable-line unicorn/error-message
824
+ /**
825
+ * allows us to filter just like with SQL's LIKE operator
826
+ *
827
+ * @param {string} testString field value to test
828
+ * @param {string} search search string in SQL LIKE format
829
+ * @returns {boolean} true if testString matches search
830
+ */
831
+ stringLike(testString, search) {
832
+ if (typeof search !== 'string' || this === null) {
833
+ return false;
834
+ }
835
+ // Remove special chars
836
+ search = search.replaceAll(
837
+ new RegExp('([\\.\\\\\\+\\*\\?\\[\\^\\]\\$\\(\\)\\{\\}\\=\\!\\<\\>\\|\\:\\-])', 'g'),
838
+ '\\$1'
839
+ );
840
+ // Replace % and _ with equivalent regex
841
+ search = search.replaceAll('%', '.*').replaceAll('_', '.');
842
+ // Check matches
843
+ return new RegExp('^' + search + '$', 'gi').test(testString);
844
+ },
845
+ /**
846
+ * returns true if no LIKE filter is defined or if all filters match
847
+ *
848
+ * @param {TYPE.MetadataTypeItem} metadata a single metadata item
849
+ * @param {object} [filters] only used in recursive calls
850
+ * @returns {boolean} true if no LIKE filter is defined or if all filters match
851
+ */
852
+ fieldsLike(metadata, filters) {
853
+ if (metadata.json && metadata.codeArr) {
854
+ // Compensate for CodeExtractItem format
855
+ metadata = metadata.json;
856
+ }
857
+ filters ||= Util.OPTIONS.like;
858
+ if (!filters) {
859
+ return true;
860
+ }
861
+ const fields = Object.keys(filters);
862
+ return fields.every((field) => {
863
+ // to allow passing in an array via cli, e.g. --like=field1,field2, we need to convert comma separated lists into arrays
864
+ const filter =
865
+ typeof filters[field] === 'string' && filters[field].includes(',')
866
+ ? filters[field].split(',')
867
+ : filters[field];
868
+ if (Array.isArray(metadata[field])) {
869
+ return metadata[field].some((f) => Util.fieldsLike(f, filter));
740
870
  } else {
741
- stack = ex.stack;
871
+ if (typeof filter === 'string') {
872
+ return Util.stringLike(metadata[field], filter);
873
+ } else if (Array.isArray(filter)) {
874
+ return filter.some((f) => Util.stringLike(metadata[field], f));
875
+ } else if (typeof filter === 'object') {
876
+ return Util.fieldsLike(metadata[field], filter);
877
+ }
742
878
  }
743
- /* eslint-enable unicorn/prefer-ternary */
744
- myWinston.debug(stack);
745
- },
746
- /**
747
- * errors should cause surrounding applications to take notice
748
- * hence we overwrite the default error function here
749
- *
750
- * @param {string} msg - the message to log
751
- * @returns {void}
752
- */
753
- error: function (msg) {
754
- winstonError(msg);
755
- Util.signalFatalError();
756
- },
757
- };
758
- Util.logger = Object.assign(myWinston, winstonExtension);
879
+ return false;
880
+ });
881
+ },
882
+ /**
883
+ * helper used by SOAP methods to ensure the type always uses an upper-cased first letter
884
+ *
885
+ * @param {string} str string to capitalize
886
+ * @returns {string} str with first letter capitalized
887
+ */
888
+ capitalizeFirstLetter(str) {
889
+ return str.charAt(0).toUpperCase() + str.slice(1);
890
+ },
891
+ };
759
892
 
760
- Util.logger.debug(`:: mcdev ${packageJsonMcdev.version} ::`);
761
- }
762
- startLogger();
893
+ Util.startLogger(false, true);
763
894
 
764
895
  module.exports = Util;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcdev",
3
- "version": "5.0.2",
3
+ "version": "5.2.0",
4
4
  "description": "Accenture Salesforce Marketing Cloud DevTools",
5
5
  "author": "Accenture: joern.berkefeld, douglas.midgley, robert.zimmermann, maciej.barnas",
6
6
  "license": "MIT",
@@ -63,7 +63,7 @@
63
63
  "command-exists": "1.2.9",
64
64
  "conf": "10.2.0",
65
65
  "console.table": "0.10.0",
66
- "deep-equal": "2.2.1",
66
+ "deep-equal": "2.2.2",
67
67
  "fs-extra": "11.1.0",
68
68
  "inquirer": "8.2.5",
69
69
  "json-to-table": "4.2.1",
@@ -71,30 +71,30 @@
71
71
  "p-limit": "3.1.0",
72
72
  "prettier": "2.8.8",
73
73
  "prettier-plugin-sql": "0.14.0",
74
- "semver": "7.5.0",
74
+ "semver": "7.5.4",
75
75
  "sfmc-sdk": "1.0.1",
76
76
  "simple-git": "3.18.0",
77
77
  "toposort": "2.0.2",
78
78
  "update-notifier": "5.1.0",
79
- "winston": "3.8.2",
79
+ "winston": "3.10.0",
80
80
  "yargs": "17.7.2"
81
81
  },
82
82
  "devDependencies": {
83
83
  "assert": "2.0.0",
84
- "axios-mock-adapter": "1.21.3",
84
+ "axios-mock-adapter": "1.21.5",
85
85
  "chai": "4.3.7",
86
86
  "chai-files": "1.4.0",
87
- "eslint": "8.41.0",
88
- "eslint-config-prettier": "8.7.0",
87
+ "eslint": "8.46.0",
88
+ "eslint-config-prettier": "9.0.0",
89
89
  "eslint-config-ssjs": "1.1.11",
90
- "eslint-plugin-jsdoc": "45.0.0",
90
+ "eslint-plugin-jsdoc": "46.4.6",
91
91
  "eslint-plugin-mocha": "10.1.0",
92
92
  "eslint-plugin-prettier": "4.2.1",
93
- "eslint-plugin-unicorn": "47.0.0",
94
- "fast-xml-parser": "4.2.2",
93
+ "eslint-plugin-unicorn": "48.0.0",
94
+ "fast-xml-parser": "4.2.7",
95
95
  "husky": "8.0.3",
96
96
  "jsdoc-to-markdown": "8.0.0",
97
- "lint-staged": "13.2.2",
97
+ "lint-staged": "13.2.3",
98
98
  "mocha": "10.2.0",
99
99
  "mock-fs": "5.2.0",
100
100
  "npm-check": "6.0.1",
@@ -14,6 +14,22 @@ describe('GENERAL', () => {
14
14
  testUtils.mockReset();
15
15
  });
16
16
 
17
+ describe('init ================', () => {
18
+ it('should init a local project without downloading BUs');
19
+ it('should init a local project and download all BUs');
20
+ });
21
+ describe('join ================', () => {
22
+ it('should clone a project from git');
23
+ });
24
+ describe('upgrade ================', () => {
25
+ it('should upgrade a project to the latest version');
26
+ });
27
+ describe('reloadBUs ================', () => {
28
+ it('should load all BUs from the server and refresh the config');
29
+ });
30
+ describe('selectTypes ================', () => {
31
+ it('should change which types are selected for default retrieval');
32
+ });
17
33
  describe('explainTypes ================', () => {
18
34
  it('without options', () => {
19
35
  handler.explainTypes();
@@ -59,4 +75,14 @@ describe('GENERAL', () => {
59
75
  return;
60
76
  });
61
77
  });
78
+ describe('createDeltaPkg ================', () => {
79
+ it('should show diff to master branch');
80
+ // mcdev createDeltaPkg master # resolves to master..HEAD
81
+ it('should show diff between master and develop branch');
82
+ // mcdev createDeltaPkg master..develop
83
+ it(
84
+ 'should show diff between master and develop branch and filter the results to only show MyProject/BU1'
85
+ );
86
+ // mcdev createDeltaPkg master..develop --filter 'MyProject/BU1'
87
+ });
62
88
  });
@@ -78,5 +78,5 @@
78
78
  "triggeredSend"
79
79
  ]
80
80
  },
81
- "version": "5.0.2"
81
+ "version": "5.2.0"
82
82
  }