mcdev 7.0.4 → 7.1.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/.github/ISSUE_TEMPLATE/bug.yml +1 -0
- package/.husky/post-checkout +1 -1
- package/.husky/post-merge +7 -1
- package/.husky/pre-commit +2 -0
- package/@types/lib/Builder.d.ts.map +1 -1
- package/@types/lib/Deployer.d.ts +3 -0
- package/@types/lib/Deployer.d.ts.map +1 -1
- package/@types/lib/index.d.ts +70 -19
- package/@types/lib/index.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Asset.d.ts +53 -16
- package/@types/lib/metadataTypes/Asset.d.ts.map +1 -1
- package/@types/lib/metadataTypes/AttributeGroup.d.ts +3 -0
- package/@types/lib/metadataTypes/AttributeGroup.d.ts.map +1 -1
- package/@types/lib/metadataTypes/AttributeSet.d.ts +5 -0
- package/@types/lib/metadataTypes/AttributeSet.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Automation.d.ts +11 -0
- package/@types/lib/metadataTypes/Automation.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Campaign.d.ts +1 -0
- package/@types/lib/metadataTypes/Campaign.d.ts.map +1 -1
- package/@types/lib/metadataTypes/ContentArea.d.ts +1 -0
- package/@types/lib/metadataTypes/ContentArea.d.ts.map +1 -1
- package/@types/lib/metadataTypes/DataExtension.d.ts +5 -2
- package/@types/lib/metadataTypes/DataExtension.d.ts.map +1 -1
- package/@types/lib/metadataTypes/DataExtensionField.d.ts +3 -4
- package/@types/lib/metadataTypes/DataExtensionField.d.ts.map +1 -1
- package/@types/lib/metadataTypes/DataExtensionTemplate.d.ts +1 -0
- package/@types/lib/metadataTypes/DataExtensionTemplate.d.ts.map +1 -1
- package/@types/lib/metadataTypes/DataExtract.d.ts +1 -0
- package/@types/lib/metadataTypes/DataExtract.d.ts.map +1 -1
- package/@types/lib/metadataTypes/DataExtractType.d.ts +1 -0
- package/@types/lib/metadataTypes/DataExtractType.d.ts.map +1 -1
- package/@types/lib/metadataTypes/DeliveryProfile.d.ts +1 -0
- package/@types/lib/metadataTypes/DeliveryProfile.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Discovery.d.ts +1 -0
- package/@types/lib/metadataTypes/Discovery.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Email.d.ts +1 -0
- package/@types/lib/metadataTypes/Email.d.ts.map +1 -1
- package/@types/lib/metadataTypes/EmailSend.d.ts +8 -0
- package/@types/lib/metadataTypes/EmailSend.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Event.d.ts +3 -0
- package/@types/lib/metadataTypes/Event.d.ts.map +1 -1
- package/@types/lib/metadataTypes/FileLocation.d.ts +1 -0
- package/@types/lib/metadataTypes/FileLocation.d.ts.map +1 -1
- package/@types/lib/metadataTypes/FileTransfer.d.ts +1 -0
- package/@types/lib/metadataTypes/FileTransfer.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Filter.d.ts +1 -0
- package/@types/lib/metadataTypes/Filter.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Folder.d.ts +39 -25
- package/@types/lib/metadataTypes/Folder.d.ts.map +1 -1
- package/@types/lib/metadataTypes/ImportFile.d.ts +5 -0
- package/@types/lib/metadataTypes/ImportFile.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Journey.d.ts +42 -3
- package/@types/lib/metadataTypes/Journey.d.ts.map +1 -1
- package/@types/lib/metadataTypes/List.d.ts +1 -0
- package/@types/lib/metadataTypes/List.d.ts.map +1 -1
- package/@types/lib/metadataTypes/MetadataType.d.ts +50 -3
- package/@types/lib/metadataTypes/MetadataType.d.ts.map +1 -1
- package/@types/lib/metadataTypes/MobileCode.d.ts +1 -0
- package/@types/lib/metadataTypes/MobileCode.d.ts.map +1 -1
- package/@types/lib/metadataTypes/MobileKeyword.d.ts +9 -0
- package/@types/lib/metadataTypes/MobileKeyword.d.ts.map +1 -1
- package/@types/lib/metadataTypes/MobileMessage.d.ts +4 -0
- package/@types/lib/metadataTypes/MobileMessage.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Query.d.ts +3 -0
- package/@types/lib/metadataTypes/Query.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Role.d.ts +1 -0
- package/@types/lib/metadataTypes/Role.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Script.d.ts +3 -1
- package/@types/lib/metadataTypes/Script.d.ts.map +1 -1
- package/@types/lib/metadataTypes/SendClassification.d.ts +3 -0
- package/@types/lib/metadataTypes/SendClassification.d.ts.map +1 -1
- package/@types/lib/metadataTypes/SenderProfile.d.ts +1 -6
- package/@types/lib/metadataTypes/SenderProfile.d.ts.map +1 -1
- package/@types/lib/metadataTypes/TransactionalEmail.d.ts +6 -0
- package/@types/lib/metadataTypes/TransactionalEmail.d.ts.map +1 -1
- package/@types/lib/metadataTypes/TransactionalMessage.d.ts +1 -0
- package/@types/lib/metadataTypes/TransactionalMessage.d.ts.map +1 -1
- package/@types/lib/metadataTypes/TransactionalPush.d.ts +3 -0
- package/@types/lib/metadataTypes/TransactionalPush.d.ts.map +1 -1
- package/@types/lib/metadataTypes/TransactionalSMS.d.ts +4 -0
- package/@types/lib/metadataTypes/TransactionalSMS.d.ts.map +1 -1
- package/@types/lib/metadataTypes/TriggeredSend.d.ts +6 -6
- package/@types/lib/metadataTypes/TriggeredSend.d.ts.map +1 -1
- package/@types/lib/metadataTypes/User.d.ts +1 -0
- package/@types/lib/metadataTypes/User.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Verification.d.ts +3 -0
- package/@types/lib/metadataTypes/Verification.d.ts.map +1 -1
- package/@types/lib/metadataTypes/definitions/Asset.definition.d.ts +24 -14
- package/@types/lib/metadataTypes/definitions/AttributeGroup.definition.d.ts +3 -0
- package/@types/lib/metadataTypes/definitions/AttributeSet.definition.d.ts +5 -0
- package/@types/lib/metadataTypes/definitions/Automation.definition.d.ts +16 -0
- package/@types/lib/metadataTypes/definitions/Campaign.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/ContentArea.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/DataExtension.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/DataExtensionField.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/DataExtensionTemplate.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/DataExtract.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/DataExtractType.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/DeliveryProfile.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/Discovery.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/Email.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/EmailSend.definition.d.ts +8 -0
- package/@types/lib/metadataTypes/definitions/Event.definition.d.ts +3 -0
- package/@types/lib/metadataTypes/definitions/FileLocation.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/FileTransfer.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/Filter.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/Folder.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/ImportFile.definition.d.ts +5 -0
- package/@types/lib/metadataTypes/definitions/Journey.definition.d.ts +13 -0
- package/@types/lib/metadataTypes/definitions/List.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/MobileCode.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/MobileKeyword.definition.d.ts +9 -0
- package/@types/lib/metadataTypes/definitions/MobileMessage.definition.d.ts +4 -0
- package/@types/lib/metadataTypes/definitions/Query.definition.d.ts +3 -0
- package/@types/lib/metadataTypes/definitions/Role.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/Script.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/SendClassification.definition.d.ts +3 -0
- package/@types/lib/metadataTypes/definitions/SenderProfile.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/TransactionalEmail.definition.d.ts +6 -0
- package/@types/lib/metadataTypes/definitions/TransactionalMessage.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/TransactionalPush.definition.d.ts +3 -0
- package/@types/lib/metadataTypes/definitions/TransactionalSMS.definition.d.ts +4 -0
- package/@types/lib/metadataTypes/definitions/TriggeredSend.definition.d.ts +6 -0
- package/@types/lib/metadataTypes/definitions/User.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/Verification.definition.d.ts +3 -0
- package/@types/lib/util/cache.d.ts +10 -0
- package/@types/lib/util/cache.d.ts.map +1 -1
- package/@types/lib/util/cli.d.ts +3 -6
- package/@types/lib/util/cli.d.ts.map +1 -1
- package/@types/lib/util/config.d.ts.map +1 -1
- package/@types/lib/util/devops.d.ts.map +1 -1
- package/@types/lib/util/init.config.d.ts.map +1 -1
- package/@types/lib/util/init.d.ts.map +1 -1
- package/@types/lib/util/init.git.d.ts.map +1 -1
- package/@types/lib/util/replaceContentBlockReference.d.ts +27 -4
- package/@types/lib/util/replaceContentBlockReference.d.ts.map +1 -1
- package/@types/lib/util/util.d.ts +32 -3
- package/@types/lib/util/util.d.ts.map +1 -1
- package/@types/types/mcdev.d.d.ts +87 -0
- package/@types/types/mcdev.d.d.ts.map +1 -1
- package/boilerplate/files/.vscode/settings.json +1 -0
- package/boilerplate/forcedUpdates.json +4 -0
- package/boilerplate/gitignore-template +0 -1
- package/lib/Builder.js +13 -8
- package/lib/Deployer.js +12 -7
- package/lib/cli.js +179 -14
- package/lib/index.js +538 -205
- package/lib/metadataTypes/Asset.js +455 -210
- package/lib/metadataTypes/Automation.js +34 -0
- package/lib/metadataTypes/DataExtension.js +33 -28
- package/lib/metadataTypes/DataExtensionField.js +2 -2
- package/lib/metadataTypes/Event.js +28 -2
- package/lib/metadataTypes/Folder.js +63 -48
- package/lib/metadataTypes/Journey.js +330 -56
- package/lib/metadataTypes/MetadataType.js +269 -57
- package/lib/metadataTypes/MobileKeyword.js +12 -1
- package/lib/metadataTypes/Script.js +4 -3
- package/lib/metadataTypes/SenderProfile.js +17 -5
- package/lib/metadataTypes/TriggeredSend.js +20 -5
- package/lib/metadataTypes/definitions/Asset.definition.js +10 -2
- package/lib/metadataTypes/definitions/AttributeGroup.definition.js +1 -0
- package/lib/metadataTypes/definitions/AttributeSet.definition.js +11 -0
- package/lib/metadataTypes/definitions/Automation.definition.js +9 -0
- package/lib/metadataTypes/definitions/Campaign.definition.js +1 -0
- package/lib/metadataTypes/definitions/ContentArea.definition.js +1 -0
- package/lib/metadataTypes/definitions/DataExtension.definition.js +1 -0
- package/lib/metadataTypes/definitions/DataExtensionField.definition.js +1 -0
- package/lib/metadataTypes/definitions/DataExtensionTemplate.definition.js +1 -0
- package/lib/metadataTypes/definitions/DataExtract.definition.js +2 -1
- package/lib/metadataTypes/definitions/DataExtractType.definition.js +1 -0
- package/lib/metadataTypes/definitions/DeliveryProfile.definition.js +1 -0
- package/lib/metadataTypes/definitions/Discovery.definition.js +1 -0
- package/lib/metadataTypes/definitions/Email.definition.js +1 -0
- package/lib/metadataTypes/definitions/EmailSend.definition.js +8 -0
- package/lib/metadataTypes/definitions/Event.definition.js +1 -0
- package/lib/metadataTypes/definitions/FileLocation.definition.js +1 -0
- package/lib/metadataTypes/definitions/FileTransfer.definition.js +4 -0
- package/lib/metadataTypes/definitions/Filter.definition.js +1 -0
- package/lib/metadataTypes/definitions/Folder.definition.js +10 -8
- package/lib/metadataTypes/definitions/ImportFile.definition.js +8 -1
- package/lib/metadataTypes/definitions/Journey.definition.js +28 -0
- package/lib/metadataTypes/definitions/List.definition.js +1 -0
- package/lib/metadataTypes/definitions/MobileCode.definition.js +1 -0
- package/lib/metadataTypes/definitions/MobileKeyword.definition.js +7 -0
- package/lib/metadataTypes/definitions/MobileMessage.definition.js +9 -0
- package/lib/metadataTypes/definitions/Query.definition.js +3 -0
- package/lib/metadataTypes/definitions/Role.definition.js +1 -0
- package/lib/metadataTypes/definitions/Script.definition.js +1 -0
- package/lib/metadataTypes/definitions/SendClassification.definition.js +4 -0
- package/lib/metadataTypes/definitions/SenderProfile.definition.js +1 -0
- package/lib/metadataTypes/definitions/TransactionalEmail.definition.js +7 -0
- package/lib/metadataTypes/definitions/TransactionalMessage.definition.js +1 -0
- package/lib/metadataTypes/definitions/TransactionalPush.definition.js +3 -0
- package/lib/metadataTypes/definitions/TransactionalSMS.definition.js +4 -0
- package/lib/metadataTypes/definitions/TriggeredSend.definition.js +10 -3
- package/lib/metadataTypes/definitions/User.definition.js +3 -0
- package/lib/metadataTypes/definitions/Verification.definition.js +1 -0
- package/lib/util/cache.js +35 -0
- package/lib/util/cli.js +96 -139
- package/lib/util/config.js +11 -19
- package/lib/util/devops.js +41 -41
- package/lib/util/init.config.js +6 -10
- package/lib/util/init.git.js +43 -57
- package/lib/util/init.js +35 -59
- package/lib/util/replaceContentBlockReference.js +107 -60
- package/lib/util/util.js +90 -4
- package/package.json +14 -13
- package/test/general.test.js +1117 -163
- package/test/mockRoot/.mcdevrc.json +1 -1
- package/test/mockRoot/deploy/testInstance/testBU/event/testNew_event_withExistingDE.event-meta.json +1 -0
- package/test/mockRoot/deploy/testInstance/testBU/event/testNew_event_withSchema.event-meta.json +1 -0
- package/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/4912312345678.TESTNEW_KEYWORD.mobileKeyword-meta.json +1 -0
- package/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/4912312345678.TESTNEW_KEYWORD_BLOCKED.mobileKeyword-meta.json +1 -0
- package/test/resourceFactory.js +43 -11
- package/test/resources/1111111/dataFolder/retrieve-ContentTypeINshared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml +364 -0
- package/test/resources/9999999/asset/{block-1157-retrieve-expected.html → build-asset_htmlblock-expected.html} +1 -1
- package/test/resources/9999999/asset/build-asset_htmlblock-expected.json +29 -0
- package/test/resources/9999999/asset/build-templatebasedemail-expected.json +65 -0
- package/test/resources/9999999/asset/resolveId-1295064-noPath-expected.json +3 -3
- package/test/resources/9999999/asset/resolveId-1295064-withPath-expected.json +3 -3
- package/test/resources/9999999/asset/retrieve-templatebasedemail-expected.json +65 -0
- package/test/resources/9999999/asset/template-emailTemplate-expected.json +20 -0
- package/test/resources/9999999/asset/template-templatebasedemail-expected.json +65 -0
- package/test/resources/9999999/asset/template-testExisting_asset_htmlblock-expected.json +29 -0
- package/test/resources/9999999/asset/testExisting_asset_htmlblock-retrieve-expected.html +23 -0
- package/test/resources/9999999/asset/{block-1157-retrieve-expected.json → testExisting_asset_htmlblock-retrieve-expected.json} +3 -3
- package/test/resources/9999999/asset/testExisting_asset_message-html-rcb-key-expected.html +6 -6
- package/test/resources/9999999/asset/testExisting_asset_message-preheader-rcb-id-expected.amp +1 -1
- package/test/resources/9999999/asset/testExisting_asset_message-preheader-rcb-key-expected.amp +4 -4
- package/test/resources/9999999/asset/testExisting_asset_message-preheader-rcb-name-expected.amp +1 -1
- package/test/resources/9999999/asset/testExisting_asset_message-text-rcb-key-expected.amp +4 -4
- package/test/resources/9999999/asset/v1/content/assets/1295064/get-response.json +4 -4
- package/test/resources/9999999/asset/v1/content/assets/1295065/get-response.json +60 -0
- package/test/resources/9999999/asset/v1/content/assets/1295066/get-response.json +60 -0
- package/test/resources/9999999/asset/v1/content/assets/5289/get-response.json +75 -0
- package/test/resources/9999999/asset/v1/content/assets/808714/get-response.json +3 -3
- package/test/resources/9999999/asset/v1/content/assets/950143/get-response.json +97 -0
- package/test/resources/9999999/asset/v1/content/assets/get-response-customerKey=testExisting_asset.json +1 -1
- package/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN195,196,197,198,199,200,201,202,203,210,211,212,213,3.json +78 -2
- package/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN205,206,230,232,1,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,14,193,194,15,195,196,197,198,199,200,201,202,203,210,211,212,213,3,207,208,209,5,214,4,215,216.json +370 -0
- package/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN205,206,230,232,1,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,14,193,194,15,195,196,197,198,199,200,201,202,203,210,211,212,213,3,215,216,217,218,219,220,221,222.json +243 -0
- package/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN205,206,230,232,1,207,208,209,5.json +229 -0
- package/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN205,206,230,232,1.json +98 -1
- package/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN217,218,219,220,221,222,223,224,225,226,227,228.json +7 -0
- package/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN223,224,225,226,227,228,214,4.json +35 -0
- package/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN223,224,225,226,227,228.json +7 -0
- package/test/resources/9999999/asset/v1/content/assets/query/{post-response-customerKey=mcdev-issue-1157.json → post-response-customerKey=testExisting_asset_htmlblock.json} +2 -2
- package/test/resources/9999999/automation/v1/queries/get-response-Name=testExisting_query.json +24 -0
- package/test/resources/9999999/automation/v1/scripts/get-response-name=testExisting_script.json +17 -0
- package/test/resources/9999999/automation/v1/scripts/get-response.json +2 -2
- package/test/resources/9999999/dataFolder/retrieve-ContentType=asset-shared-QAA-response.xml +70 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentType=asset-shared-response.xml +70 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentType=journey-response.xml +48 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,automatio,dataexten,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,triggered,triggered,useriniti-response.xml +519 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,dataexten,salesforc,shared_da,shared_da,shared_sa,synchroni,automatio,useriniti,journey,mysubs,list,publicati,queryacti,ssjsactiv,triggered,triggered-response.xml +519 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,journey-response.xml +92 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml +115 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,ssjsactivity-response.xml +92 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared-QAA-response.xml +70 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset-shared,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml +431 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentTypeINautomations,queryactivity-response.xml +70 -0
- package/test/resources/9999999/dataFolder/{retrieve-response.xml → retrieve-ContentTypeINdataextension,hidden,queryactivity,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml} +32 -119
- package/test/resources/9999999/dataFolder/retrieve-ContentTypeINdataextension,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml +117 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentTypeINhidden,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml +46 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentTypeINshared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml +251 -0
- package/test/resources/9999999/dataFolder/retrieve-response-.xml +519 -0
- package/test/resources/9999999/event/build-expected.json +0 -1
- package/test/resources/9999999/event/get-expected.json +0 -1
- package/test/resources/9999999/event/post_withExistingDE-callout-expected.json +3 -0
- package/test/resources/9999999/event/post_withExistingDE-expected.json +2 -0
- package/test/resources/9999999/event/post_withSchema-callout-expected.json +3 -0
- package/test/resources/9999999/event/post_withSchema-expected.json +2 -0
- package/test/resources/9999999/event/put-callout-expected.json +3 -1
- package/test/resources/9999999/event/put-expected.json +2 -2
- package/test/resources/9999999/event/template-expected.json +0 -1
- package/test/resources/9999999/interaction/v1/eventDefinitions/key_testExisting_event/put-response.json +2 -1
- package/test/resources/9999999/interaction/v1/eventDefinitions/post_withExistingDE-response.json +2 -0
- package/test/resources/9999999/interaction/v1/eventDefinitions/post_withSchema-response.json +2 -0
- package/test/resources/9999999/interaction/v1/interactions/3c3f4112-9b43-43ca-8a89-aa0375b2c1a2/get-response.json +4 -4
- package/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Quicksend/get-response.json +4 -4
- package/test/resources/9999999/interaction/v1/interactions/publishAsync/3c3f4112-9b43-43ca-8a89-aa0375b2c1a2/post-response.json +4 -0
- package/test/resources/9999999/interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-failed.json +34 -0
- package/test/resources/9999999/interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-success.json +5 -0
- package/test/resources/9999999/interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-successWarnings.json +36 -0
- package/test/resources/9999999/journey/build-expected.json +5 -5
- package/test/resources/9999999/journey/get-multistep-expected.json +1 -1
- package/test/resources/9999999/journey/get-quicksend-expected.json +5 -5
- package/test/resources/9999999/journey/get-quicksend-rcb-id-expected.json +1 -1
- package/test/resources/9999999/journey/get-quicksend-rcb-key-expected.json +7 -7
- package/test/resources/9999999/journey/get-quicksend-rcb-name-expected.json +1 -1
- package/test/resources/9999999/journey/post-expected.json +1 -1
- package/test/resources/9999999/journey/publish-callout-expected.json +1 -0
- package/test/resources/9999999/journey/put-expected.json +1 -1
- package/test/resources/9999999/journey/template-expected.json +5 -5
- package/test/resources/9999999/mobileKeyword/build-expected.json +1 -0
- package/test/resources/9999999/mobileKeyword/get-expected.json +1 -0
- package/test/resources/9999999/mobileKeyword/post-create-expected.json +1 -0
- package/test/resources/9999999/mobileKeyword/template-expected.json +1 -0
- package/test/resources/{1111111/accountUser/retrieve-CustomerKey=testExisting_userANDActiveFlag=trueANDEmailisNullORNamelikeapp userANDMustChangePassword=false-response.xml → 9999999/queryDefinition/retrieve-CustomerKey=badANDStatus=Active-response.xml} +10 -11
- package/test/resources/9999999/script/get_ampincluded-rcb-key-expected.html +2 -2
- package/test/resources/9999999/script/get_ampscript-expected.html +1 -0
- package/test/resources/9999999/script/get_ampscript-rcb-id-expected.html +1 -0
- package/test/resources/9999999/script/get_ampscript-rcb-key-expected.html +3 -2
- package/test/resources/9999999/script/get_ampscript-rcb-name-expected.html +3 -0
- package/test/resources/9999999/script/get_mixed-expected.html +2 -2
- package/test/resources/9999999/script/get_mixed-rcb-key-expected.html +2 -2
- package/test/resources/9999999/senderProfile/get-rcb-key-expected.json +4 -4
- package/test/resources/9999999/senderProfile/retrieve-response.xml +1 -1
- package/test/resources/9999999/triggeredSend/get-rcb-key-expected.json +4 -4
- package/test/resources/9999999/triggeredSendDefinition/retrieve-TriggeredSendStatusINNew,Active,Inactive,Moved,Canceled-response.xml +1 -1
- package/test/type.asset.test.js +189 -39
- package/test/type.automation.test.js +134 -58
- package/test/type.dataExtract.test.js +4 -4
- package/test/type.emailSend.test.js +3 -3
- package/test/type.event.test.js +0 -2
- package/test/type.journey.test.js +322 -9
- package/test/type.query.test.js +33 -29
- package/test/type.script.test.js +61 -11
- package/test/type.senderProfile.test.js +36 -3
- package/test/type.transactionalEmail.test.js +3 -3
- package/test/type.triggeredSend.test.js +75 -6
- package/test/utils.js +13 -3
- package/types/mcdev.d.js +27 -1
- /package/test/resources/1111111/accountUser/{retrieve-ActiveFlag=falseANDCustomerKey=testExisting_userANDEmaillike@-response.xml → retrieve-ActiveFlag=falseANDCustomerKey=testExisting_userANDEmaillike@-QAA-response.xml} +0 -0
- /package/test/resources/1111111/accountUser/{retrieve-ActiveFlag=falseANDEmaillike@-response.xml → retrieve-ActiveFlag=falseANDEmaillike@-QAA-response.xml} +0 -0
- /package/test/resources/1111111/accountUser/{retrieve-ActiveFlag=trueANDCustomerKey=testExisting_userANDEmaillike@-response.xml → retrieve-ActiveFlag=trueANDCustomerKey=testExisting_userANDEmaillike@-QAA-response.xml} +0 -0
- /package/test/resources/1111111/accountUser/{retrieve-ActiveFlag=trueANDEmailisNullORNamelikeapp userANDMustChangePassword=false-response.xml → retrieve-ActiveFlag=trueANDEmailisNullORNamelikeapp userANDMustChangePassword=false-QAA-response.xml} +0 -0
- /package/test/resources/1111111/accountUser/{retrieve-ActiveFlag=trueANDEmaillike@-response.xml → retrieve-ActiveFlag=trueANDEmaillike@-QAA-response.xml} +0 -0
- /package/test/resources/1111111/businessUnit/{retrieve-ID=1111111-response.xml → retrieve-ID=1111111-QAA-response.xml} +0 -0
- /package/test/resources/1111111/dataFolder/{retrieve-ContentType=synchronizeddataextensionORContentType=shared_salesforcedataextensionORContentType=shared_dataextensionORContentType=shared_dataORContentType=salesforcedataextensionORContentType=dataextensionORContentType=hidden-response.xml → retrieve-ContentTypeINdataextension,hidden,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml} +0 -0
- /package/test/resources/1111111/dataFolder/{retrieve-response.xml → retrieve-response-.xml} +0 -0
- /package/test/resources/9999999/dataFolder/{retrieve-ContentType=asset-sharedORContentType=asset-response.xml → retrieve-ContentTypeINasset,asset-shared-response.xml} +0 -0
- /package/test/resources/9999999/dataFolder/{retrieve-ContentType=contextual_suppression_listORContentType=publicationORContentType=suppression_listORContentType=mysubsORContentType=list-response.xml → retrieve-ContentTypeINcontextual_suppression_list,list,mysubs,publication,suppression_list-response.xml} +0 -0
- /package/test/resources/9999999/dataFolder/{retrieve-ContentType=synchronizeddataextensionORContentType=shared_salesforcedataextensionORContentType=shared_dataextensionORContentType=shared_dataORContentType=salesforcedataextensionORContentType=dataextensionORContentType=hidden-response.xml → retrieve-ContentTypeINdataextension,hidden,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml} +0 -0
- /package/test/resources/9999999/dataFolder/{retrieve-ContentType=triggered_send_journeybuilderORContentType=triggered_sendORContentType=hidden-response.xml → retrieve-ContentTypeINhidden,triggered_send,triggered_send_journeybuilder-response.xml} +0 -0
|
@@ -19,6 +19,7 @@ import ReplaceCbReference from '../util/replaceContentBlockReference.js';
|
|
|
19
19
|
* @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap
|
|
20
20
|
* @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams
|
|
21
21
|
* @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap
|
|
22
|
+
* @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo
|
|
22
23
|
*/
|
|
23
24
|
/**
|
|
24
25
|
* @typedef {import('../../types/mcdev.d.js').AssetSubType} AssetSubType
|
|
@@ -58,11 +59,40 @@ class Asset extends MetadataType {
|
|
|
58
59
|
if (retrieveDir) {
|
|
59
60
|
await File.initPrettier();
|
|
60
61
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
|
|
62
|
+
if (retrieveDir && !cache.getCache()?.asset) {
|
|
63
|
+
// cache this for 3 reasons:
|
|
64
|
+
// 1) subtypes asset, message and template reference other content blocks by id/key/objectId as part of their views
|
|
65
|
+
// 2) subtype message references a template if it is template-based
|
|
66
|
+
// 3) all non-binary subtypes support ampscript / ssjs which can load otherc content blocks via ContentBlockyByX()
|
|
67
|
+
|
|
68
|
+
Util.logger.info(' - Caching dependent Metadata: asset');
|
|
69
|
+
const resultLocal = await this.retrieveForCache(
|
|
70
|
+
undefined,
|
|
71
|
+
this.definition.selflinkedSubTypes,
|
|
72
|
+
undefined,
|
|
73
|
+
false
|
|
74
|
+
);
|
|
75
|
+
cache.mergeMetadata('asset', resultLocal.metadata);
|
|
76
|
+
Util.logger.info(' - Caching dependent Metadata: shared asset');
|
|
77
|
+
const resultShared = await this.retrieveForCache(
|
|
78
|
+
undefined,
|
|
79
|
+
this.definition.selflinkedSubTypes,
|
|
80
|
+
undefined,
|
|
81
|
+
true
|
|
82
|
+
);
|
|
83
|
+
cache.mergeMetadata('asset', resultShared.metadata);
|
|
84
|
+
}
|
|
85
|
+
if (retrieveDir) {
|
|
86
|
+
// loop through subtypes and return results of each subType for caching (saving is handled per subtype)
|
|
87
|
+
for (const subType of subTypeArr) {
|
|
88
|
+
// each subtype contains multiple different specific types (images contains jpg and png for example)
|
|
89
|
+
// we use await here to limit the risk of too many concurrent api requests at time
|
|
90
|
+
items.push(
|
|
91
|
+
...(await this.requestSubType(subType, retrieveDir, key, null, loadShared))
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
items.push(...(await this.requestSubType(subTypeArr, null, key, null, loadShared)));
|
|
66
96
|
}
|
|
67
97
|
const metadata = this.parseResponseBody({ items: items });
|
|
68
98
|
if (retrieveDir) {
|
|
@@ -73,44 +103,6 @@ class Asset extends MetadataType {
|
|
|
73
103
|
}
|
|
74
104
|
return { metadata: metadata, type: this.definition.type };
|
|
75
105
|
}
|
|
76
|
-
/**
|
|
77
|
-
* Helper for writing Metadata to disk, used for Retrieve and deploy
|
|
78
|
-
*
|
|
79
|
-
* @param {MetadataTypeMap} results metadata results from deploy
|
|
80
|
-
* @param {string} retrieveDir directory where metadata should be stored after deploy/retrieve
|
|
81
|
-
* @param {string} [overrideType] for use when there is a subtype (such as folder-queries)
|
|
82
|
-
* @param {TemplateMap} [templateVariables] variables to be replaced in the metadata
|
|
83
|
-
* @returns {Promise.<MetadataTypeMap>} Promise of saved metadata
|
|
84
|
-
*/
|
|
85
|
-
static async saveResults(results, retrieveDir, overrideType, templateVariables) {
|
|
86
|
-
if (Object.keys(results).length) {
|
|
87
|
-
// only execute the following if records were found
|
|
88
|
-
await this._postRetrieveTasksBulk(results);
|
|
89
|
-
}
|
|
90
|
-
return super.saveResults(results, retrieveDir, overrideType, templateVariables);
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* helper for Journey's {@link Asset.saveResults}. Gets executed after retreive of metadata type and
|
|
94
|
-
*
|
|
95
|
-
* @param {MetadataTypeMap} metadataMap key=customer key, value=metadata
|
|
96
|
-
*/
|
|
97
|
-
static async _postRetrieveTasksBulk(metadataMap) {
|
|
98
|
-
// Template-Based Email
|
|
99
|
-
let needTemplates = false;
|
|
100
|
-
for (const key in metadataMap) {
|
|
101
|
-
if (metadataMap[key].assetType.name == 'templatebasedemail') {
|
|
102
|
-
needTemplates = true;
|
|
103
|
-
break;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (needTemplates && !cache.getCache()?.asset) {
|
|
108
|
-
// for
|
|
109
|
-
Util.logger.info(' - Caching dependent Metadata: asset-template');
|
|
110
|
-
const result = await this.retrieveForCache(undefined, ['template']);
|
|
111
|
-
cache.setMetadata('asset', result.metadata);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
106
|
|
|
115
107
|
/**
|
|
116
108
|
* Retrieves asset metadata for caching
|
|
@@ -207,7 +199,7 @@ class Asset extends MetadataType {
|
|
|
207
199
|
/**
|
|
208
200
|
* Retrieves Metadata of a specific asset type
|
|
209
201
|
*
|
|
210
|
-
* @param {string} subType group of similar assets to put in a folder (ie. images)
|
|
202
|
+
* @param {string|string[]} subType group of similar assets to put in a folder (ie. images)
|
|
211
203
|
* @param {string} [retrieveDir] target directory for saving assets
|
|
212
204
|
* @param {string} [key] key/id/name to filter by
|
|
213
205
|
* @param {TemplateMap} [templateVariables] variables to be replaced in the metadata
|
|
@@ -215,15 +207,29 @@ class Asset extends MetadataType {
|
|
|
215
207
|
* @returns {Promise.<object[]>} Promise
|
|
216
208
|
*/
|
|
217
209
|
static async requestSubType(subType, retrieveDir, key, templateVariables, loadShared = false) {
|
|
210
|
+
const subTypeArr = Array.isArray(subType) ? subType : [subType];
|
|
218
211
|
if (retrieveDir) {
|
|
219
|
-
|
|
212
|
+
if (Array.isArray(subType)) {
|
|
213
|
+
throw new TypeError(
|
|
214
|
+
'requestSubType should not be called with multiple subtypes when retrieving to disk.'
|
|
215
|
+
);
|
|
216
|
+
} else {
|
|
217
|
+
Util.logger.info(`- Retrieving Subtype: ${subType}`);
|
|
218
|
+
}
|
|
220
219
|
} else {
|
|
221
|
-
|
|
220
|
+
// in this mode we can accept arrays because we don't need to save this to a subtype folder but just want the records
|
|
221
|
+
Util.logSubtypes(subTypeArr);
|
|
222
222
|
}
|
|
223
223
|
/** @type {AssetSubType[]} */
|
|
224
|
-
const extendedSubTypeArr =
|
|
225
|
-
|
|
226
|
-
|
|
224
|
+
const extendedSubTypeArr = subTypeArr.flatMap(
|
|
225
|
+
(subType) => this.definition.extendedSubTypes[subType]
|
|
226
|
+
);
|
|
227
|
+
// the API can only assetType.ids at a time or else will throw: "DbUtility.GetPagedCollection passing through non-timeout DB error (30001)"
|
|
228
|
+
const subtypeIdsList = Util.chunk(
|
|
229
|
+
extendedSubTypeArr?.map(
|
|
230
|
+
(subTypeItemName) => this.definition.typeMapping[subTypeItemName]
|
|
231
|
+
),
|
|
232
|
+
50
|
|
227
233
|
);
|
|
228
234
|
const uri = '/asset/v1/content/assets/query' + (loadShared ? '?scope=shared' : '');
|
|
229
235
|
/** @type {AssetRequestParams} */
|
|
@@ -233,46 +239,15 @@ class Asset extends MetadataType {
|
|
|
233
239
|
pageSize: 50,
|
|
234
240
|
},
|
|
235
241
|
query: null,
|
|
236
|
-
fields: [
|
|
242
|
+
fields: [
|
|
243
|
+
'category',
|
|
244
|
+
'createdDate',
|
|
245
|
+
'createdBy',
|
|
246
|
+
'modifiedDate',
|
|
247
|
+
'modifiedBy',
|
|
248
|
+
'objectID',
|
|
249
|
+
], // get folder to allow duplicate name check against cache
|
|
237
250
|
};
|
|
238
|
-
|
|
239
|
-
if (key) {
|
|
240
|
-
payload.query = {
|
|
241
|
-
leftOperand: {
|
|
242
|
-
property: 'assetType.id',
|
|
243
|
-
simpleOperator: 'in',
|
|
244
|
-
value: subtypeIds,
|
|
245
|
-
},
|
|
246
|
-
logicalOperator: 'AND',
|
|
247
|
-
};
|
|
248
|
-
if (key.startsWith('id:')) {
|
|
249
|
-
payload.query.rightOperand = {
|
|
250
|
-
property: this.definition.idField,
|
|
251
|
-
simpleOperator: 'equal',
|
|
252
|
-
value: key.slice(3),
|
|
253
|
-
};
|
|
254
|
-
} else if (key.startsWith('name:')) {
|
|
255
|
-
payload.query.rightOperand = {
|
|
256
|
-
property: this.definition.nameField,
|
|
257
|
-
simpleOperator: 'equal',
|
|
258
|
-
value: key.slice(5),
|
|
259
|
-
};
|
|
260
|
-
} else {
|
|
261
|
-
payload.query.rightOperand = {
|
|
262
|
-
property: this.definition.keyField,
|
|
263
|
-
simpleOperator: 'equal',
|
|
264
|
-
value: key,
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
} else {
|
|
268
|
-
payload.query = {
|
|
269
|
-
property: 'assetType.id',
|
|
270
|
-
simpleOperator: 'in',
|
|
271
|
-
value: subtypeIds,
|
|
272
|
-
};
|
|
273
|
-
payload.sort = [{ property: 'id', direction: 'ASC' }];
|
|
274
|
-
}
|
|
275
|
-
// for caching we do not need these fields
|
|
276
251
|
if (retrieveDir) {
|
|
277
252
|
payload.fields = [
|
|
278
253
|
'fileProperties',
|
|
@@ -287,21 +262,11 @@ class Asset extends MetadataType {
|
|
|
287
262
|
'tags',
|
|
288
263
|
];
|
|
289
264
|
}
|
|
290
|
-
|
|
291
|
-
let lastPage = 0;
|
|
265
|
+
|
|
292
266
|
let items = [];
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
if (response?.items?.length) {
|
|
297
|
-
// sometimes the api will return a payload without items
|
|
298
|
-
// --> ensure we only add proper items-arrays here
|
|
299
|
-
items = items.concat(response.items);
|
|
300
|
-
}
|
|
301
|
-
// check if any more records
|
|
302
|
-
if (response?.message?.includes('all shards failed')) {
|
|
303
|
-
// When running certain filters, there is a limit of 10k on ElastiCache.
|
|
304
|
-
// Since we sort by ID, we can get the last ID then run new requests from there
|
|
267
|
+
|
|
268
|
+
for (const subtypeIds of subtypeIdsList) {
|
|
269
|
+
if (key) {
|
|
305
270
|
payload.query = {
|
|
306
271
|
leftOperand: {
|
|
307
272
|
property: 'assetType.id',
|
|
@@ -309,24 +274,75 @@ class Asset extends MetadataType {
|
|
|
309
274
|
value: subtypeIds,
|
|
310
275
|
},
|
|
311
276
|
logicalOperator: 'AND',
|
|
312
|
-
rightOperand: {
|
|
313
|
-
property: 'id',
|
|
314
|
-
simpleOperator: 'greaterThan',
|
|
315
|
-
value: items.at(-1).id,
|
|
316
|
-
},
|
|
317
277
|
};
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
278
|
+
if (key.startsWith('id:')) {
|
|
279
|
+
payload.query.rightOperand = {
|
|
280
|
+
property: this.definition.idField,
|
|
281
|
+
simpleOperator: 'equal',
|
|
282
|
+
value: key.slice(3),
|
|
283
|
+
};
|
|
284
|
+
} else if (key.startsWith('name:')) {
|
|
285
|
+
payload.query.rightOperand = {
|
|
286
|
+
property: this.definition.nameField,
|
|
287
|
+
simpleOperator: 'equal',
|
|
288
|
+
value: key.slice(5),
|
|
289
|
+
};
|
|
290
|
+
} else {
|
|
291
|
+
payload.query.rightOperand = {
|
|
292
|
+
property: this.definition.keyField,
|
|
293
|
+
simpleOperator: 'equal',
|
|
294
|
+
value: key,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
323
297
|
} else {
|
|
324
|
-
|
|
298
|
+
payload.query = {
|
|
299
|
+
property: 'assetType.id',
|
|
300
|
+
simpleOperator: 'in',
|
|
301
|
+
value: subtypeIds,
|
|
302
|
+
};
|
|
303
|
+
// payload.sort = [{ property: 'id', direction: 'ASC' }];
|
|
325
304
|
}
|
|
326
|
-
|
|
305
|
+
// for caching we do not need these fields
|
|
306
|
+
let moreResults = false;
|
|
307
|
+
let lastPage = 0;
|
|
308
|
+
do {
|
|
309
|
+
payload.page.page = lastPage + 1;
|
|
310
|
+
const response = await this.client.rest.post(uri, payload);
|
|
311
|
+
if (response?.items?.length) {
|
|
312
|
+
// sometimes the api will return a payload without items
|
|
313
|
+
// --> ensure we only add proper items-arrays here
|
|
314
|
+
items = items.concat(response.items);
|
|
315
|
+
}
|
|
316
|
+
// check if any more records
|
|
317
|
+
if (response?.message?.includes('all shards failed')) {
|
|
318
|
+
// When running certain filters, there is a limit of 10k on ElastiCache.
|
|
319
|
+
// Since we sort by ID, we can get the last ID then run new requests from there
|
|
320
|
+
payload.query = {
|
|
321
|
+
leftOperand: {
|
|
322
|
+
property: 'assetType.id',
|
|
323
|
+
simpleOperator: 'in',
|
|
324
|
+
value: subtypeIds,
|
|
325
|
+
},
|
|
326
|
+
logicalOperator: 'AND',
|
|
327
|
+
rightOperand: {
|
|
328
|
+
property: 'id',
|
|
329
|
+
simpleOperator: 'greaterThan',
|
|
330
|
+
value: items.at(-1).id,
|
|
331
|
+
},
|
|
332
|
+
};
|
|
333
|
+
lastPage = 0;
|
|
334
|
+
moreResults = true;
|
|
335
|
+
} else if (response.page * response.pageSize < response.count) {
|
|
336
|
+
moreResults = true;
|
|
337
|
+
lastPage = Number(response.page);
|
|
338
|
+
} else {
|
|
339
|
+
moreResults = false;
|
|
340
|
+
}
|
|
341
|
+
} while (moreResults);
|
|
342
|
+
}
|
|
327
343
|
|
|
328
344
|
// only when we save results do we need the complete metadata or files. caching can skip these
|
|
329
|
-
if (retrieveDir) {
|
|
345
|
+
if (retrieveDir && !Array.isArray(subType)) {
|
|
330
346
|
if (items.length > 0) {
|
|
331
347
|
for (const item of items) {
|
|
332
348
|
if (item.customerKey.trim() !== item.customerKey) {
|
|
@@ -344,10 +360,7 @@ class Asset extends MetadataType {
|
|
|
344
360
|
Util.logger.info(` Downloaded asset-${subType}: ${items.length}`);
|
|
345
361
|
}
|
|
346
362
|
|
|
347
|
-
return items
|
|
348
|
-
item._subType = subType;
|
|
349
|
-
return item;
|
|
350
|
-
});
|
|
363
|
+
return items;
|
|
351
364
|
}
|
|
352
365
|
/**
|
|
353
366
|
* Retrieves extended metadata (files or extended content) of asset
|
|
@@ -389,6 +402,8 @@ class Asset extends MetadataType {
|
|
|
389
402
|
const promiseMap = await Promise.all(
|
|
390
403
|
items.map((item, index) =>
|
|
391
404
|
rateLimit(async () => {
|
|
405
|
+
const metadataMapSaveSingle = {};
|
|
406
|
+
|
|
392
407
|
// this is a file so extended is at another endpoint
|
|
393
408
|
if (item?.fileProperties?.extension && !completed.includes(item.id)) {
|
|
394
409
|
try {
|
|
@@ -397,8 +412,10 @@ class Asset extends MetadataType {
|
|
|
397
412
|
} catch (ex) {
|
|
398
413
|
failed.push({ item: item, error: ex });
|
|
399
414
|
}
|
|
400
|
-
// even if
|
|
415
|
+
// still return even if extended failed
|
|
401
416
|
metadataMap[item.customerKey] = item;
|
|
417
|
+
// even if the extended file failed, still save the metadata
|
|
418
|
+
metadataMapSaveSingle[item.customerKey] = item;
|
|
402
419
|
}
|
|
403
420
|
// this is a complex type which stores data in the asset itself
|
|
404
421
|
else if (!completed.includes(item.id)) {
|
|
@@ -406,8 +423,10 @@ class Asset extends MetadataType {
|
|
|
406
423
|
const extendedItem = await this.client.rest.get(
|
|
407
424
|
'asset/v1/content/assets/' + item.id
|
|
408
425
|
);
|
|
409
|
-
// only
|
|
426
|
+
// only return the metadata if we have extended content
|
|
410
427
|
metadataMap[item.customerKey] = extendedItem;
|
|
428
|
+
// only save the metadata if we have extended content
|
|
429
|
+
metadataMapSaveSingle[item.customerKey] = extendedItem;
|
|
411
430
|
// overwrite the original item with the extended content to ensure retrieve() returns it
|
|
412
431
|
items[index] = extendedItem;
|
|
413
432
|
} catch (ex) {
|
|
@@ -415,9 +434,9 @@ class Asset extends MetadataType {
|
|
|
415
434
|
}
|
|
416
435
|
}
|
|
417
436
|
completed.push(item.id);
|
|
418
|
-
if (
|
|
437
|
+
if (metadataMapSaveSingle[item.customerKey]) {
|
|
419
438
|
await this.saveResults(
|
|
420
|
-
|
|
439
|
+
metadataMapSaveSingle,
|
|
421
440
|
retrieveDir,
|
|
422
441
|
'asset-' + subType,
|
|
423
442
|
templateVariables
|
|
@@ -730,6 +749,9 @@ class Asset extends MetadataType {
|
|
|
730
749
|
// define asset's subtype
|
|
731
750
|
const subType = this._getSubtype(metadata);
|
|
732
751
|
|
|
752
|
+
// #0 format blocks in slots for deployment
|
|
753
|
+
await this._preDeployTasksBocks(metadata);
|
|
754
|
+
|
|
733
755
|
// #1 get text extracts back into the JSON
|
|
734
756
|
await this._mergeCode(metadata, deployDir, subType);
|
|
735
757
|
|
|
@@ -738,7 +760,7 @@ class Asset extends MetadataType {
|
|
|
738
760
|
|
|
739
761
|
// only execute #3 if we are deploying / copying from one BU to another, not while using mcdev as a developer tool
|
|
740
762
|
if (
|
|
741
|
-
|
|
763
|
+
Util.OPTIONS.autoMidSuffix &&
|
|
742
764
|
this.buObject.mid &&
|
|
743
765
|
metadata.memberId != this.buObject.mid && // soft comparison to accomodate for string-version of mid
|
|
744
766
|
!metadata[this.definition.keyField].endsWith(this.buObject.mid)
|
|
@@ -928,9 +950,17 @@ class Asset extends MetadataType {
|
|
|
928
950
|
}: ${extractedFile.fileName}.${extractedFile.fileExt}.`
|
|
929
951
|
);
|
|
930
952
|
}
|
|
953
|
+
|
|
954
|
+
// apply templating to subfolders
|
|
931
955
|
extractedFile.subFolder = extractedFile.subFolder
|
|
932
956
|
.map((el) => (el === templateName ? metadata[this.definition.keyField] : el))
|
|
933
957
|
.map((el) => this.applyTemplateValues(el, templateVariables));
|
|
958
|
+
|
|
959
|
+
// apply templating to filenames of extracted code
|
|
960
|
+
extractedFile.fileName = extractedFile.fileName
|
|
961
|
+
.split('.')
|
|
962
|
+
.map((el) => (el === templateName ? metadata[this.definition.keyField] : el))
|
|
963
|
+
.join('.');
|
|
934
964
|
}
|
|
935
965
|
|
|
936
966
|
// #2 binary extracts
|
|
@@ -1017,11 +1047,83 @@ class Asset extends MetadataType {
|
|
|
1017
1047
|
);
|
|
1018
1048
|
}
|
|
1019
1049
|
metadata.category = {
|
|
1020
|
-
id: cache.
|
|
1050
|
+
id: cache.getFolderId(metadata.r__folder_Path),
|
|
1021
1051
|
};
|
|
1022
1052
|
delete metadata.r__folder_Path;
|
|
1023
1053
|
}
|
|
1024
1054
|
|
|
1055
|
+
/**
|
|
1056
|
+
* helper for {@link Asset.preDeployTasks} that loads extracted code content back into JSON
|
|
1057
|
+
*
|
|
1058
|
+
* @param {AssetItem} metadata a single asset definition
|
|
1059
|
+
* @returns {Promise.<void>} fileList for templating (disregarded during deployment)
|
|
1060
|
+
*/
|
|
1061
|
+
static async _preDeployTasksBocks(metadata) {
|
|
1062
|
+
switch (metadata.assetType.name) {
|
|
1063
|
+
case 'templatebasedemail': // message
|
|
1064
|
+
case 'htmlemail':
|
|
1065
|
+
case 'webpage': {
|
|
1066
|
+
// metadata.views.html.slots.<>.blocks.<>.content (optional)
|
|
1067
|
+
if (metadata?.views?.html?.slots) {
|
|
1068
|
+
await this._preDeployTasksBocks_slots(metadata.views.html.slots);
|
|
1069
|
+
}
|
|
1070
|
+
break;
|
|
1071
|
+
}
|
|
1072
|
+
case 'template': {
|
|
1073
|
+
// metadata.slots.<>.blocks.<>.content (optional)
|
|
1074
|
+
if (metadata?.slots) {
|
|
1075
|
+
await this._preDeployTasksBocks_slots(metadata.slots);
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
break;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
/**
|
|
1083
|
+
* helper for {@link Asset.preDeployTasks} that loads extracted code content back into JSON
|
|
1084
|
+
*
|
|
1085
|
+
* @param {object} metadataSlots metadata.views.html.slots or deeper slots.<>.blocks.<>.slots
|
|
1086
|
+
* @returns {Promise.<void>} -
|
|
1087
|
+
*/
|
|
1088
|
+
static async _preDeployTasksBocks_slots(metadataSlots) {
|
|
1089
|
+
for (const slot in metadataSlots) {
|
|
1090
|
+
if (Object.prototype.hasOwnProperty.call(metadataSlots, slot)) {
|
|
1091
|
+
const slotObj = metadataSlots[slot];
|
|
1092
|
+
// found slot
|
|
1093
|
+
if (slotObj.blocks) {
|
|
1094
|
+
for (const block in slotObj.blocks) {
|
|
1095
|
+
if (Object.prototype.hasOwnProperty.call(slotObj.blocks, block)) {
|
|
1096
|
+
const asset = slotObj.blocks[block];
|
|
1097
|
+
if (asset.r__asset_key) {
|
|
1098
|
+
// by only running the following if r__asset_key was set, we simply skip anything that wasnt resolved during retrieve
|
|
1099
|
+
asset.customerKey = asset.r__asset_key;
|
|
1100
|
+
asset.id = cache.searchForField(
|
|
1101
|
+
'asset',
|
|
1102
|
+
asset.r__asset_key,
|
|
1103
|
+
'customerKey',
|
|
1104
|
+
'id'
|
|
1105
|
+
);
|
|
1106
|
+
asset.objectID = cache.searchForField(
|
|
1107
|
+
'asset',
|
|
1108
|
+
asset.r__asset_key,
|
|
1109
|
+
'customerKey',
|
|
1110
|
+
'objectID'
|
|
1111
|
+
);
|
|
1112
|
+
delete asset.r__asset_key;
|
|
1113
|
+
asset.thumbnail = {
|
|
1114
|
+
thumbnailUrl: '/v1/assets/' + asset.id + '/thumbnail',
|
|
1115
|
+
};
|
|
1116
|
+
|
|
1117
|
+
this.setFolderId(asset);
|
|
1118
|
+
}
|
|
1119
|
+
await this._preDeployTasksBocks(asset);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1025
1127
|
/**
|
|
1026
1128
|
* helper for {@link Asset.preDeployTasks} that loads extracted code content back into JSON
|
|
1027
1129
|
*
|
|
@@ -1406,6 +1508,7 @@ class Asset extends MetadataType {
|
|
|
1406
1508
|
if (slotObj.blocks) {
|
|
1407
1509
|
for (const block in slotObj.blocks) {
|
|
1408
1510
|
if (Object.prototype.hasOwnProperty.call(slotObj.blocks, block)) {
|
|
1511
|
+
const asset = slotObj.blocks[block];
|
|
1409
1512
|
const fileName = `${prefix}.[${slot}-${block}]${subtypeExtension}`;
|
|
1410
1513
|
if (
|
|
1411
1514
|
await File.pathExists(
|
|
@@ -1419,7 +1522,7 @@ class Asset extends MetadataType {
|
|
|
1419
1522
|
// the main content can be empty (=not set up yet) hence check if we did extract sth or else readFile() will print error msgs
|
|
1420
1523
|
// if an extracted block was found, save it back into JSON
|
|
1421
1524
|
if (!fileListOnly) {
|
|
1422
|
-
|
|
1525
|
+
asset.content = await File.readFilteredFilename(
|
|
1423
1526
|
[...readDirArr, 'blocks'],
|
|
1424
1527
|
fileName,
|
|
1425
1528
|
'html'
|
|
@@ -1431,21 +1534,35 @@ class Asset extends MetadataType {
|
|
|
1431
1534
|
subFolder: [...subDirArr, templateFileName, 'blocks'],
|
|
1432
1535
|
fileName: fileName,
|
|
1433
1536
|
fileExt: 'html',
|
|
1434
|
-
content:
|
|
1537
|
+
content: asset.content,
|
|
1435
1538
|
});
|
|
1436
1539
|
}
|
|
1437
1540
|
}
|
|
1438
|
-
if (
|
|
1541
|
+
if (asset.slots) {
|
|
1439
1542
|
// * recursion: each block can have slots of its own
|
|
1440
1543
|
await this._mergeCode_slots(
|
|
1441
1544
|
`${prefix}.[${slot}-${block}]`,
|
|
1442
|
-
|
|
1545
|
+
asset.slots,
|
|
1443
1546
|
readDirArr,
|
|
1444
1547
|
subtypeExtension,
|
|
1445
1548
|
subDirArr,
|
|
1446
1549
|
fileList,
|
|
1447
1550
|
customerKey,
|
|
1448
|
-
templateName
|
|
1551
|
+
templateName,
|
|
1552
|
+
fileListOnly
|
|
1553
|
+
);
|
|
1554
|
+
} else if (asset?.views?.html?.slots) {
|
|
1555
|
+
// * recursion: each block can have slots of its own
|
|
1556
|
+
await this._mergeCode_slots(
|
|
1557
|
+
`${prefix}.[${slot}-${block}]`,
|
|
1558
|
+
asset.views.html.slots,
|
|
1559
|
+
readDirArr,
|
|
1560
|
+
subtypeExtension,
|
|
1561
|
+
subDirArr,
|
|
1562
|
+
fileList,
|
|
1563
|
+
customerKey,
|
|
1564
|
+
templateName,
|
|
1565
|
+
fileListOnly
|
|
1449
1566
|
);
|
|
1450
1567
|
}
|
|
1451
1568
|
}
|
|
@@ -1635,6 +1752,8 @@ class Asset extends MetadataType {
|
|
|
1635
1752
|
}
|
|
1636
1753
|
}
|
|
1637
1754
|
/**
|
|
1755
|
+
* helper for {@link Asset.postRetrieveTasks} via {@link Asset._extractCode}
|
|
1756
|
+
*
|
|
1638
1757
|
* @param {string} prefix usually the customerkey
|
|
1639
1758
|
* @param {object} metadataSlots metadata.views.html.slots or deeper slots.<>.blocks.<>.slots
|
|
1640
1759
|
* @param {object[]} codeArr to be extended array for extracted code
|
|
@@ -1647,22 +1766,47 @@ class Asset extends MetadataType {
|
|
|
1647
1766
|
// found slot
|
|
1648
1767
|
for (const block in slotObj.blocks) {
|
|
1649
1768
|
if (Object.prototype.hasOwnProperty.call(slotObj.blocks, block)) {
|
|
1650
|
-
|
|
1769
|
+
const asset = slotObj.blocks[block];
|
|
1770
|
+
if (asset.content) {
|
|
1651
1771
|
// found content block
|
|
1652
|
-
const code =
|
|
1772
|
+
const code = asset.content;
|
|
1653
1773
|
codeArr.push({
|
|
1654
1774
|
subFolder: ['blocks'],
|
|
1655
1775
|
fileName: `${prefix}.[${slot}-${block}]`,
|
|
1656
1776
|
fileExt: 'html',
|
|
1657
1777
|
content: code,
|
|
1658
1778
|
});
|
|
1659
|
-
delete
|
|
1779
|
+
delete asset.content;
|
|
1780
|
+
}
|
|
1781
|
+
// clean up fields from the other content block
|
|
1782
|
+
if (asset.id) {
|
|
1783
|
+
try {
|
|
1784
|
+
asset.r__asset_key = cache.searchForField(
|
|
1785
|
+
'asset',
|
|
1786
|
+
asset.id,
|
|
1787
|
+
'id',
|
|
1788
|
+
'customerKey'
|
|
1789
|
+
);
|
|
1790
|
+
// only delete this if we found the asset in cache, otherwise ignore
|
|
1791
|
+
delete asset.id;
|
|
1792
|
+
delete asset.objectID;
|
|
1793
|
+
delete asset.customerKey;
|
|
1794
|
+
delete asset.thumbnail;
|
|
1795
|
+
} catch {
|
|
1796
|
+
Util.logger.debug(
|
|
1797
|
+
` - asset id:${asset.id} / key:${asset.customerKey} / name:${asset.name} not found in cache`
|
|
1798
|
+
);
|
|
1799
|
+
}
|
|
1660
1800
|
}
|
|
1661
|
-
if (
|
|
1801
|
+
if (asset.category?.id) {
|
|
1802
|
+
this.setFolderPath(asset);
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1805
|
+
if (asset.slots) {
|
|
1662
1806
|
// * recursion: each block can have slots of its own
|
|
1663
1807
|
this._extractCode_slots(
|
|
1664
1808
|
`${prefix}.[${slot}-${block}]`,
|
|
1665
|
-
|
|
1809
|
+
asset.slots,
|
|
1666
1810
|
codeArr
|
|
1667
1811
|
);
|
|
1668
1812
|
}
|
|
@@ -1674,9 +1818,9 @@ class Asset extends MetadataType {
|
|
|
1674
1818
|
/**
|
|
1675
1819
|
* Returns file contents mapped to their fileName without '.json' ending
|
|
1676
1820
|
*
|
|
1677
|
-
* @param {string} dir directory
|
|
1678
|
-
* @param {boolean} _ unused parameter
|
|
1679
|
-
* @param {string[]} selectedSubType asset, message, ...
|
|
1821
|
+
* @param {string} dir directory with json files, e.g. /retrieve/cred/bu/asset, /deploy/cred/bu/asset, /template/asset
|
|
1822
|
+
* @param {boolean} [_] unused parameter
|
|
1823
|
+
* @param {string[]} [selectedSubType] asset, message, ...
|
|
1680
1824
|
* @returns {Promise.<MetadataTypeMap>} fileName => fileContent map
|
|
1681
1825
|
*/
|
|
1682
1826
|
static async getJsonFromFS(dir, _, selectedSubType) {
|
|
@@ -1691,46 +1835,7 @@ class Asset extends MetadataType {
|
|
|
1691
1835
|
continue;
|
|
1692
1836
|
}
|
|
1693
1837
|
const currentdir = File.normalizePath([dir, subtype]);
|
|
1694
|
-
|
|
1695
|
-
const files = await File.readdir(currentdir, { withFileTypes: true });
|
|
1696
|
-
|
|
1697
|
-
for (const dirent of files) {
|
|
1698
|
-
try {
|
|
1699
|
-
let thisDir = currentdir;
|
|
1700
|
-
let fileName = dirent.name;
|
|
1701
|
-
if (dirent.isDirectory()) {
|
|
1702
|
-
// complex types with more than one extracted piece of code are saved in their
|
|
1703
|
-
// own subfolder (with folder name = CustomerKey)
|
|
1704
|
-
// this section aims to find that json in the subfolder
|
|
1705
|
-
const subfolderFiles = await File.readdir(
|
|
1706
|
-
File.normalizePath([currentdir, dirent.name])
|
|
1707
|
-
);
|
|
1708
|
-
for (const subFileName of subfolderFiles) {
|
|
1709
|
-
if (subFileName.endsWith('-meta.json')) {
|
|
1710
|
-
fileName = subFileName;
|
|
1711
|
-
thisDir = File.normalizePath([currentdir, dirent.name]);
|
|
1712
|
-
}
|
|
1713
|
-
}
|
|
1714
|
-
}
|
|
1715
|
-
if (fileName.endsWith('-meta.json')) {
|
|
1716
|
-
const fileContent = await File.readJSONFile(
|
|
1717
|
-
thisDir,
|
|
1718
|
-
fileName,
|
|
1719
|
-
false
|
|
1720
|
-
);
|
|
1721
|
-
// subtype will change the metadata suffix length
|
|
1722
|
-
const fileNameWithoutEnding = fileName.slice(
|
|
1723
|
-
0,
|
|
1724
|
-
-17 - subtype.length
|
|
1725
|
-
);
|
|
1726
|
-
fileName2FileContent[fileNameWithoutEnding] = fileContent;
|
|
1727
|
-
}
|
|
1728
|
-
} catch (ex) {
|
|
1729
|
-
// by catching this in the loop we gracefully handle the issue and move on to the next file
|
|
1730
|
-
Util.metadataLogger('debug', this.definition.type, 'getJsonFromFS', ex);
|
|
1731
|
-
}
|
|
1732
|
-
}
|
|
1733
|
-
}
|
|
1838
|
+
await this._getJsonFromFS(currentdir, subtype, fileName2FileContent);
|
|
1734
1839
|
}
|
|
1735
1840
|
} catch (ex) {
|
|
1736
1841
|
// this will catch issues with readdir
|
|
@@ -1739,6 +1844,41 @@ class Asset extends MetadataType {
|
|
|
1739
1844
|
}
|
|
1740
1845
|
return fileName2FileContent;
|
|
1741
1846
|
}
|
|
1847
|
+
/**
|
|
1848
|
+
* helper for {@link Asset.getJsonFromFS} that reads the file system for metadata files
|
|
1849
|
+
*
|
|
1850
|
+
* @param {string} currentdir directory to scan
|
|
1851
|
+
* @param {string} subtype single subtype of asset
|
|
1852
|
+
* @param {MetadataTypeMap} fileName2FileContent fileName => fileContent map
|
|
1853
|
+
*/
|
|
1854
|
+
static async _getJsonFromFS(currentdir, subtype, fileName2FileContent) {
|
|
1855
|
+
if (await File.pathExists(currentdir)) {
|
|
1856
|
+
const fileEnding = `.asset-${subtype}-meta.json`;
|
|
1857
|
+
const fileEndingLength = fileEnding.length;
|
|
1858
|
+
const files = await File.readdir(currentdir, { withFileTypes: true });
|
|
1859
|
+
for (const dirent of files) {
|
|
1860
|
+
const fileName = dirent.name;
|
|
1861
|
+
try {
|
|
1862
|
+
if (dirent.isDirectory()) {
|
|
1863
|
+
await this._getJsonFromFS(
|
|
1864
|
+
File.normalizePath([currentdir, fileName]),
|
|
1865
|
+
subtype,
|
|
1866
|
+
fileName2FileContent
|
|
1867
|
+
);
|
|
1868
|
+
} else if (fileName.endsWith(fileEnding)) {
|
|
1869
|
+
const fileContent = await File.readJSONFile(currentdir, fileName, false);
|
|
1870
|
+
// subtype will change the metadata suffix length
|
|
1871
|
+
const fileNameWithoutEnding = fileName.slice(0, -fileEndingLength);
|
|
1872
|
+
fileName2FileContent[fileNameWithoutEnding] = fileContent;
|
|
1873
|
+
}
|
|
1874
|
+
} catch (ex) {
|
|
1875
|
+
// by catching this in the loop we gracefully handle the issue and move on to the next file
|
|
1876
|
+
Util.metadataLogger('debug', this.definition.type, 'getJsonFromFS', ex);
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1742
1882
|
/**
|
|
1743
1883
|
* check template directory for complex types that open subfolders for their subtypes
|
|
1744
1884
|
*
|
|
@@ -2058,7 +2198,7 @@ class Asset extends MetadataType {
|
|
|
2058
2198
|
}
|
|
2059
2199
|
if (json.sharedWith && Array.isArray(json.sharedWith)) {
|
|
2060
2200
|
Util.logger.warn(
|
|
2061
|
-
`
|
|
2201
|
+
` - Shared with: ${json.sharedWith
|
|
2062
2202
|
.map(
|
|
2063
2203
|
(mid) =>
|
|
2064
2204
|
Util.inverseGet(
|
|
@@ -2169,9 +2309,10 @@ class Asset extends MetadataType {
|
|
|
2169
2309
|
*
|
|
2170
2310
|
* @param {MetadataTypeItem} item single metadata item
|
|
2171
2311
|
* @param {string} retrieveDir directory where metadata is saved
|
|
2312
|
+
* @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates
|
|
2172
2313
|
* @returns {Promise.<MetadataTypeItem>} key of the item that was updated
|
|
2173
2314
|
*/
|
|
2174
|
-
static async replaceCbReference(item, retrieveDir) {
|
|
2315
|
+
static async replaceCbReference(item, retrieveDir, findAssetKeys) {
|
|
2175
2316
|
const responseItem = structuredClone(item);
|
|
2176
2317
|
const parentName = `${this.definition.type} ${item[this.definition.keyField]}`;
|
|
2177
2318
|
let changes = false;
|
|
@@ -2190,7 +2331,11 @@ class Asset extends MetadataType {
|
|
|
2190
2331
|
const fileListChanged = [];
|
|
2191
2332
|
for (const file of fileList) {
|
|
2192
2333
|
try {
|
|
2193
|
-
file.content = ReplaceCbReference.replaceReference(
|
|
2334
|
+
file.content = ReplaceCbReference.replaceReference(
|
|
2335
|
+
file.content,
|
|
2336
|
+
parentName,
|
|
2337
|
+
findAssetKeys
|
|
2338
|
+
);
|
|
2194
2339
|
changes = true;
|
|
2195
2340
|
fileListChanged.push(file);
|
|
2196
2341
|
} catch (ex) {
|
|
@@ -2199,16 +2344,17 @@ class Asset extends MetadataType {
|
|
|
2199
2344
|
}
|
|
2200
2345
|
}
|
|
2201
2346
|
}
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2347
|
+
if (!findAssetKeys) {
|
|
2348
|
+
// save what was changed regardless of other errors
|
|
2349
|
+
for (const extractedFile of fileListChanged) {
|
|
2350
|
+
File.writeToFile(
|
|
2351
|
+
[retrieveDir, ...extractedFile.subFolder],
|
|
2352
|
+
extractedFile.fileName,
|
|
2353
|
+
extractedFile.fileExt,
|
|
2354
|
+
extractedFile.content,
|
|
2355
|
+
extractedFile.encoding || null
|
|
2356
|
+
);
|
|
2357
|
+
}
|
|
2212
2358
|
}
|
|
2213
2359
|
|
|
2214
2360
|
if (error) {
|
|
@@ -2217,7 +2363,7 @@ class Asset extends MetadataType {
|
|
|
2217
2363
|
|
|
2218
2364
|
if (!changes) {
|
|
2219
2365
|
const ex = new Error('No changes made to the code.');
|
|
2220
|
-
// @ts-expect-error
|
|
2366
|
+
// @ts-expect-error custom error object
|
|
2221
2367
|
ex.code = 200;
|
|
2222
2368
|
throw ex;
|
|
2223
2369
|
}
|
|
@@ -2232,9 +2378,10 @@ class Asset extends MetadataType {
|
|
|
2232
2378
|
*
|
|
2233
2379
|
* @param {MetadataTypeMap} metadataMap list of metadata (keyField => metadata)
|
|
2234
2380
|
* @param {string} retrieveDir retrieve dir including cred and bu
|
|
2381
|
+
* @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates
|
|
2235
2382
|
* @returns {Promise.<string[]>} Returns list of keys for which references were replaced
|
|
2236
2383
|
*/
|
|
2237
|
-
static async replaceCbReferenceLoop(metadataMap, retrieveDir) {
|
|
2384
|
+
static async replaceCbReferenceLoop(metadataMap, retrieveDir, findAssetKeys) {
|
|
2238
2385
|
const keysForDeploy = [];
|
|
2239
2386
|
if (!metadataMap) {
|
|
2240
2387
|
// if a type was skipped e.g. because it shall only be looked at on the parent then we would expect metadataMap to be undefined
|
|
@@ -2246,8 +2393,7 @@ class Asset extends MetadataType {
|
|
|
2246
2393
|
.join(' and ');
|
|
2247
2394
|
|
|
2248
2395
|
if (Object.keys(metadataMap).length) {
|
|
2249
|
-
Util.logger.
|
|
2250
|
-
// const baseDir = [retrieveDir, ...this.definition.type.split('-')];
|
|
2396
|
+
Util.logger.debug(` - Searching in ${this.definition.type} `);
|
|
2251
2397
|
const deployMap = {};
|
|
2252
2398
|
|
|
2253
2399
|
for (const key in metadataMap) {
|
|
@@ -2260,34 +2406,133 @@ class Asset extends MetadataType {
|
|
|
2260
2406
|
|
|
2261
2407
|
try {
|
|
2262
2408
|
// add key but make sure to turn it into string or else numeric keys will be filtered later
|
|
2263
|
-
deployMap[key] = await this.replaceCbReference(
|
|
2409
|
+
deployMap[key] = await this.replaceCbReference(
|
|
2410
|
+
item,
|
|
2411
|
+
retrieveDir,
|
|
2412
|
+
findAssetKeys
|
|
2413
|
+
);
|
|
2264
2414
|
|
|
2265
2415
|
// ! this method is equal to the super version except that it does not run saveToDisk here
|
|
2266
2416
|
// await this.saveToDisk(deployMap, key, baseDir);
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2417
|
+
if (findAssetKeys) {
|
|
2418
|
+
keysForDeploy.push(...[...findAssetKeys].map((key) => key + ''));
|
|
2419
|
+
} else {
|
|
2420
|
+
keysForDeploy.push(key + '');
|
|
2421
|
+
Util.logger.info(
|
|
2422
|
+
` - added ${this.definition.type} to update queue: ${key}`
|
|
2423
|
+
);
|
|
2424
|
+
}
|
|
2270
2425
|
} catch (ex) {
|
|
2271
2426
|
if (ex.code !== 200) {
|
|
2272
2427
|
// dont print error if we simply did not find relevant content blocks
|
|
2273
2428
|
Util.logger.errorStack(ex, ex.message);
|
|
2274
2429
|
}
|
|
2275
|
-
|
|
2276
|
-
Util.
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2430
|
+
if (!findAssetKeys) {
|
|
2431
|
+
Util.logger.info(
|
|
2432
|
+
Util.getGrayMsg(
|
|
2433
|
+
` ☇ skipping ${this.definition.type} ${
|
|
2434
|
+
item[this.definition.keyField]
|
|
2435
|
+
}: no ${fromDescription} found`
|
|
2436
|
+
)
|
|
2437
|
+
);
|
|
2438
|
+
}
|
|
2282
2439
|
}
|
|
2283
2440
|
}
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2441
|
+
if (!findAssetKeys) {
|
|
2442
|
+
Util.logger.info(
|
|
2443
|
+
`Found ${keysForDeploy.length} ${this.definition.type}${keysForDeploy.length === 1 ? '' : 's'} to update`
|
|
2444
|
+
);
|
|
2445
|
+
}
|
|
2288
2446
|
}
|
|
2289
2447
|
return keysForDeploy;
|
|
2290
2448
|
}
|
|
2449
|
+
/**
|
|
2450
|
+
*
|
|
2451
|
+
* @param {string[]} keyArr limit retrieval to given metadata type
|
|
2452
|
+
* @param {string} retrieveDir retrieve dir including cred and bu
|
|
2453
|
+
* @param {Set.<string>} findAssetKeys list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates
|
|
2454
|
+
* @returns {Promise.<Set.<string>>} found asset keys
|
|
2455
|
+
*/
|
|
2456
|
+
static async getCbReferenceKeys(keyArr, retrieveDir, findAssetKeys) {
|
|
2457
|
+
if (!Object.prototype.hasOwnProperty.call(this, 'replaceCbReference')) {
|
|
2458
|
+
// only types that have a replaceCbReference method actually have ampscript/ssjs
|
|
2459
|
+
return;
|
|
2460
|
+
}
|
|
2461
|
+
if (!this.getJsonFromFSCache) {
|
|
2462
|
+
// avoid re-reading the same files in every recursive iteration
|
|
2463
|
+
this.getJsonFromFSCache = await this.getJsonFromFS(
|
|
2464
|
+
File.normalizePath([retrieveDir, this.definition.type])
|
|
2465
|
+
);
|
|
2466
|
+
}
|
|
2467
|
+
// get all metadata of the current type; then filter by keys in selectedTypes
|
|
2468
|
+
const metadataMap = Util.filterObjByKeys(this.getJsonFromFSCache, [...findAssetKeys]);
|
|
2469
|
+
const newKeysFound = new Set(
|
|
2470
|
+
await this.replaceCbReferenceLoop(metadataMap, retrieveDir, findAssetKeys)
|
|
2471
|
+
);
|
|
2472
|
+
if (newKeysFound.size) {
|
|
2473
|
+
const keysToCrawl = [];
|
|
2474
|
+
for (const value of newKeysFound) {
|
|
2475
|
+
if (!keyArr.includes(value)) {
|
|
2476
|
+
keyArr.push(value);
|
|
2477
|
+
keysToCrawl.push(value);
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
Util.logger.info(Util.getGrayMsg(` - asset: ${keysToCrawl.join(', ')}`));
|
|
2481
|
+
|
|
2482
|
+
if (keysToCrawl.length) {
|
|
2483
|
+
findAssetKeys = new Set([
|
|
2484
|
+
...findAssetKeys,
|
|
2485
|
+
...(await this.getCbReferenceKeys(keyArr, retrieveDir, new Set(keysToCrawl))),
|
|
2486
|
+
]);
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
return findAssetKeys;
|
|
2490
|
+
}
|
|
2491
|
+
|
|
2492
|
+
/**
|
|
2493
|
+
* optional helper for {@link this.getDependentTypes}
|
|
2494
|
+
*
|
|
2495
|
+
* @param {object} metadataItem metadata json read from filesystem
|
|
2496
|
+
* @param {TypeKeyCombo} dependentTypeKeyCombo list started in this.getDependentTypes
|
|
2497
|
+
*/
|
|
2498
|
+
static getDependentFilesExtra(metadataItem, dependentTypeKeyCombo) {
|
|
2499
|
+
const dependentKeyArr = [];
|
|
2500
|
+
// search:
|
|
2501
|
+
// - metadata.views.html.slots
|
|
2502
|
+
// - metadata.slots
|
|
2503
|
+
if (metadataItem.views?.html?.slots) {
|
|
2504
|
+
this._getDependentFilesExtra(metadataItem.views.html.slots, dependentKeyArr);
|
|
2505
|
+
}
|
|
2506
|
+
if (metadataItem.slots) {
|
|
2507
|
+
this._getDependentFilesExtra(metadataItem.slots, dependentKeyArr);
|
|
2508
|
+
}
|
|
2509
|
+
if (dependentKeyArr.length) {
|
|
2510
|
+
dependentTypeKeyCombo.asset ||= [];
|
|
2511
|
+
dependentTypeKeyCombo.asset.push(...dependentKeyArr);
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
/**
|
|
2515
|
+
* @param {object} slots metadata.views.html.slots or deeper slots.<>.blocks.<>.slots
|
|
2516
|
+
* @param {string[]} dependentKeyArr list of found keys
|
|
2517
|
+
*/
|
|
2518
|
+
static _getDependentFilesExtra(slots, dependentKeyArr) {
|
|
2519
|
+
for (const slot in slots) {
|
|
2520
|
+
for (const block in slots[slot].blocks) {
|
|
2521
|
+
const asset = slots[slot].blocks[block];
|
|
2522
|
+
if (asset.r__asset_key) {
|
|
2523
|
+
dependentKeyArr.push(asset.r__asset_key);
|
|
2524
|
+
}
|
|
2525
|
+
if (asset.views?.html?.slots) {
|
|
2526
|
+
// * recursion: each block can have slots of its own
|
|
2527
|
+
this._getDependentFilesExtra(asset.views.html.slots, dependentKeyArr);
|
|
2528
|
+
}
|
|
2529
|
+
if (asset.slots) {
|
|
2530
|
+
// * recursion: each block can have slots of its own
|
|
2531
|
+
this._getDependentFilesExtra(asset.slots, dependentKeyArr);
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2291
2536
|
}
|
|
2292
2537
|
|
|
2293
2538
|
// Assign definition to static attributes
|