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.
- package/.coverage-comment-template.svelte +177 -161
- package/.eslintrc.json +4 -4
- package/.github/ISSUE_TEMPLATE/bug.yml +2 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +2 -2
- package/.github/dependabot.yml +8 -0
- package/.github/workflows/coverage-base-update.yml +6 -2
- package/.github/workflows/coverage-develop-branch.yml +7 -8
- package/.github/workflows/coverage-main-branch.yml +7 -8
- package/.github/workflows/coverage.yml +7 -4
- package/.husky/post-checkout +4 -2
- package/.husky/post-merge +1 -0
- package/.vscode/extensions.json +4 -0
- package/docs/dist/documentation.md +756 -294
- package/lib/Deployer.js +28 -28
- package/lib/MetadataTypeDefinitions.js +1 -1
- package/lib/MetadataTypeInfo.js +1 -1
- package/lib/Retriever.js +1 -1
- package/lib/cli.js +184 -6
- package/lib/index.js +493 -22
- package/lib/metadataTypes/Asset.js +10 -11
- package/lib/metadataTypes/AttributeGroup.js +76 -2
- package/lib/metadataTypes/AttributeSet.js +260 -0
- package/lib/metadataTypes/Automation.js +771 -247
- package/lib/metadataTypes/DataExtension.js +7 -7
- package/lib/metadataTypes/DataExtensionField.js +1 -1
- package/lib/metadataTypes/Event.js +2 -3
- package/lib/metadataTypes/Folder.js +1 -1
- package/lib/metadataTypes/Journey.js +5 -6
- package/lib/metadataTypes/MetadataType.js +187 -60
- package/lib/metadataTypes/MobileKeyword.js +8 -8
- package/lib/metadataTypes/MobileMessage.js +5 -5
- package/lib/metadataTypes/Query.js +47 -5
- package/lib/metadataTypes/Script.js +3 -3
- package/lib/metadataTypes/TransactionalSMS.js +5 -5
- package/lib/metadataTypes/TriggeredSend.js +25 -50
- package/lib/metadataTypes/User.js +7 -4
- package/lib/metadataTypes/definitions/Asset.definition.js +1 -0
- package/lib/metadataTypes/definitions/AttributeGroup.definition.js +117 -106
- package/lib/metadataTypes/definitions/{SetDefinition.definition.js → AttributeSet.definition.js} +54 -27
- package/lib/metadataTypes/definitions/Automation.definition.js +74 -21
- package/lib/metadataTypes/definitions/DataExtension.definition.js +1 -0
- package/lib/metadataTypes/definitions/DataExtract.definition.js +1 -0
- package/lib/metadataTypes/definitions/EmailSend.definition.js +1 -0
- package/lib/metadataTypes/definitions/Event.definition.js +1 -0
- package/lib/metadataTypes/definitions/Filter.definition.js +1 -0
- package/lib/metadataTypes/definitions/ImportFile.definition.js +37 -6
- package/lib/metadataTypes/definitions/MobileKeyword.definition.js +1 -0
- package/lib/metadataTypes/definitions/Query.definition.js +1 -0
- package/lib/metadataTypes/definitions/Role.definition.js +1 -0
- package/lib/metadataTypes/definitions/TriggeredSend.definition.js +2 -0
- package/lib/metadataTypes/definitions/User.definition.js +1 -0
- package/lib/util/cache.js +9 -4
- package/lib/util/cli.js +40 -0
- package/lib/util/devops.js +13 -11
- package/lib/util/file.js +2 -2
- package/lib/util/init.js +84 -0
- package/lib/util/util.js +268 -137
- package/package.json +11 -11
- package/test/general.test.js +26 -0
- package/test/mockRoot/.mcdevrc.json +1 -1
- package/test/mockRoot/deploy/testInstance/testBU/automation/testExisting_automation.automation-meta.json +52 -0
- package/test/mockRoot/deploy/testInstance/testBU/automation/testNew_automation.automation-meta.json +45 -0
- package/test/mockRoot/deploy/testInstance/testBU/dataExtract/testExisting_dataExtract.dataExtract-meta.json +35 -0
- package/test/mockRoot/deploy/testInstance/testBU/dataExtract/testNew_dataExtract.dataExtract-meta.json +35 -0
- package/test/mockRoot/deploy/testInstance/testBU/fileTransfer/testExisting_fileTransfer.fileTransfer-meta.json +17 -0
- package/test/mockRoot/deploy/testInstance/testBU/fileTransfer/testNew_fileTransfer.fileTransfer-meta.json +17 -0
- package/test/mockRoot/deploy/testInstance/testBU/importFile/testExisting_importFile.importFile-meta.json +29 -0
- package/test/mockRoot/deploy/testInstance/testBU/importFile/testNew_importFile.importFile-meta.json +29 -0
- package/test/mockRoot/deploy/testInstance/testBU/query/{testExistingQuery.query-meta.json → testExisting_query.query-meta.json} +2 -2
- package/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query_fixKeys.query-meta.json +11 -0
- package/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query_fixKeys.query-meta.sql +6 -0
- package/test/mockRoot/deploy/testInstance/testBU/query/{testNewQuery.query-meta.json → testNew_query.query-meta.json} +2 -2
- package/test/mockRoot/deploy/testInstance/testBU/script/testExisting_script.script-meta.json +6 -0
- package/test/mockRoot/deploy/testInstance/testBU/script/testExisting_script.script-meta.ssjs +1 -0
- package/test/mockRoot/deploy/testInstance/testBU/script/testNew_script.script-meta.json +6 -0
- package/test/mockRoot/deploy/testInstance/testBU/script/testNew_script.script-meta.ssjs +1 -0
- package/test/mockRoot/deploy/testInstance/testBU/triggeredSend/testExisting_triggeredSend.triggeredSend-meta.json +29 -0
- package/test/mockRoot/deploy/testInstance/testBU/triggeredSend/testNew_triggeredSend.triggeredSend-meta.json +29 -0
- package/test/resourceFactory.js +132 -24
- package/test/resources/1111111/accountUser/retrieve-ActiveFlag=falseANDCustomerKey=testExisting_userANDEmaillike@-response.xml +27 -0
- package/test/resources/1111111/accountUser/retrieve-ActiveFlag=falseANDEmaillike@-response.xml +156 -0
- package/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDEmailisNullORNamelikeapp userANDMustChangePassword=false-response.xml +87 -0
- package/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDEmaillike@-response.xml +156 -0
- package/test/resources/1111111/accountUser/retrieve-CustomerKey=testExisting_userANDActiveFlag=trueANDEmailisNullORNamelikeapp userANDMustChangePassword=false-response.xml +27 -0
- package/test/resources/1111111/accountUserAccount/retrieve-AccountUser.AccountUserID=700301950-response.xml +60 -0
- package/test/resources/1111111/user/retrieve-expected.md +4 -2
- package/test/resources/9999999/attributeGroup/retrieve-expected.json +25 -0
- package/test/resources/9999999/attributeSet/retrieve-expected.json +748 -0
- package/test/resources/9999999/automation/build-expected.json +57 -0
- package/test/resources/9999999/automation/create-expected.json +45 -0
- package/test/resources/9999999/automation/create-testNew_automation-expected.md +28 -0
- package/test/resources/9999999/automation/delete-response.xml +40 -0
- package/test/resources/9999999/automation/patch_fixKeys-pause-expected.json +44 -0
- package/test/resources/9999999/automation/patch_fixKeys-schedule-expected.json +44 -0
- package/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml +42 -0
- package/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-fixKey_pause-response.xml +42 -0
- package/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-fixKey_schedule-response.xml +42 -0
- package/test/resources/9999999/automation/perform-a8afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml +42 -0
- package/test/resources/9999999/automation/retrieve-expected.json +57 -0
- package/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md +30 -0
- package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml +52 -0
- package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-ad2e-pause-response.xml +38 -0
- package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-fixKey_pause-response.xml +52 -0
- package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-fixKey_schedule-response.xml +52 -0
- package/test/resources/9999999/automation/schedule-a8afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml +52 -0
- package/test/resources/9999999/automation/template-expected.json +57 -0
- package/test/resources/9999999/automation/update-expected.json +45 -0
- package/test/resources/9999999/automation/update-testExisting_automation-expected.md +28 -0
- package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json +85 -0
- package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/patch-response.json +85 -0
- package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-pause/get-response.json +85 -0
- package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-pause/patch-response.json +85 -0
- package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_pause/get-response.json +85 -0
- package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_pause/patch-response.json +85 -0
- package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_schedule/get-response.json +85 -0
- package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_schedule/patch-response.json +85 -0
- package/test/resources/9999999/automation/v1/automations/a8afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json +85 -0
- package/test/resources/9999999/automation/v1/automations/post-response.json +86 -0
- package/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/get-response.json +38 -0
- package/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/patch-response.json +38 -0
- package/test/resources/9999999/automation/v1/dataextracts/get-response.json +20 -0
- package/test/resources/9999999/automation/v1/dataextracts/post-response.json +38 -0
- package/test/resources/9999999/automation/v1/dataextracttypes/get-response.json +50 -0
- package/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/get-response.json +18 -0
- package/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/patch-response.json +18 -0
- package/test/resources/9999999/automation/v1/filetransfers/get-response.json +15 -0
- package/test/resources/9999999/automation/v1/filetransfers/post-response.json +18 -0
- package/test/resources/9999999/automation/v1/ftplocations/get-response.json +18 -0
- package/test/resources/9999999/automation/v1/imports/9d16f42c-2260-ed11-b849-48df37d1de8b/patch-response.json +31 -0
- package/test/resources/9999999/automation/v1/imports/get-response.json +38 -0
- package/test/resources/9999999/automation/v1/imports/post-response.json +30 -0
- package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dae/actions/start/post-response.txt +1 -0
- package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/actions/start/post-response.txt +1 -0
- package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/get-response.json +2 -2
- package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/patch-response.json +2 -2
- package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeys/get-response.json +17 -0
- package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeys/patch-response.json +18 -0
- package/test/resources/9999999/automation/v1/queries/get-response.json +22 -5
- package/test/resources/9999999/automation/v1/queries/post-response.json +2 -2
- package/test/resources/9999999/automation/v1/scripts/39f6a488-20eb-4ba0-b0b9-023725b574e4/patch-response.json +10 -0
- package/test/resources/9999999/automation/v1/scripts/get-response.json +27 -0
- package/test/resources/9999999/automation/v1/scripts/post-response.json +10 -0
- package/test/resources/9999999/dataExtension/retrieve-Name=testExisting_dataExtension-response.xml +52 -0
- package/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testExisting_dataExtension-response.xml +98 -0
- package/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_dataExtensionORDataExtension.CustomerKey=testExisting_dataExtension-response.xml +99 -0
- package/test/resources/9999999/dataExtract/build-expected.json +35 -0
- package/test/resources/9999999/dataExtract/get-expected.json +39 -0
- package/test/resources/9999999/dataExtract/patch-expected.json +37 -0
- package/test/resources/9999999/dataExtract/post-expected.json +37 -0
- package/test/resources/9999999/dataExtract/template-expected.json +35 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentType=automations-response.xml +48 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentType=contextual_suppression_listORContentType=publicationORContentType=suppression_listORContentType=mysubsORContentType=list-response.xml +136 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentType=queryactivity-response.xml +48 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentType=ssjsactivity-response.xml +48 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentType=triggered_send_journeybuilderORContentType=triggered_sendORContentType=hidden-response.xml +276 -0
- package/test/resources/9999999/dataFolder/retrieve-response.xml +45 -0
- package/test/resources/9999999/email/retrieve-response.xml +203 -0
- package/test/resources/9999999/emailSendDefinition/retrieve-IsPlatformObject=falseANDDescriptionnotEqualsSFSendDefinition-response.xml +85 -0
- package/test/resources/9999999/fileTransfer/build-expected.json +15 -0
- package/test/resources/9999999/fileTransfer/get-expected.json +17 -0
- package/test/resources/9999999/fileTransfer/patch-expected.json +17 -0
- package/test/resources/9999999/fileTransfer/post-expected.json +17 -0
- package/test/resources/9999999/fileTransfer/template-expected.json +15 -0
- package/test/resources/9999999/hub/v1/contacts/schema/attributeGroups/get-response.json +585 -0
- package/test/resources/9999999/hub/v1/contacts/schema/setDefinitions/get-response.json +19807 -0
- package/test/resources/9999999/importFile/build-expected.json +27 -0
- package/test/resources/9999999/importFile/get-expected.json +29 -0
- package/test/resources/9999999/importFile/patch-expected.json +29 -0
- package/test/resources/9999999/importFile/post-expected.json +29 -0
- package/test/resources/9999999/importFile/template-expected.json +27 -0
- package/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/get-response.json +21 -0
- package/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/post-response.json +0 -0
- package/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/get-response.json +30 -0
- package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation-response.xml +30 -0
- package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixKey_pause-response.xml +32 -0
- package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixKey_schedule-response.xml +32 -0
- package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixedKey_paused-response.xml +32 -0
- package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixedKey_scheduled-response.xml +32 -0
- package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_pause-response.xml +30 -0
- package/test/resources/9999999/program/retrieve-CustomerKey=testNew_automation-response.xml +30 -0
- package/test/resources/9999999/program/retrieve-Name=testExisting_automation-response.xml +31 -0
- package/test/resources/9999999/program/retrieve-response.xml +50 -0
- package/test/resources/9999999/query/build-expected.json +2 -2
- package/test/resources/9999999/query/get-expected.json +2 -2
- package/test/resources/9999999/query/get2-expected.json +2 -2
- package/test/resources/9999999/query/patch-expected.json +2 -2
- package/test/resources/9999999/query/patch_fixKeys-expected.json +11 -0
- package/test/resources/9999999/query/patch_fixKeys-expected.sql +6 -0
- package/test/resources/9999999/query/post-expected.json +2 -2
- package/test/resources/9999999/query/template-expected.json +2 -2
- package/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixKeysANDStatus=Active-response.xml +30 -0
- package/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixedKeysANDStatus=Active-response.xml +30 -0
- package/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testNew_queryANDStatus=Active-response.xml +30 -0
- package/test/resources/9999999/script/build-expected.json +6 -0
- package/test/resources/9999999/script/build-expected.ssjs +1 -0
- package/test/resources/9999999/script/get-expected.json +8 -0
- package/test/resources/9999999/script/get-expected.ssjs +1 -0
- package/test/resources/9999999/script/get_noScriptTag-expected.html +1 -0
- package/test/resources/9999999/script/get_noScriptTag-expected.json +8 -0
- package/test/resources/9999999/script/patch-expected.json +8 -0
- package/test/resources/9999999/script/patch-expected.ssjs +1 -0
- package/test/resources/9999999/script/post-expected.json +8 -0
- package/test/resources/9999999/script/post-expected.ssjs +1 -0
- package/test/resources/9999999/script/template-expected.json +6 -0
- package/test/resources/9999999/script/template-expected.ssjs +1 -0
- package/test/resources/9999999/triggeredSend/build-expected.json +29 -0
- package/test/resources/9999999/triggeredSend/get-expected.json +29 -0
- package/test/resources/9999999/triggeredSend/patch-expected.json +29 -0
- package/test/resources/9999999/triggeredSend/post-expected.json +29 -0
- package/test/resources/9999999/triggeredSend/template-expected.json +29 -0
- package/test/resources/9999999/triggeredSendDefinition/create-response.xml +75 -0
- package/test/resources/9999999/triggeredSendDefinition/delete-response.xml +36 -0
- package/test/resources/9999999/triggeredSendDefinition/{retrieve-response.xml → retrieve-TriggeredSendStatusINNew,Active,Inactive,Moved,Canceled-response.xml} +4 -4
- package/test/resources/9999999/triggeredSendDefinition/update-response.xml +74 -0
- package/test/type.attributeGroup.test.js +55 -0
- package/test/type.attributeSet.test.js +55 -0
- package/test/type.automation.test.js +886 -0
- package/test/type.dataExtension.test.js +3 -1
- package/test/type.dataExtract.test.js +187 -0
- package/test/type.fileTransfer.test.js +185 -0
- package/test/type.importFile.test.js +186 -0
- package/test/type.mobileKeyword.test.js +0 -1
- package/test/type.query.test.js +497 -33
- package/test/type.script.test.js +367 -0
- package/test/type.triggeredSend.test.js +152 -0
- package/test/type.user.test.js +37 -11
- package/test/utils.js +10 -6
- package/.coverage-comment-template.md +0 -20
- package/lib/metadataTypes/SetDefinition.js +0 -37
- /package/test/mockRoot/deploy/testInstance/testBU/query/{testExistingQuery.query-meta.sql → testExisting_query.query-meta.sql} +0 -0
- /package/test/mockRoot/deploy/testInstance/testBU/query/{testNewQuery.query-meta.sql → testNew_query.query-meta.sql} +0 -0
- /package/test/resources/1111111/accountUser/{retrieve-response.xml → retrieve-ActiveFlag=trueANDCustomerKey=testExisting_userANDEmaillike@-response.xml} +0 -0
- /package/test/resources/1111111/accountUserAccount/{retrieve-response.xml → retrieve-AccountUser.AccountUserIDIN700301950,700301951,7471228-response.xml} +0 -0
- /package/test/resources/1111111/businessUnit/{retrieve-response.xml → retrieve-ID=1111111-response.xml} +0 -0
- /package/test/resources/1111111/list/{retrieve-response.xml → retrieve-CustomerKey=All SubscribersORListName=All Subscribers-response.xml} +0 -0
- /package/test/resources/1111111/role/{retrieve-response.xml → retrieve-IsPrivate=false-response.xml} +0 -0
- /package/test/resources/9999999/queryDefinition/{retrieve-response.xml → retrieve-CustomerKey=testExisting_queryANDStatus=Active-response.xml} +0 -0
|
@@ -59,8 +59,8 @@ class DataExtension extends MetadataType {
|
|
|
59
59
|
// output error & remove from deploy list
|
|
60
60
|
Util.logger.error(
|
|
61
61
|
` ☇ skipping ${this.definition.type} ${
|
|
62
|
-
metadataMap[this.definition.keyField]
|
|
63
|
-
} / ${metadataMap[this.definition.nameField]}: ${ex.message}`
|
|
62
|
+
metadataMap[metadataKey][this.definition.keyField]
|
|
63
|
+
} / ${metadataMap[metadataKey][this.definition.nameField]}: ${ex.message}`
|
|
64
64
|
);
|
|
65
65
|
delete metadataMap[metadataKey];
|
|
66
66
|
// skip rest of handling for this DE
|
|
@@ -203,7 +203,7 @@ class DataExtension extends MetadataType {
|
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
205
|
/**
|
|
206
|
-
* helper for {@link upsert}
|
|
206
|
+
* helper for {@link DataExtension.upsert}
|
|
207
207
|
*
|
|
208
208
|
* @private
|
|
209
209
|
* @param {object} res -
|
|
@@ -607,7 +607,7 @@ class DataExtension extends MetadataType {
|
|
|
607
607
|
metadata[customerKey].Fields = fieldArr;
|
|
608
608
|
}
|
|
609
609
|
/**
|
|
610
|
-
* helper for {@link
|
|
610
|
+
* helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} that removes old files after the key was changed
|
|
611
611
|
*
|
|
612
612
|
* @private
|
|
613
613
|
* @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
|
|
@@ -624,16 +624,16 @@ class DataExtension extends MetadataType {
|
|
|
624
624
|
* @returns {Promise.<TYPE.DataExtensionItem>} Promise of updated single DE
|
|
625
625
|
*/
|
|
626
626
|
static async preDeployTasks(metadata) {
|
|
627
|
-
if (metadata.Name
|
|
627
|
+
if (metadata.Name?.startsWith('_')) {
|
|
628
628
|
throw new Error(`Cannot Upsert Strongly Typed Data Extensions`);
|
|
629
629
|
}
|
|
630
630
|
if (
|
|
631
631
|
this.buObject.eid !== this.buObject.mid &&
|
|
632
|
-
metadata.r__folder_Path
|
|
632
|
+
metadata.r__folder_Path?.startsWith('Shared Items')
|
|
633
633
|
) {
|
|
634
634
|
throw new Error(`Cannot Create/Update a Shared Data Extension from the Child BU`);
|
|
635
635
|
}
|
|
636
|
-
if (metadata.r__folder_Path
|
|
636
|
+
if (metadata.r__folder_Path?.startsWith('Synchronized Data Extensions')) {
|
|
637
637
|
throw new Error(
|
|
638
638
|
`Cannot Create/Update a Synchronized Data Extension. Please use Contact Builder to maintain these`
|
|
639
639
|
);
|
|
@@ -31,7 +31,7 @@ class DataExtensionField extends MetadataType {
|
|
|
31
31
|
return super.retrieveSOAP(null, requestParams, null, additionalFields);
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
|
-
* helper for
|
|
34
|
+
* helper for DataExtension.retrieveFieldsForSingleDe that sorts the fields into an array
|
|
35
35
|
*
|
|
36
36
|
* @param {TYPE.DataExtensionFieldMap} fieldsObj customerKey-based list of fields for one dataExtension
|
|
37
37
|
* @returns {TYPE.DataExtensionFieldItem[]} sorted array of field objects
|
|
@@ -136,12 +136,11 @@ class Event extends MetadataType {
|
|
|
136
136
|
* @param {TYPE.MetadataTypeMap} metadata metadata mapped by their keyField
|
|
137
137
|
* @param {string} deployDir directory where deploy metadata are saved
|
|
138
138
|
* @param {string} retrieveDir directory where metadata after deploy should be saved
|
|
139
|
-
* @param {boolean} [isRefresh] optional flag - so far not used by eventDefinition
|
|
140
139
|
* @returns {Promise.<TYPE.MetadataTypeMap>} Promise of keyField => metadata map
|
|
141
140
|
*/
|
|
142
|
-
static async deploy(metadata, deployDir, retrieveDir
|
|
141
|
+
static async deploy(metadata, deployDir, retrieveDir) {
|
|
143
142
|
Util.logBeta(this.definition.type);
|
|
144
|
-
return super.deploy(metadata, deployDir, retrieveDir
|
|
143
|
+
return super.deploy(metadata, deployDir, retrieveDir);
|
|
145
144
|
}
|
|
146
145
|
|
|
147
146
|
/**
|
|
@@ -452,7 +452,7 @@ class Folder extends MetadataType {
|
|
|
452
452
|
* Returns file contents mapped to their filename without '.json' ending
|
|
453
453
|
*
|
|
454
454
|
* @param {string} dir directory that contains '.json' files to be read
|
|
455
|
-
* @param {boolean} [listBadKeys
|
|
455
|
+
* @param {boolean} [listBadKeys] do not print errors, used for badKeys()
|
|
456
456
|
* @returns {TYPE.MetadataTypeMap} fileName => fileContent map
|
|
457
457
|
*/
|
|
458
458
|
static getJsonFromFS(dir, listBadKeys) {
|
|
@@ -216,12 +216,11 @@ class Journey extends MetadataType {
|
|
|
216
216
|
* @param {TYPE.MetadataTypeMap} metadata metadata mapped by their keyField
|
|
217
217
|
* @param {string} deployDir directory where deploy metadata are saved
|
|
218
218
|
* @param {string} retrieveDir directory where metadata after deploy should be saved
|
|
219
|
-
* @param {boolean} [isRefresh] optional flag - so far not used by interaction
|
|
220
219
|
* @returns {Promise.<TYPE.MetadataTypeMap>} Promise of keyField => metadata map
|
|
221
220
|
*/
|
|
222
|
-
static async deploy(metadata, deployDir, retrieveDir
|
|
221
|
+
static async deploy(metadata, deployDir, retrieveDir) {
|
|
223
222
|
Util.logBeta(this.definition.type);
|
|
224
|
-
return super.deploy(metadata, deployDir, retrieveDir
|
|
223
|
+
return super.deploy(metadata, deployDir, retrieveDir);
|
|
225
224
|
}
|
|
226
225
|
|
|
227
226
|
/**
|
|
@@ -265,7 +264,7 @@ class Journey extends MetadataType {
|
|
|
265
264
|
}
|
|
266
265
|
|
|
267
266
|
/**
|
|
268
|
-
* helper for Journey's {@link saveResults}. Gets executed after retreive of metadata type and
|
|
267
|
+
* helper for Journey's {@link Journey.saveResults}. Gets executed after retreive of metadata type and
|
|
269
268
|
*
|
|
270
269
|
* @param {TYPE.MetadataTypeMap} metadataMap key=customer key, value=metadata
|
|
271
270
|
*/
|
|
@@ -478,7 +477,7 @@ class Journey extends MetadataType {
|
|
|
478
477
|
return metadata;
|
|
479
478
|
}
|
|
480
479
|
/**
|
|
481
|
-
* helper for {@link postRetrieveTasks}
|
|
480
|
+
* helper for {@link Journey.postRetrieveTasks}
|
|
482
481
|
*
|
|
483
482
|
* @private
|
|
484
483
|
* @param {TYPE.MetadataTypeItem} metadata a single item
|
|
@@ -800,7 +799,7 @@ class Journey extends MetadataType {
|
|
|
800
799
|
}
|
|
801
800
|
|
|
802
801
|
/**
|
|
803
|
-
* helper for {@link preDeployTasks}
|
|
802
|
+
* helper for {@link Journey.preDeployTasks}
|
|
804
803
|
*
|
|
805
804
|
* @private
|
|
806
805
|
* @param {TYPE.MetadataTypeItem} metadata a single item
|
|
@@ -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
|
|
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) {
|
|
@@ -58,15 +58,9 @@ class MetadataType {
|
|
|
58
58
|
if (key === fileNameWithoutEnding || listBadKeys) {
|
|
59
59
|
fileName2FileContent[fileNameWithoutEnding] = fileContent;
|
|
60
60
|
} else {
|
|
61
|
-
Util.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
'getJsonFromFS',
|
|
65
|
-
'Name of the Metadata and the External Identifier must match',
|
|
66
|
-
JSON.stringify({
|
|
67
|
-
Filename: fileNameWithoutEnding,
|
|
68
|
-
ExternalIdentifier: key,
|
|
69
|
-
})
|
|
61
|
+
Util.logger.error(
|
|
62
|
+
` ${this.definition.type} ${key}: Name of the metadata file and the JSON-key (${this.definition.keyField}) must match` +
|
|
63
|
+
Util.getGrayMsg(` - ${dir}/${fileName}`)
|
|
70
64
|
);
|
|
71
65
|
}
|
|
72
66
|
}
|
|
@@ -114,11 +108,10 @@ class MetadataType {
|
|
|
114
108
|
* @param {TYPE.MetadataTypeMap} metadata metadata mapped by their keyField
|
|
115
109
|
* @param {string} deployDir directory where deploy metadata are saved
|
|
116
110
|
* @param {string} retrieveDir directory where metadata after deploy should be saved
|
|
117
|
-
* @param {boolean} [isRefresh] optional flag to indicate that triggeredSend should be refreshed after deployment of assets
|
|
118
111
|
* @returns {Promise.<TYPE.MetadataTypeMap>} Promise of keyField => metadata map
|
|
119
112
|
*/
|
|
120
|
-
static async deploy(metadata, deployDir, retrieveDir
|
|
121
|
-
const upsertResults = await this.upsert(metadata, deployDir
|
|
113
|
+
static async deploy(metadata, deployDir, retrieveDir) {
|
|
114
|
+
const upsertResults = await this.upsert(metadata, deployDir);
|
|
122
115
|
const savedMetadata = await this.saveResults(upsertResults, retrieveDir, null);
|
|
123
116
|
if (
|
|
124
117
|
this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type) &&
|
|
@@ -137,13 +130,12 @@ class MetadataType {
|
|
|
137
130
|
* @param {TYPE.MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create
|
|
138
131
|
* @param {TYPE.MetadataTypeMap} originalMetadata metadata to be updated (contains additioanl fields)
|
|
139
132
|
* @param {{created: number, updated: number}} createdUpdated counter representing successful creates/updates
|
|
140
|
-
* @param {boolean} [isRefresh] optional flag to indicate that triggeredSend should be refreshed after deployment of assets
|
|
141
133
|
* @returns {void}
|
|
142
134
|
*/
|
|
143
|
-
static postDeployTasks(upsertResults, originalMetadata, createdUpdated
|
|
135
|
+
static postDeployTasks(upsertResults, originalMetadata, createdUpdated) {}
|
|
144
136
|
|
|
145
137
|
/**
|
|
146
|
-
* helper for {@link createREST}
|
|
138
|
+
* helper for {@link MetadataType.createREST}
|
|
147
139
|
*
|
|
148
140
|
* @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
|
|
149
141
|
* @param {object} apiResponse varies depending on the API call
|
|
@@ -152,7 +144,7 @@ class MetadataType {
|
|
|
152
144
|
static postCreateTasks(metadataEntry, apiResponse) {}
|
|
153
145
|
|
|
154
146
|
/**
|
|
155
|
-
* helper for {@link updateREST}
|
|
147
|
+
* helper for {@link MetadataType.updateREST}
|
|
156
148
|
*
|
|
157
149
|
* @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
|
|
158
150
|
* @param {object} apiResponse varies depending on the API call
|
|
@@ -161,7 +153,7 @@ class MetadataType {
|
|
|
161
153
|
static postUpdateTasks(metadataEntry, apiResponse) {}
|
|
162
154
|
|
|
163
155
|
/**
|
|
164
|
-
* helper for {@link createREST} when legacy API endpoints as these do not return the created item but only their new id
|
|
156
|
+
* helper for {@link MetadataType.createREST} when legacy API endpoints as these do not return the created item but only their new id
|
|
165
157
|
*
|
|
166
158
|
* @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
|
|
167
159
|
* @param {object} apiResponse varies depending on the API call
|
|
@@ -460,6 +452,29 @@ class MetadataType {
|
|
|
460
452
|
return;
|
|
461
453
|
}
|
|
462
454
|
|
|
455
|
+
/**
|
|
456
|
+
* Abstract execute method that needs to be implemented in child metadata type
|
|
457
|
+
*
|
|
458
|
+
* @returns {void}
|
|
459
|
+
*/
|
|
460
|
+
static execute() {
|
|
461
|
+
Util.logger.error(
|
|
462
|
+
` ☇ skipping ${this.definition.type}: execute is not supported yet for ${this.definition.type}`
|
|
463
|
+
);
|
|
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 [];
|
|
476
|
+
}
|
|
477
|
+
|
|
463
478
|
/**
|
|
464
479
|
* test if metadata was actually changed or not to potentially skip it during deployment
|
|
465
480
|
*
|
|
@@ -531,10 +546,9 @@ class MetadataType {
|
|
|
531
546
|
*
|
|
532
547
|
* @param {TYPE.MetadataTypeMap} metadataMap metadata mapped by their keyField
|
|
533
548
|
* @param {string} deployDir directory where deploy metadata are saved
|
|
534
|
-
* @param {boolean} [isRefresh] optional flag to indicate that triggeredSend should be refreshed after deployment of assets
|
|
535
549
|
* @returns {Promise.<TYPE.MetadataTypeMap>} keyField => metadata map
|
|
536
550
|
*/
|
|
537
|
-
static async upsert(metadataMap, deployDir
|
|
551
|
+
static async upsert(metadataMap, deployDir) {
|
|
538
552
|
const orignalMetadataMap = JSON.parse(JSON.stringify(metadataMap));
|
|
539
553
|
const metadataToUpdate = [];
|
|
540
554
|
const metadataToCreate = [];
|
|
@@ -626,12 +640,10 @@ class MetadataType {
|
|
|
626
640
|
const metadataResults = createResults.concat(updateResults).filter(Boolean);
|
|
627
641
|
upsertResults = this.parseResponseBody(metadataResults);
|
|
628
642
|
}
|
|
629
|
-
await this.postDeployTasks(
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
isRefresh
|
|
634
|
-
);
|
|
643
|
+
await this.postDeployTasks(upsertResults, orignalMetadataMap, {
|
|
644
|
+
created: createResults.length,
|
|
645
|
+
updated: updateResults.length,
|
|
646
|
+
});
|
|
635
647
|
return upsertResults;
|
|
636
648
|
}
|
|
637
649
|
|
|
@@ -650,6 +662,7 @@ class MetadataType {
|
|
|
650
662
|
metadataMap[metadataKey][this.definition.keyField]
|
|
651
663
|
);
|
|
652
664
|
// Update if it already exists; Create it if not
|
|
665
|
+
const maxKeyLength = this.definition.maxKeyLength || 36;
|
|
653
666
|
if (
|
|
654
667
|
Util.logger.level === 'debug' &&
|
|
655
668
|
metadataMap[metadataKey][this.definition.idField] &&
|
|
@@ -703,11 +716,11 @@ class MetadataType {
|
|
|
703
716
|
// NOTE: trim twice while getting the newKey value to remove leading spaces before limiting the length
|
|
704
717
|
const newKey = (metadataMap[metadataKey][Util.OPTIONS.changeKeyField] + '')
|
|
705
718
|
.trim()
|
|
706
|
-
.slice(0,
|
|
719
|
+
.slice(0, maxKeyLength)
|
|
707
720
|
.trim();
|
|
708
|
-
if (metadataMap[metadataKey][Util.OPTIONS.changeKeyField] + '' >
|
|
721
|
+
if (metadataMap[metadataKey][Util.OPTIONS.changeKeyField] + '' > maxKeyLength) {
|
|
709
722
|
Util.logger.warn(
|
|
710
|
-
|
|
723
|
+
`${this.definition.type} ${this.definition.keyField} may not exceed ${maxKeyLength} characters. Truncated the value in field ${Util.OPTIONS.changeKeyField} to ${newKey}`
|
|
711
724
|
);
|
|
712
725
|
}
|
|
713
726
|
if (metadataKey == newKey) {
|
|
@@ -727,10 +740,10 @@ class MetadataType {
|
|
|
727
740
|
}
|
|
728
741
|
} else if (Util.OPTIONS.changeKeyValue) {
|
|
729
742
|
// NOTE: trim twice while getting the newKey value to remove leading spaces before limiting the length
|
|
730
|
-
const newKey = Util.OPTIONS.changeKeyValue.trim().slice(0,
|
|
731
|
-
if (Util.OPTIONS.changeKeyValue.trim().length >
|
|
743
|
+
const newKey = Util.OPTIONS.changeKeyValue.trim().slice(0, maxKeyLength).trim();
|
|
744
|
+
if (Util.OPTIONS.changeKeyValue.trim().length > maxKeyLength) {
|
|
732
745
|
Util.logger.warn(
|
|
733
|
-
|
|
746
|
+
`${this.definition.type} ${this.definition.keyField} may not exceed ${maxKeyLength} characters. Truncated your value to ${newKey}`
|
|
734
747
|
);
|
|
735
748
|
}
|
|
736
749
|
if (this.definition.keyField == this.definition.idField) {
|
|
@@ -808,7 +821,7 @@ class MetadataType {
|
|
|
808
821
|
);
|
|
809
822
|
return response;
|
|
810
823
|
} catch (ex) {
|
|
811
|
-
const parsedErrors = this.
|
|
824
|
+
const parsedErrors = this.getErrorsREST(ex);
|
|
812
825
|
Util.logger.error(
|
|
813
826
|
` ☇ error creating ${this.definition.type} ${
|
|
814
827
|
metadataEntry[this.definition.keyField] ||
|
|
@@ -838,7 +851,7 @@ class MetadataType {
|
|
|
838
851
|
this.removeNotCreateableFields(metadataEntry);
|
|
839
852
|
try {
|
|
840
853
|
const response = await this.client.soap.create(
|
|
841
|
-
|
|
854
|
+
Util.capitalizeFirstLetter(soapType),
|
|
842
855
|
metadataEntry,
|
|
843
856
|
null
|
|
844
857
|
);
|
|
@@ -862,7 +875,7 @@ class MetadataType {
|
|
|
862
875
|
*
|
|
863
876
|
* @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
|
|
864
877
|
* @param {string} uri rest endpoint for PATCH
|
|
865
|
-
* @param {'patch'|'post'|'put'} [httpMethod
|
|
878
|
+
* @param {'patch'|'post'|'put'} [httpMethod] defaults to 'patch'; some update requests require PUT instead of PATCH
|
|
866
879
|
* @returns {Promise.<object> | null} Promise of API response or null in case of an error
|
|
867
880
|
*/
|
|
868
881
|
static async updateREST(metadataEntry, uri, httpMethod = 'patch') {
|
|
@@ -871,7 +884,7 @@ class MetadataType {
|
|
|
871
884
|
// set to empty object in case API returned nothing to be able to update it in helper classes
|
|
872
885
|
const response = (await this.client.rest[httpMethod](uri, metadataEntry)) || {};
|
|
873
886
|
await this._postChangeKeyTasks(metadataEntry);
|
|
874
|
-
this.
|
|
887
|
+
this.getErrorsREST(response);
|
|
875
888
|
await this.postUpdateTasks(metadataEntry, response);
|
|
876
889
|
// some times, e.g. automation dont return a key in their update response and hence we need to fall back to name
|
|
877
890
|
Util.logger.info(
|
|
@@ -882,7 +895,7 @@ class MetadataType {
|
|
|
882
895
|
);
|
|
883
896
|
return response;
|
|
884
897
|
} catch (ex) {
|
|
885
|
-
const parsedErrors = this.
|
|
898
|
+
const parsedErrors = this.getErrorsREST(ex);
|
|
886
899
|
Util.logger.error(
|
|
887
900
|
` ☇ error updating ${this.definition.type} ${
|
|
888
901
|
metadataEntry[this.definition.keyField] ||
|
|
@@ -897,7 +910,7 @@ class MetadataType {
|
|
|
897
910
|
}
|
|
898
911
|
|
|
899
912
|
/**
|
|
900
|
-
* helper for {@link updateREST} and {@link updateSOAP} that removes old files after the key was changed
|
|
913
|
+
* helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} that removes old files after the key was changed
|
|
901
914
|
*
|
|
902
915
|
* @private
|
|
903
916
|
* @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
|
|
@@ -943,7 +956,7 @@ class MetadataType {
|
|
|
943
956
|
this.removeNotUpdateableFields(metadataEntry);
|
|
944
957
|
try {
|
|
945
958
|
const response = await this.client.soap.update(
|
|
946
|
-
|
|
959
|
+
Util.capitalizeFirstLetter(soapType),
|
|
947
960
|
metadataEntry,
|
|
948
961
|
null
|
|
949
962
|
);
|
|
@@ -978,15 +991,20 @@ class MetadataType {
|
|
|
978
991
|
}
|
|
979
992
|
}
|
|
980
993
|
/**
|
|
981
|
-
* helper for {@link _handleSOAPErrors}
|
|
994
|
+
* helper for {@link MetadataType._handleSOAPErrors}
|
|
982
995
|
*
|
|
983
996
|
* @param {Error} ex error that occured
|
|
984
997
|
* @returns {string} error message
|
|
985
998
|
*/
|
|
986
999
|
static getSOAPErrorMsg(ex) {
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
1000
|
+
if (ex?.json?.Results?.length) {
|
|
1001
|
+
if (ex?.json?.Results[0].StatusMessage) {
|
|
1002
|
+
return `${ex.json.Results[0].StatusMessage} (Code ${ex.json.Results[0].ErrorCode})`;
|
|
1003
|
+
} else if (ex?.json?.Results[0].Result.StatusMessage) {
|
|
1004
|
+
return `${ex.json.Results[0].Result.StatusMessage} (Code ${ex.json.Results[0].Result.ErrorCode})`;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
return ex.message;
|
|
990
1008
|
}
|
|
991
1009
|
/**
|
|
992
1010
|
* Retrieves SOAP via generic fuel-soap wrapper based metadata of metadata type into local filesystem. executes callback with retrieved metadata
|
|
@@ -1003,7 +1021,11 @@ class MetadataType {
|
|
|
1003
1021
|
const soapType = this.definition.soapType || this.definition.type;
|
|
1004
1022
|
let response;
|
|
1005
1023
|
try {
|
|
1006
|
-
response = await this.client.soap.retrieveBulk(
|
|
1024
|
+
response = await this.client.soap.retrieveBulk(
|
|
1025
|
+
Util.capitalizeFirstLetter(soapType),
|
|
1026
|
+
fields,
|
|
1027
|
+
requestParams
|
|
1028
|
+
);
|
|
1007
1029
|
} catch (ex) {
|
|
1008
1030
|
this._handleSOAPErrors(ex, 'retrieving');
|
|
1009
1031
|
return {};
|
|
@@ -1066,9 +1088,61 @@ class MetadataType {
|
|
|
1066
1088
|
type: this.definition.type,
|
|
1067
1089
|
};
|
|
1068
1090
|
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Used to execute a query/automation etc.
|
|
1093
|
+
*
|
|
1094
|
+
* @param {string} uri REST endpoint where the POST request should be sent
|
|
1095
|
+
* @param {string} key item key
|
|
1096
|
+
* @returns {Promise.<{key:string, response:string}>} metadata key and API response (OK or error)
|
|
1097
|
+
*/
|
|
1098
|
+
static async executeREST(uri, key) {
|
|
1099
|
+
try {
|
|
1100
|
+
const response = await this.client.rest.post(uri, {}); // payload is empty for this request
|
|
1101
|
+
if (response === 'OK') {
|
|
1102
|
+
Util.logger.info(` - executed ${this.definition.type}: ${key}`);
|
|
1103
|
+
} else {
|
|
1104
|
+
throw new Error(response);
|
|
1105
|
+
}
|
|
1106
|
+
return { key, response };
|
|
1107
|
+
} catch (ex) {
|
|
1108
|
+
Util.logger.error(`Failed to execute ${this.definition.type} ${key}: ${ex.message}`);
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1069
1111
|
|
|
1070
1112
|
/**
|
|
1071
|
-
*
|
|
1113
|
+
* Used to execute a query/automation etc.
|
|
1114
|
+
*
|
|
1115
|
+
* @param {TYPE.MetadataTypeItem} [metadataEntry] single metadata entry
|
|
1116
|
+
* @returns {Promise.<{key:string, response:object}>} metadata key and API response
|
|
1117
|
+
*/
|
|
1118
|
+
static async executeSOAP(metadataEntry) {
|
|
1119
|
+
const soapType = this.definition.soapType || this.definition.type;
|
|
1120
|
+
try {
|
|
1121
|
+
const response = await this.client.soap.perform(
|
|
1122
|
+
Util.capitalizeFirstLetter(soapType),
|
|
1123
|
+
'start',
|
|
1124
|
+
{
|
|
1125
|
+
ObjectID: metadataEntry[this.definition.idField],
|
|
1126
|
+
}
|
|
1127
|
+
);
|
|
1128
|
+
if (response?.OverallStatus === 'OK') {
|
|
1129
|
+
Util.logger.info(
|
|
1130
|
+
` - executed ${this.definition.type}: ${
|
|
1131
|
+
metadataEntry[this.definition.keyField]
|
|
1132
|
+
}`
|
|
1133
|
+
);
|
|
1134
|
+
} else {
|
|
1135
|
+
throw new Error(response?.OverallStatus);
|
|
1136
|
+
}
|
|
1137
|
+
return { key: metadataEntry[this.definition.keyField], response };
|
|
1138
|
+
} catch (ex) {
|
|
1139
|
+
this._handleSOAPErrors(ex, 'executing', metadataEntry);
|
|
1140
|
+
return null;
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
/**
|
|
1145
|
+
* helper for {@link MetadataType.retrieveREST} and {@link MetadataType.retrieveSOAP}
|
|
1072
1146
|
*
|
|
1073
1147
|
* @param {string|number} [singleRetrieve] key of single item to filter by
|
|
1074
1148
|
* @param {TYPE.MetadataTypeMap} metadataMap saved metadata
|
|
@@ -1271,7 +1345,7 @@ class MetadataType {
|
|
|
1271
1345
|
*
|
|
1272
1346
|
* @static
|
|
1273
1347
|
* @param {TYPE.MetadataTypeItem} metadataEntry metadata entry
|
|
1274
|
-
* @param {boolean} [include
|
|
1348
|
+
* @param {boolean} [include] true: use definition.include / options.include; false=exclude: use definition.filter / options.exclude
|
|
1275
1349
|
* @returns {boolean} true: skip saving == filtered; false: continue with saving
|
|
1276
1350
|
* @memberof MetadataType
|
|
1277
1351
|
*/
|
|
@@ -1316,7 +1390,7 @@ class MetadataType {
|
|
|
1316
1390
|
*
|
|
1317
1391
|
* @static
|
|
1318
1392
|
* @param {object} metadataEntry metadata entry
|
|
1319
|
-
* @param {boolean} [include
|
|
1393
|
+
* @param {boolean} [include] true: use definition.include / options.include; false=exclude: use definition.filter / options.exclude
|
|
1320
1394
|
* @returns {boolean} true: filtered == do NOT save; false: not filtered == do save
|
|
1321
1395
|
* @memberof MetadataType
|
|
1322
1396
|
*/
|
|
@@ -1548,6 +1622,10 @@ class MetadataType {
|
|
|
1548
1622
|
}
|
|
1549
1623
|
}
|
|
1550
1624
|
|
|
1625
|
+
if (Util.OPTIONS.like && !Util.fieldsLike(results[originalKey])) {
|
|
1626
|
+
Util.logger.debug(`Filtered ${originalKey} because of --like option`);
|
|
1627
|
+
continue;
|
|
1628
|
+
}
|
|
1551
1629
|
// we dont store Id on local disk, but we need it for caching logic,
|
|
1552
1630
|
// so its in retrieve but not in save. Here we put into the clone so that the original
|
|
1553
1631
|
// object used for caching doesnt have the Id removed.
|
|
@@ -1594,7 +1672,7 @@ class MetadataType {
|
|
|
1594
1672
|
return savedResults;
|
|
1595
1673
|
}
|
|
1596
1674
|
/**
|
|
1597
|
-
* helper for {@link buildDefinitionForNested}
|
|
1675
|
+
* helper for {@link MetadataType.buildDefinitionForNested}
|
|
1598
1676
|
* searches extracted file for template variable names and applies the market values
|
|
1599
1677
|
*
|
|
1600
1678
|
* @param {string} code code from extracted code
|
|
@@ -1606,7 +1684,7 @@ class MetadataType {
|
|
|
1606
1684
|
return Mustache.render(code, templateVariables, {}, ['{{{', '}}}']);
|
|
1607
1685
|
}
|
|
1608
1686
|
/**
|
|
1609
|
-
* helper for {@link buildTemplateForNested}
|
|
1687
|
+
* helper for {@link MetadataType.buildTemplateForNested}
|
|
1610
1688
|
* searches extracted file for template variable values and applies the market variable names
|
|
1611
1689
|
*
|
|
1612
1690
|
* @param {string} code code from extracted code
|
|
@@ -1618,7 +1696,7 @@ class MetadataType {
|
|
|
1618
1696
|
return Util.replaceByObject(code, templateVariables);
|
|
1619
1697
|
}
|
|
1620
1698
|
/**
|
|
1621
|
-
* helper for {@link buildDefinition}
|
|
1699
|
+
* helper for {@link MetadataType.buildDefinition}
|
|
1622
1700
|
* handles extracted code if any are found for complex types (e.g script, asset, query)
|
|
1623
1701
|
*
|
|
1624
1702
|
* @param {string} templateDir Directory where metadata templates are stored
|
|
@@ -1639,7 +1717,7 @@ class MetadataType {
|
|
|
1639
1717
|
return null;
|
|
1640
1718
|
}
|
|
1641
1719
|
/**
|
|
1642
|
-
* helper for {@link buildTemplate}
|
|
1720
|
+
* helper for {@link MetadataType.buildTemplate}
|
|
1643
1721
|
* handles extracted code if any are found for complex types
|
|
1644
1722
|
*
|
|
1645
1723
|
* @param {string} templateDir Directory where metadata templates are stored
|
|
@@ -1785,7 +1863,7 @@ class MetadataType {
|
|
|
1785
1863
|
* @param {object} ex response payload from REST API
|
|
1786
1864
|
* @returns {string[] | void} formatted Error Message
|
|
1787
1865
|
*/
|
|
1788
|
-
static
|
|
1866
|
+
static getErrorsREST(ex) {
|
|
1789
1867
|
const errors = [];
|
|
1790
1868
|
if (ex?.response?.status >= 400 && ex?.response?.status < 600) {
|
|
1791
1869
|
if (ex.response.data.errors) {
|
|
@@ -1808,11 +1886,13 @@ class MetadataType {
|
|
|
1808
1886
|
}
|
|
1809
1887
|
} else if (ex.response.data.message) {
|
|
1810
1888
|
errors.push(ex.response.data.message);
|
|
1811
|
-
} else {
|
|
1889
|
+
} else if (ex.response.data) {
|
|
1812
1890
|
errors.push(`Undefined Errors: ${JSON.stringify(ex.response.data)}`);
|
|
1891
|
+
Util.logger.debug(JSON.stringify(ex.response.data));
|
|
1892
|
+
} else {
|
|
1893
|
+
errors.push(`${ex.response.status} ${ex.response.statusText}`);
|
|
1813
1894
|
}
|
|
1814
1895
|
Util.logger.debug(JSON.stringify(ex.config));
|
|
1815
|
-
Util.logger.debug(JSON.stringify(ex.response.data));
|
|
1816
1896
|
}
|
|
1817
1897
|
return errors;
|
|
1818
1898
|
}
|
|
@@ -1875,11 +1955,7 @@ class MetadataType {
|
|
|
1875
1955
|
metadata[overrideKeyField || this.definition.keyField] = customerKey;
|
|
1876
1956
|
const soapType = this.definition.soapType || this.definition.type;
|
|
1877
1957
|
try {
|
|
1878
|
-
await this.client.soap.delete(
|
|
1879
|
-
soapType.charAt(0).toUpperCase() + soapType.slice(1),
|
|
1880
|
-
metadata,
|
|
1881
|
-
null
|
|
1882
|
-
);
|
|
1958
|
+
await this.client.soap.delete(Util.capitalizeFirstLetter(soapType), metadata, null);
|
|
1883
1959
|
if (!handleOutside) {
|
|
1884
1960
|
Util.logger.info(` - deleted ${this.definition.type}: ${customerKey}`);
|
|
1885
1961
|
}
|
|
@@ -1932,7 +2008,7 @@ class MetadataType {
|
|
|
1932
2008
|
* Returns metadata of a business unit that is saved locally
|
|
1933
2009
|
*
|
|
1934
2010
|
* @param {string} readDir root directory of metadata.
|
|
1935
|
-
* @param {boolean} [listBadKeys
|
|
2011
|
+
* @param {boolean} [listBadKeys] do not print errors, used for badKeys()
|
|
1936
2012
|
* @param {object} [buMetadata] Metadata of BU in local directory
|
|
1937
2013
|
* @returns {object} Metadata of BU in local directory
|
|
1938
2014
|
*/
|
|
@@ -1970,6 +2046,57 @@ class MetadataType {
|
|
|
1970
2046
|
const fileList = keyArr.map((key) => File.normalizePath([path, key + typeExtension]));
|
|
1971
2047
|
return fileList;
|
|
1972
2048
|
}
|
|
2049
|
+
|
|
2050
|
+
/**
|
|
2051
|
+
*
|
|
2052
|
+
* @param {TYPE.MetadataTypeMap} metadataMap metadata mapped by their keyField
|
|
2053
|
+
* @returns {string[]} list of keys
|
|
2054
|
+
*/
|
|
2055
|
+
static getKeysForFixing(metadataMap) {
|
|
2056
|
+
const keysForDeploy = [];
|
|
2057
|
+
if (Object.keys(metadataMap).length) {
|
|
2058
|
+
Util.logger.info(
|
|
2059
|
+
`Searching for ${this.definition.type} keys among downloaded items that need fixing:`
|
|
2060
|
+
);
|
|
2061
|
+
for (const item of Object.values(metadataMap)) {
|
|
2062
|
+
if (item[this.definition.nameField].length > this.definition.maxKeyLength) {
|
|
2063
|
+
Util.logger.warn(
|
|
2064
|
+
`Name of the item ${
|
|
2065
|
+
item[this.definition.keyField]
|
|
2066
|
+
} is too long for a key. Consider renaming your item. Key will be equal first ${
|
|
2067
|
+
this.definition.maxKeyLength
|
|
2068
|
+
} characters of the name`
|
|
2069
|
+
);
|
|
2070
|
+
item[this.definition.nameField] = item[this.definition.nameField].slice(
|
|
2071
|
+
0,
|
|
2072
|
+
this.definition.maxKeyLength
|
|
2073
|
+
);
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
if (
|
|
2077
|
+
item[this.definition.nameField] != item[this.definition.keyField] &&
|
|
2078
|
+
!this.definition.keyIsFixed
|
|
2079
|
+
) {
|
|
2080
|
+
keysForDeploy.push(item[this.definition.keyField]);
|
|
2081
|
+
Util.logger.info(
|
|
2082
|
+
` - added ${this.definition.type} to fixKey queue: ${
|
|
2083
|
+
item[this.definition.keyField]
|
|
2084
|
+
}`
|
|
2085
|
+
);
|
|
2086
|
+
} else {
|
|
2087
|
+
Util.logger.info(
|
|
2088
|
+
Util.getGrayMsg(
|
|
2089
|
+
` ☇ skipping ${this.definition.type} ${
|
|
2090
|
+
item[this.definition.keyField]
|
|
2091
|
+
}: key does not need to be updated`
|
|
2092
|
+
)
|
|
2093
|
+
);
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
Util.logger.info(`Found ${keysForDeploy.length} ${this.definition.type} keys to fix`);
|
|
2097
|
+
}
|
|
2098
|
+
return keysForDeploy;
|
|
2099
|
+
}
|
|
1973
2100
|
}
|
|
1974
2101
|
|
|
1975
2102
|
MetadataType.definition = {
|