mcdev 4.3.3 → 5.0.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.md +20 -0
- package/.coverage-comment-template.svelte +178 -0
- package/.eslintrc.json +2 -0
- package/.fork/.prettierrc +6 -0
- package/.fork/custom-commands.json +13 -1
- package/.github/ISSUE_TEMPLATE/bug.yml +2 -0
- package/.github/workflows/code-test.yml +36 -0
- package/.github/workflows/coverage-base-update.yml +57 -0
- package/.github/workflows/coverage-develop-branch.yml +41 -0
- package/.github/workflows/coverage-main-branch.yml +41 -0
- package/.github/workflows/coverage.yml +77 -0
- package/.husky/post-checkout +1 -1
- package/.prettierrc +1 -1
- package/.vscode/extensions.json +0 -4
- package/boilerplate/config.json +1 -1
- package/boilerplate/files/.prettierrc +1 -1
- package/boilerplate/files/.vscode/extensions.json +1 -1
- package/boilerplate/files/.vscode/settings.json +1 -0
- package/boilerplate/forcedUpdates.json +8 -0
- package/docs/dist/documentation.md +1261 -433
- package/lib/Builder.js +6 -1
- package/lib/Deployer.js +34 -10
- package/lib/MetadataTypeDefinitions.js +8 -6
- package/lib/MetadataTypeInfo.js +8 -6
- package/lib/Retriever.js +4 -1
- package/lib/cli.js +54 -42
- package/lib/index.js +82 -8
- package/lib/metadataTypes/Asset.js +185 -31
- package/lib/metadataTypes/AttributeGroup.js +0 -1
- package/lib/metadataTypes/Automation.js +48 -5
- package/lib/metadataTypes/Campaign.js +20 -7
- package/lib/metadataTypes/ContentArea.js +1 -1
- package/lib/metadataTypes/DataExtension.js +221 -184
- package/lib/metadataTypes/DataExtensionField.js +12 -19
- package/lib/metadataTypes/DataExtensionTemplate.js +1 -1
- package/lib/metadataTypes/DataExtract.js +1 -1
- package/lib/metadataTypes/DataExtractType.js +1 -1
- package/lib/metadataTypes/Email.js +1 -1
- package/lib/metadataTypes/{EmailSendDefinition.js → EmailSend.js} +5 -5
- package/lib/metadataTypes/{EventDefinition.js → Event.js} +17 -35
- package/lib/metadataTypes/{FtpLocation.js → FileLocation.js} +2 -2
- package/lib/metadataTypes/FileTransfer.js +8 -7
- package/lib/metadataTypes/Filter.js +1 -1
- package/lib/metadataTypes/Folder.js +8 -3
- package/lib/metadataTypes/ImportFile.js +6 -6
- package/lib/metadataTypes/{Interaction.js → Journey.js} +311 -147
- package/lib/metadataTypes/List.js +2 -2
- package/lib/metadataTypes/MetadataType.js +318 -90
- package/lib/metadataTypes/MobileCode.js +0 -1
- package/lib/metadataTypes/MobileKeyword.js +336 -40
- package/lib/metadataTypes/MobileMessage.js +473 -0
- package/lib/metadataTypes/Query.js +114 -32
- package/lib/metadataTypes/Role.js +60 -21
- package/lib/metadataTypes/Script.js +5 -7
- package/lib/metadataTypes/SendClassification.js +40 -0
- package/lib/metadataTypes/SetDefinition.js +1 -7
- package/lib/metadataTypes/TransactionalEmail.js +2 -3
- package/lib/metadataTypes/TransactionalMessage.js +1 -2
- package/lib/metadataTypes/TransactionalSMS.js +8 -15
- package/lib/metadataTypes/{TriggeredSendDefinition.js → TriggeredSend.js} +35 -27
- package/lib/metadataTypes/User.js +1177 -0
- package/lib/metadataTypes/definitions/Asset.definition.js +2 -4
- package/lib/metadataTypes/definitions/AttributeGroup.definition.js +1 -0
- package/lib/metadataTypes/definitions/Automation.definition.js +3 -2
- package/lib/metadataTypes/definitions/Campaign.definition.js +79 -4
- package/lib/metadataTypes/definitions/ContentArea.definition.js +1 -0
- package/lib/metadataTypes/definitions/DataExtension.definition.js +2 -1
- 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 +1 -0
- package/lib/metadataTypes/definitions/DataExtractType.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/{EmailSendDefinition.definition.js → EmailSend.definition.js} +4 -2
- package/lib/metadataTypes/definitions/{EventDefinition.definition.js → Event.definition.js} +2 -1
- package/lib/metadataTypes/definitions/{FtpLocation.definition.js → FileLocation.definition.js} +4 -3
- package/lib/metadataTypes/definitions/FileTransfer.definition.js +3 -2
- package/lib/metadataTypes/definitions/Filter.definition.js +1 -0
- package/lib/metadataTypes/definitions/Folder.definition.js +2 -0
- package/lib/metadataTypes/definitions/ImportFile.definition.js +4 -3
- package/lib/metadataTypes/definitions/{Interaction.definition.js → Journey.definition.js} +11 -2
- package/lib/metadataTypes/definitions/List.definition.js +1 -0
- package/lib/metadataTypes/definitions/MobileCode.definition.js +3 -1
- package/lib/metadataTypes/definitions/MobileKeyword.definition.js +27 -17
- package/lib/metadataTypes/definitions/MobileMessage.definition.js +743 -0
- package/lib/metadataTypes/definitions/Query.definition.js +3 -2
- package/lib/metadataTypes/definitions/Role.definition.js +5 -0
- package/lib/metadataTypes/definitions/Script.definition.js +1 -0
- package/lib/metadataTypes/definitions/SendClassification.definition.js +114 -0
- package/lib/metadataTypes/definitions/SetDefinition.definition.js +1 -0
- package/lib/metadataTypes/definitions/TransactionalEmail.definition.js +2 -1
- package/lib/metadataTypes/definitions/TransactionalPush.definition.js +1 -0
- package/lib/metadataTypes/definitions/TransactionalSMS.definition.js +1 -0
- package/lib/metadataTypes/definitions/{TriggeredSendDefinition.definition.js → TriggeredSend.definition.js} +5 -3
- package/lib/metadataTypes/definitions/User.definition.js +365 -0
- package/lib/retrieveChangelog.js +1 -2
- package/lib/util/auth.js +29 -9
- package/lib/util/businessUnit.js +3 -3
- package/lib/util/cli.js +55 -7
- package/lib/util/devops.js +93 -8
- package/lib/util/file.js +55 -13
- package/lib/util/init.config.js +1 -2
- package/lib/util/init.npm.js +3 -3
- package/lib/util/util.js +68 -14
- package/package.json +16 -15
- package/test/general.test.js +62 -0
- package/test/mockRoot/.mcdevrc.json +7 -5
- package/test/mockRoot/deploy/testInstance/_ParentBU_/user/testBlocked_user.user-meta.json +23 -0
- package/test/mockRoot/deploy/testInstance/_ParentBU_/user/testExisting_user.user-meta.json +31 -0
- package/test/mockRoot/deploy/testInstance/_ParentBU_/user/testNew_user.user-meta.json +27 -0
- package/test/mockRoot/deploy/testInstance/testBU/dataExtension/{childBU_dataextension_test.dataExtension-meta.json → testExisting_dataExtension.dataExtension-meta.json} +2 -2
- package/test/mockRoot/deploy/testInstance/testBU/dataExtension/{testDataExtension.dataExtension-meta.json → testNew_dataExtension.dataExtension-meta.json} +2 -2
- package/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_interaction.interaction-meta.json +576 -0
- package/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/testNew_keyword.mobileKeyword-meta.amp +2 -0
- package/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/testNew_keyword.mobileKeyword-meta.json +10 -0
- package/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/testNew_keyword_blocked.mobileKeyword-meta.amp +2 -0
- package/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/testNew_keyword_blocked.mobileKeyword-meta.json +10 -0
- package/test/mockRoot/deploy/testInstance/testBU/mobileMessage/NTIzOjc4OjA.mobileMessage-meta.amp +1 -0
- package/test/mockRoot/deploy/testInstance/testBU/mobileMessage/NTIzOjc4OjA.mobileMessage-meta.json +61 -0
- package/test/mockRoot/deploy/testInstance/testBU/mobileMessage/new.mobileMessage-meta.amp +1 -0
- package/test/mockRoot/deploy/testInstance/testBU/mobileMessage/new.mobileMessage-meta.json +60 -0
- package/test/mockRoot/deploy/testInstance/testBU/query/testExistingQuery.query-meta.json +1 -1
- package/test/mockRoot/deploy/testInstance/testBU/query/testNewQuery.query-meta.json +1 -1
- package/test/mockRoot/deploy/testInstance/testBU/query/testNewQuery.query-meta.sql +1 -1
- package/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json +1 -1
- package/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testNew_temail.transactionalEmail-meta.json +1 -1
- package/test/resourceFactory.js +13 -0
- package/test/resources/1111111/accountUser/configure-response.xml +70 -0
- package/test/resources/1111111/accountUser/create-response.xml +97 -0
- package/test/resources/1111111/accountUser/retrieve-response.xml +156 -0
- package/test/resources/1111111/accountUser/update-response.xml +111 -0
- package/test/resources/1111111/accountUserAccount/retrieve-response.xml +77 -0
- package/test/resources/1111111/platform/v1/setup/quickflow/data/get-response.json +455 -0
- package/test/resources/1111111/role/retrieve-response.xml +76 -0
- package/test/resources/1111111/user/build-expected.json +16 -0
- package/test/resources/1111111/user/create-expected.json +21 -0
- package/test/resources/1111111/user/retrieve-expected.json +24 -0
- package/test/resources/1111111/user/template-expected.json +16 -0
- package/test/resources/1111111/user/update-expected.json +21 -0
- package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/delete-response.json +1 -0
- package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/get-response.json +17 -0
- package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/patch-response.json +3 -3
- package/test/resources/9999999/automation/v1/queries/get-response.json +21 -4
- package/test/resources/9999999/automation/v1/queries/post-response.json +4 -4
- package/test/resources/9999999/data/v1/customobjectdata/key/{childBU_dataextension_test → testExisting_dataExtension}/rowset/get-response.json +1 -1
- package/test/resources/9999999/dataExtension/build-expected.json +3 -3
- package/test/resources/9999999/dataExtension/create-expected.json +2 -2
- package/test/resources/9999999/dataExtension/create-response.xml +8 -3
- package/test/resources/9999999/dataExtension/retrieve-expected.json +3 -3
- package/test/resources/9999999/dataExtension/retrieve-response.xml +9 -4
- package/test/resources/9999999/dataExtension/template-expected.json +3 -3
- package/test/resources/9999999/dataExtension/update-expected.json +3 -3
- package/test/resources/9999999/dataExtension/update-response.xml +9 -4
- package/test/resources/9999999/dataExtensionField/retrieve-response.xml +14 -9
- package/test/resources/9999999/interaction/v1/interactions/get-response.json +312 -0
- package/test/resources/9999999/interaction/v1/interactions/key_testExisting_interaction/get-response.json +312 -0
- package/test/resources/9999999/interaction/v1/interactions/key_testExisting_interaction/put-response.json +592 -0
- package/test/resources/9999999/journey/build-expected.json +572 -0
- package/test/resources/9999999/journey/get-expected.json +576 -0
- package/test/resources/9999999/journey/put-expected.json +576 -0
- package/test/resources/9999999/journey/template-expected.json +572 -0
- package/test/resources/9999999/legacy/v1/beta/mobile/keyword/NXV4ZFMwTEFwRVczd3RaLUF5X3p5dzo4Njow/get-response.json +42 -0
- package/test/resources/9999999/legacy/v1/beta/mobile/keyword/cTVJaG5oSDJPVUNHcUh6Z3pQT2tVdzo4Njow/delete-response.json +0 -0
- package/test/resources/9999999/legacy/v1/beta/mobile/keyword/get-response.json +1 -0
- package/test/resources/9999999/legacy/v1/beta/mobile/keyword/post-response.json +3 -0
- package/test/resources/9999999/legacy/v1/beta/mobile/message/NTIzOjc4OjA/delete-response.json +0 -0
- package/test/resources/9999999/legacy/v1/beta/mobile/message/NTIzOjc4OjA/get-response.json +106 -0
- package/test/resources/9999999/legacy/v1/beta/mobile/message/NTIzOjc4OjA/post-response.json +0 -0
- package/test/resources/9999999/legacy/v1/beta/mobile/message/NTQ3Ojc4OjA/get-response.json +127 -0
- package/test/resources/9999999/legacy/v1/beta/mobile/message/get-response.json +129 -0
- package/test/resources/9999999/legacy/v1/beta/mobile/message/post-response.json +3 -0
- package/test/resources/9999999/legacy/v1/beta2/data/campaign/get-response.json +29 -0
- package/test/resources/9999999/messaging/v1/email/definitions/post-response.json +1 -1
- package/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/get-response.json +1 -1
- package/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/patch-response.json +1 -1
- package/test/resources/9999999/mobileKeyword/build-expected.amp +2 -0
- package/test/resources/9999999/mobileKeyword/build-expected.json +9 -0
- package/test/resources/9999999/mobileKeyword/get-expected.amp +2 -0
- package/test/resources/9999999/mobileKeyword/get-expected.json +15 -0
- package/test/resources/9999999/mobileKeyword/post-create-expected.amp +2 -0
- package/test/resources/9999999/mobileKeyword/post-create-expected.json +17 -0
- package/test/resources/9999999/mobileKeyword/template-expected.amp +2 -0
- package/test/resources/9999999/mobileKeyword/template-expected.json +9 -0
- package/test/resources/9999999/mobileMessage/build-expected.amp +1 -0
- package/test/resources/9999999/mobileMessage/build-expected.json +60 -0
- package/test/resources/9999999/mobileMessage/get-expected.amp +1 -0
- package/test/resources/9999999/mobileMessage/get-expected.json +61 -0
- package/test/resources/9999999/mobileMessage/post-create-expected.amp +1 -0
- package/test/resources/9999999/mobileMessage/post-create-expected.json +63 -0
- package/test/resources/9999999/mobileMessage/post-update-expected.amp +1 -0
- package/test/resources/9999999/mobileMessage/post-update-expected.json +61 -0
- package/test/resources/9999999/mobileMessage/template-expected.amp +1 -0
- package/test/resources/9999999/mobileMessage/template-expected.json +60 -0
- package/test/resources/9999999/query/build-expected.json +1 -1
- package/test/resources/9999999/query/get-expected.json +1 -1
- package/test/resources/9999999/query/get2-expected.json +11 -0
- package/test/resources/9999999/query/patch-expected.json +1 -1
- package/test/resources/9999999/query/post-expected.json +1 -1
- package/test/resources/9999999/query/template-expected.json +1 -1
- package/test/resources/9999999/queryDefinition/retrieve-response.xml +30 -0
- package/test/resources/9999999/transactionalEmail/build-expected.json +5 -5
- package/test/resources/9999999/transactionalEmail/get-expected.json +1 -1
- package/test/resources/9999999/transactionalEmail/patch-expected.json +1 -1
- package/test/resources/9999999/transactionalEmail/post-expected.json +1 -1
- package/test/resources/9999999/transactionalEmail/template-expected.json +5 -5
- package/test/resources/9999999/transactionalPush/build-expected.json +2 -2
- package/test/resources/9999999/transactionalPush/template-expected.json +2 -2
- package/test/resources/9999999/transactionalSMS/build-expected.json +3 -3
- package/test/resources/9999999/transactionalSMS/template-expected.json +3 -3
- package/test/{dataExtension.test.js → type.dataExtension.test.js} +78 -21
- package/test/{interaction.test.js → type.journey.test.js} +64 -30
- package/test/type.mobileKeyword.test.js +250 -0
- package/test/type.mobileMessage.test.js +205 -0
- package/test/{query.test.js → type.query.test.js} +102 -5
- package/test/{transactionalEmail.test.js → type.transactionalEmail.test.js} +40 -2
- package/test/{transactionalPush.test.js → type.transactionalPush.test.js} +41 -2
- package/test/{transactionalSMS.test.js → type.transactionalSMS.test.js} +73 -3
- package/test/type.user.test.js +160 -0
- package/test/utils.js +17 -5
- package/types/mcdev.d.js +48 -15
- package/.github/workflows/code-analysis.yml +0 -57
- package/lib/metadataTypes/AccountUser.js +0 -426
- package/lib/metadataTypes/definitions/AccountUser.definition.js +0 -227
- package/test/mockRoot/deploy/testInstance/testBU/interaction/testExisting_interaction.interaction-meta.json +0 -266
- package/test/resources/9999999/interaction/build-expected.json +0 -260
- package/test/resources/9999999/interaction/get-expected.json +0 -264
- package/test/resources/9999999/interaction/put-expected.json +0 -264
- package/test/resources/9999999/interaction/template-expected.json +0 -260
- package/test/resources/9999999/interaction/v1/interactions/put-response.json +0 -280
- /package/test/mockRoot/deploy/testInstance/testBU/{interaction → journey}/testNew_interaction.interaction-meta.json +0 -0
- /package/test/resources/9999999/{interaction → journey}/post-expected.json +0 -0
|
@@ -25,7 +25,7 @@ class Asset extends MetadataType {
|
|
|
25
25
|
*/
|
|
26
26
|
static async retrieve(retrieveDir, _, subTypeArr, key) {
|
|
27
27
|
const items = [];
|
|
28
|
-
subTypeArr
|
|
28
|
+
subTypeArr ||= this._getSubTypes();
|
|
29
29
|
await File.initPrettier();
|
|
30
30
|
// loop through subtypes and return results of each subType for caching (saving is handled per subtype)
|
|
31
31
|
for (const subType of subTypeArr) {
|
|
@@ -113,6 +113,7 @@ class Asset extends MetadataType {
|
|
|
113
113
|
* @returns {Promise} Promise
|
|
114
114
|
*/
|
|
115
115
|
static create(metadata) {
|
|
116
|
+
delete metadata.businessUnitAvailability;
|
|
116
117
|
const uri = '/asset/v1/content/assets/';
|
|
117
118
|
return super.createREST(metadata, uri);
|
|
118
119
|
}
|
|
@@ -495,6 +496,78 @@ class Asset extends MetadataType {
|
|
|
495
496
|
return metadata;
|
|
496
497
|
}
|
|
497
498
|
|
|
499
|
+
/**
|
|
500
|
+
* Gets executed after deployment of metadata type
|
|
501
|
+
*
|
|
502
|
+
* @param {TYPE.MetadataTypeMap} metadata metadata mapped by their keyField
|
|
503
|
+
* @param {TYPE.MetadataTypeMap} _ originalMetadata to be updated (contains additioanl fields)
|
|
504
|
+
* @param {{created: number, updated: number}} createdUpdated counter representing successful creates/updates
|
|
505
|
+
* @param {boolean} [isRefresh] optional flag to indicate that triggeredSend should be refreshed after deployment of assets
|
|
506
|
+
* @returns {Promise.<void>} -
|
|
507
|
+
*/
|
|
508
|
+
static async postDeployTasks(metadata, _, createdUpdated, isRefresh) {
|
|
509
|
+
if (isRefresh) {
|
|
510
|
+
if (createdUpdated.updated) {
|
|
511
|
+
// only run this if assets were updated. for created assets we do not expect
|
|
512
|
+
this._refreshTriggeredSend(metadata);
|
|
513
|
+
} else {
|
|
514
|
+
Util.logger.warn(
|
|
515
|
+
'You set the --refresh flag but no updated assets found. Skipping refresh of triggeredSendDefinitions.'
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* helper for {@link postDeployTasks}. triggers a refresh of active triggerredSendDefinitions associated with the updated asset-message items. Gets executed if isRefresh is true.
|
|
523
|
+
*
|
|
524
|
+
* @private
|
|
525
|
+
* @param {TYPE.MetadataTypeMap} metadata metadata mapped by their keyField
|
|
526
|
+
* @returns {Promise.<void>} -
|
|
527
|
+
*/
|
|
528
|
+
static async _refreshTriggeredSend(metadata) {
|
|
529
|
+
// get legacyData.legacyId from assets to compare to TSD's metadata.Email.ID to
|
|
530
|
+
const legacyIdArr = Object.keys(metadata)
|
|
531
|
+
.map((key) => metadata[key]?.legacyData?.legacyId)
|
|
532
|
+
.filter(Boolean);
|
|
533
|
+
|
|
534
|
+
if (!legacyIdArr.length) {
|
|
535
|
+
Util.logger.warn(
|
|
536
|
+
'No legacyId found in updated emails. Skipping refresh of triggeredSendDefinitions.'
|
|
537
|
+
);
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
// prep triggeredSendDefinition class
|
|
541
|
+
const TriggeredSend = require('./TriggeredSend');
|
|
542
|
+
TriggeredSend.properties = this.properties;
|
|
543
|
+
TriggeredSend.buObject = this.buObject;
|
|
544
|
+
TriggeredSend.client = this.client;
|
|
545
|
+
try {
|
|
546
|
+
// find refreshable TSDs
|
|
547
|
+
const tsdObj = (await TriggeredSend.findRefreshableItems()).metadata;
|
|
548
|
+
|
|
549
|
+
const tsdCountInitial = Object.keys(tsdObj).length;
|
|
550
|
+
const emailCount = legacyIdArr.length;
|
|
551
|
+
// filter TSDs by legacyId
|
|
552
|
+
for (const key in tsdObj) {
|
|
553
|
+
if (!legacyIdArr.includes(tsdObj[key].Email.ID)) {
|
|
554
|
+
delete tsdObj[key];
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
const tsdCountFiltered = Object.keys(tsdObj).length;
|
|
558
|
+
Util.logger.info(
|
|
559
|
+
`Found ${tsdCountFiltered} out of ${tsdCountInitial} total triggeredSendDefinitions for ${emailCount} deployed emails. Commencing validation...`
|
|
560
|
+
);
|
|
561
|
+
|
|
562
|
+
// get keys of TSDs to refresh
|
|
563
|
+
const keyArr = await TriggeredSend.getKeysForValidTSDs(tsdObj);
|
|
564
|
+
|
|
565
|
+
await TriggeredSend.refresh(keyArr);
|
|
566
|
+
} catch {
|
|
567
|
+
Util.logger.warn('Failed to refresh triggeredSendDefinition');
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
498
571
|
/**
|
|
499
572
|
* prepares an asset definition for deployment
|
|
500
573
|
*
|
|
@@ -818,16 +891,17 @@ class Asset extends MetadataType {
|
|
|
818
891
|
|
|
819
892
|
// metadata.views.html.content (mandatory)
|
|
820
893
|
// the main content can be empty (=not set up yet) hence check if we did extract sth or else readFile() will print error msgs
|
|
894
|
+
const fileName = 'views.html.content' + subtypeExtension;
|
|
821
895
|
if (
|
|
822
896
|
(await File.pathExists(
|
|
823
|
-
File.normalizePath([...readDirArr,
|
|
897
|
+
File.normalizePath([...readDirArr, `${fileName}.html`])
|
|
824
898
|
)) &&
|
|
825
899
|
metadata.views.html
|
|
826
900
|
) {
|
|
827
901
|
if (!fileListOnly) {
|
|
828
902
|
metadata.views.html.content = await File.readFilteredFilename(
|
|
829
903
|
readDirArr,
|
|
830
|
-
|
|
904
|
+
fileName,
|
|
831
905
|
'html'
|
|
832
906
|
);
|
|
833
907
|
}
|
|
@@ -836,7 +910,7 @@ class Asset extends MetadataType {
|
|
|
836
910
|
// to use this method in templating, store a copy of the info in fileList
|
|
837
911
|
fileList.push({
|
|
838
912
|
subFolder: [...subDirArr, customerKey],
|
|
839
|
-
fileName:
|
|
913
|
+
fileName: fileName,
|
|
840
914
|
fileExt: 'html',
|
|
841
915
|
content: metadata.views.html.content,
|
|
842
916
|
});
|
|
@@ -859,6 +933,59 @@ class Asset extends MetadataType {
|
|
|
859
933
|
}
|
|
860
934
|
break;
|
|
861
935
|
}
|
|
936
|
+
case 'template': {
|
|
937
|
+
// template-template
|
|
938
|
+
// this complex type always creates its own subdir per asset
|
|
939
|
+
subDirArr = [this.definition.type, subType];
|
|
940
|
+
readDirArr = [deployDir, ...subDirArr, templateName || customerKey];
|
|
941
|
+
const fileName = 'content' + subtypeExtension;
|
|
942
|
+
|
|
943
|
+
const fileExtArr = ['html']; // eslint-disable-line no-case-declarations
|
|
944
|
+
for (const ext of fileExtArr) {
|
|
945
|
+
if (
|
|
946
|
+
await File.pathExists(
|
|
947
|
+
File.normalizePath([...readDirArr, `${fileName}.${ext}`])
|
|
948
|
+
)
|
|
949
|
+
) {
|
|
950
|
+
// the main content can be empty (=not set up yet) hence check if we did extract sth or else readFile() will print error msgs
|
|
951
|
+
if (!fileListOnly) {
|
|
952
|
+
metadata.content = await File.readFilteredFilename(
|
|
953
|
+
readDirArr,
|
|
954
|
+
fileName,
|
|
955
|
+
ext
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
if (templateName) {
|
|
959
|
+
// to use this method in templating, store a copy of the info in fileList
|
|
960
|
+
fileList.push({
|
|
961
|
+
subFolder: subDirArr,
|
|
962
|
+
fileName: fileName,
|
|
963
|
+
fileExt: ext,
|
|
964
|
+
content: metadata.content,
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
// break loop when found
|
|
968
|
+
break;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
// metadata.slots.<>.blocks.<>.content (optional)
|
|
973
|
+
if (metadata?.slots) {
|
|
974
|
+
await this._mergeCode_slots(
|
|
975
|
+
'slots',
|
|
976
|
+
metadata.slots,
|
|
977
|
+
readDirArr,
|
|
978
|
+
subtypeExtension,
|
|
979
|
+
subDirArr,
|
|
980
|
+
fileList,
|
|
981
|
+
customerKey,
|
|
982
|
+
templateName,
|
|
983
|
+
fileListOnly
|
|
984
|
+
);
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
break;
|
|
988
|
+
}
|
|
862
989
|
case 'textonlyemail': {
|
|
863
990
|
// message
|
|
864
991
|
// metadata.views.text.content
|
|
@@ -970,7 +1097,6 @@ class Asset extends MetadataType {
|
|
|
970
1097
|
|
|
971
1098
|
break;
|
|
972
1099
|
}
|
|
973
|
-
case 'template': // template-template
|
|
974
1100
|
case 'buttonblock': // block - Button Block
|
|
975
1101
|
case 'freeformblock': // block
|
|
976
1102
|
case 'htmlblock': // block
|
|
@@ -983,12 +1109,7 @@ class Asset extends MetadataType {
|
|
|
983
1109
|
// metadata.content
|
|
984
1110
|
subDirArr = [this.definition.type, subType];
|
|
985
1111
|
readDirArr = [deployDir, ...subDirArr];
|
|
986
|
-
const fileExtArr = ['html']; // eslint-disable-line no-case-declarations
|
|
987
|
-
if (metadata.assetType.name === 'codesnippetblock') {
|
|
988
|
-
// extracted code snippets should end on the right extension
|
|
989
|
-
// we are making a few assumptions during retrieve to pick the right one
|
|
990
|
-
fileExtArr.push('amp', 'sjss');
|
|
991
|
-
}
|
|
1112
|
+
const fileExtArr = ['html', 'ssjs', 'amp']; // eslint-disable-line no-case-declarations
|
|
992
1113
|
for (const ext of fileExtArr) {
|
|
993
1114
|
if (
|
|
994
1115
|
await File.pathExists(
|
|
@@ -1005,6 +1126,9 @@ class Asset extends MetadataType {
|
|
|
1005
1126
|
(templateName || customerKey) + subtypeExtension,
|
|
1006
1127
|
ext
|
|
1007
1128
|
);
|
|
1129
|
+
if (ext === 'ssjs') {
|
|
1130
|
+
metadata.content = `<script runat="server">\n${metadata.content}</script>`;
|
|
1131
|
+
}
|
|
1008
1132
|
}
|
|
1009
1133
|
if (templateName) {
|
|
1010
1134
|
// to use this method in templating, store a copy of the info in fileList
|
|
@@ -1117,14 +1241,14 @@ class Asset extends MetadataType {
|
|
|
1117
1241
|
// unfortunately, asset's key can contain spaces at beginning/end which can break the file system when folders are created with it
|
|
1118
1242
|
const customerKey = metadata.customerKey.trim();
|
|
1119
1243
|
switch (metadata.assetType.name) {
|
|
1120
|
-
case 'templatebasedemail': // message
|
|
1244
|
+
case 'templatebasedemail': // message-templatebasedemail
|
|
1121
1245
|
case 'htmlemail': {
|
|
1122
|
-
// message
|
|
1246
|
+
// message-htmlemail
|
|
1123
1247
|
// metadata.views.html.content (mandatory)
|
|
1124
1248
|
if (metadata.views?.html?.content?.length) {
|
|
1125
1249
|
codeArr.push({
|
|
1126
1250
|
subFolder: null,
|
|
1127
|
-
fileName: '
|
|
1251
|
+
fileName: 'views.html.content',
|
|
1128
1252
|
fileExt: 'html',
|
|
1129
1253
|
content: metadata.views.html.content,
|
|
1130
1254
|
});
|
|
@@ -1142,8 +1266,32 @@ class Asset extends MetadataType {
|
|
|
1142
1266
|
subFolder: [customerKey],
|
|
1143
1267
|
};
|
|
1144
1268
|
}
|
|
1269
|
+
case 'template': {
|
|
1270
|
+
// template-template
|
|
1271
|
+
// metadata.content
|
|
1272
|
+
const fileExt = 'html'; // eslint-disable-line no-case-declarations
|
|
1273
|
+
if (metadata?.content?.length) {
|
|
1274
|
+
codeArr.push({
|
|
1275
|
+
subFolder: null,
|
|
1276
|
+
fileName: 'content',
|
|
1277
|
+
fileExt: fileExt,
|
|
1278
|
+
content: metadata.content,
|
|
1279
|
+
});
|
|
1280
|
+
delete metadata.content;
|
|
1281
|
+
}
|
|
1282
|
+
// metadata.slots.<>.blocks.<>.content (optional)
|
|
1283
|
+
if (metadata.slots) {
|
|
1284
|
+
this._extractCode_slots('slots', metadata.slots, codeArr);
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
return {
|
|
1288
|
+
json: metadata,
|
|
1289
|
+
codeArr: codeArr,
|
|
1290
|
+
subFolder: [customerKey],
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1145
1293
|
case 'textonlyemail': {
|
|
1146
|
-
// message
|
|
1294
|
+
// message-textonlyemail
|
|
1147
1295
|
// metadata.views.text.content
|
|
1148
1296
|
if (metadata.views?.text?.content?.length) {
|
|
1149
1297
|
codeArr.push({
|
|
@@ -1157,7 +1305,7 @@ class Asset extends MetadataType {
|
|
|
1157
1305
|
return { json: metadata, codeArr: codeArr, subFolder: null };
|
|
1158
1306
|
}
|
|
1159
1307
|
case 'webpage': {
|
|
1160
|
-
// asset
|
|
1308
|
+
// asset-webpage
|
|
1161
1309
|
// metadata.views.html.content (pre & post 20222)
|
|
1162
1310
|
if (metadata.views?.html?.content?.length) {
|
|
1163
1311
|
codeArr.push({
|
|
@@ -1192,31 +1340,37 @@ class Asset extends MetadataType {
|
|
|
1192
1340
|
subFolder: [customerKey],
|
|
1193
1341
|
};
|
|
1194
1342
|
}
|
|
1195
|
-
case '
|
|
1196
|
-
case '
|
|
1197
|
-
case '
|
|
1198
|
-
case '
|
|
1199
|
-
case '
|
|
1200
|
-
case '
|
|
1201
|
-
case '
|
|
1202
|
-
case 'smartcaptureblock': // other
|
|
1343
|
+
case 'buttonblock': // block-buttonblock
|
|
1344
|
+
case 'freeformblock': // block-freeformblock
|
|
1345
|
+
case 'htmlblock': // block-htmlblock
|
|
1346
|
+
case 'icemailformblock': // block-icemailformblock - Interactive Content Email Form
|
|
1347
|
+
case 'imageblock': // block-imageblock - Image Block
|
|
1348
|
+
case 'textblock': // block-textblock
|
|
1349
|
+
case 'smartcaptureblock': // other-smartcaptureblock
|
|
1203
1350
|
case 'codesnippetblock': {
|
|
1204
|
-
// other
|
|
1351
|
+
// other-codesnippetblock
|
|
1205
1352
|
// metadata.content
|
|
1206
|
-
let fileExt
|
|
1207
|
-
|
|
1353
|
+
let fileExt;
|
|
1354
|
+
let content = metadata?.content;
|
|
1355
|
+
const ssjs = Util.getSsjs(metadata?.content);
|
|
1356
|
+
|
|
1357
|
+
if (ssjs) {
|
|
1358
|
+
fileExt = 'ssjs';
|
|
1359
|
+
content = ssjs;
|
|
1360
|
+
} else if (
|
|
1208
1361
|
metadata.assetType.name === 'codesnippetblock' && // extracted code snippets should end on the right extension
|
|
1209
|
-
|
|
1210
|
-
metadata?.content?.includes('%%[')
|
|
1362
|
+
content?.includes('%%[')
|
|
1211
1363
|
) {
|
|
1212
1364
|
fileExt = 'amp';
|
|
1365
|
+
} else {
|
|
1366
|
+
fileExt = 'html';
|
|
1213
1367
|
}
|
|
1214
|
-
if (
|
|
1368
|
+
if (content?.length) {
|
|
1215
1369
|
codeArr.push({
|
|
1216
1370
|
subFolder: null,
|
|
1217
1371
|
fileName: customerKey,
|
|
1218
1372
|
fileExt: fileExt,
|
|
1219
|
-
content:
|
|
1373
|
+
content: content,
|
|
1220
1374
|
});
|
|
1221
1375
|
delete metadata.content;
|
|
1222
1376
|
}
|
|
@@ -230,12 +230,11 @@ class Automation extends MetadataType {
|
|
|
230
230
|
* @param {TYPE.AutomationMap} metadata metadata mapped by their keyField
|
|
231
231
|
* @param {string} targetBU name/shorthand of target businessUnit for mapping
|
|
232
232
|
* @param {string} retrieveDir directory where metadata after deploy should be saved
|
|
233
|
+
* @param {boolean} [isRefresh] optional flag - so far not used by automation
|
|
233
234
|
* @returns {Promise.<TYPE.AutomationMap>} Promise
|
|
234
235
|
*/
|
|
235
|
-
static async deploy(metadata, targetBU, retrieveDir) {
|
|
236
|
-
const
|
|
237
|
-
const upsertResults = await this.upsert(metadata, targetBU);
|
|
238
|
-
await this.postDeployTasks(upsertResults, orignalMetadata);
|
|
236
|
+
static async deploy(metadata, targetBU, retrieveDir, isRefresh) {
|
|
237
|
+
const upsertResults = await this.upsert(metadata, targetBU, isRefresh);
|
|
239
238
|
await this.saveResults(upsertResults, retrieveDir, null);
|
|
240
239
|
return upsertResults;
|
|
241
240
|
}
|
|
@@ -868,7 +867,7 @@ class Automation extends MetadataType {
|
|
|
868
867
|
row1.push(
|
|
869
868
|
`| ${column.title}${
|
|
870
869
|
column.description
|
|
871
|
-
? `<br>_<small>${column.description.
|
|
870
|
+
? `<br>_<small>${column.description.replaceAll('\n', '<br>')}</small>_`
|
|
872
871
|
: ''
|
|
873
872
|
} `
|
|
874
873
|
);
|
|
@@ -1000,6 +999,50 @@ class Automation extends MetadataType {
|
|
|
1000
999
|
return super.getFilesToCommit(keyArr);
|
|
1001
1000
|
}
|
|
1002
1001
|
}
|
|
1002
|
+
/**
|
|
1003
|
+
* helper to allow us to select single metadata entries via REST
|
|
1004
|
+
*
|
|
1005
|
+
* @private
|
|
1006
|
+
* @param {string} key customer key
|
|
1007
|
+
* @returns {Promise.<string>} objectId or enpty string
|
|
1008
|
+
*/
|
|
1009
|
+
static async _getObjectIdForSingleRetrieve(key) {
|
|
1010
|
+
const response = await this.client.soap.retrieve('Program', ['ObjectID'], {
|
|
1011
|
+
filter: {
|
|
1012
|
+
leftOperand: 'CustomerKey',
|
|
1013
|
+
operator: 'equals',
|
|
1014
|
+
rightOperand: key,
|
|
1015
|
+
},
|
|
1016
|
+
});
|
|
1017
|
+
return response?.Results?.length ? response.Results[0].ObjectID : null;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* Delete a metadata item from the specified business unit
|
|
1022
|
+
*
|
|
1023
|
+
* @param {string} customerKey Identifier of data extension
|
|
1024
|
+
* @returns {boolean} deletion success status
|
|
1025
|
+
*/
|
|
1026
|
+
static async deleteByKey(customerKey) {
|
|
1027
|
+
// the delete endpoint returns a general exception if the automation does not exist; handle it gracefully instead by adding a retrieve first
|
|
1028
|
+
const objectId = customerKey ? await this._getObjectIdForSingleRetrieve(customerKey) : null;
|
|
1029
|
+
if (!objectId) {
|
|
1030
|
+
Util.logger.error(` - automation not found`);
|
|
1031
|
+
return false;
|
|
1032
|
+
}
|
|
1033
|
+
return super.deleteByKeySOAP(customerKey, 'CustomerKey');
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* clean up after deleting a metadata item
|
|
1037
|
+
*
|
|
1038
|
+
* @param {string} customerKey Identifier of metadata item
|
|
1039
|
+
* @returns {void}
|
|
1040
|
+
*/
|
|
1041
|
+
static async postDeleteTasks(customerKey) {
|
|
1042
|
+
// delete local copy: retrieve/cred/bu/.../...-meta.json
|
|
1043
|
+
// delete local copy: retrieve/cred/bu/.../...-doc.md
|
|
1044
|
+
await super.postDeleteTasks(customerKey, [`${this.definition.type}-doc.md`]);
|
|
1045
|
+
}
|
|
1003
1046
|
}
|
|
1004
1047
|
|
|
1005
1048
|
// Assign definition to static attributes
|
|
@@ -21,31 +21,44 @@ class Campaign extends MetadataType {
|
|
|
21
21
|
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise
|
|
22
22
|
*/
|
|
23
23
|
static async retrieve(retrieveDir, _, __, key) {
|
|
24
|
-
const res = await super.retrieveREST(
|
|
24
|
+
const res = await super.retrieveREST(
|
|
25
|
+
retrieveDir,
|
|
26
|
+
'/legacy/v1/beta2/data/campaign/',
|
|
27
|
+
null,
|
|
28
|
+
key
|
|
29
|
+
);
|
|
25
30
|
// get assignments
|
|
26
|
-
|
|
31
|
+
Util.logger.info(`Retrieving: campaignAsset`);
|
|
27
32
|
const campaignAssets = await Promise.all(
|
|
28
33
|
Object.keys(res.metadata).map((key) =>
|
|
29
|
-
this.getAssetTags(retrieveDir, res.metadata[key].
|
|
34
|
+
this.getAssetTags(retrieveDir, res.metadata[key].campaignId, key)
|
|
30
35
|
)
|
|
31
36
|
);
|
|
32
37
|
Util.logger.info(
|
|
33
|
-
`Downloaded:
|
|
38
|
+
`Downloaded: campaignAsset (${campaignAssets.flat().length})` + Util.getKeysString(key)
|
|
34
39
|
);
|
|
35
40
|
|
|
36
41
|
return res;
|
|
37
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Retrieves event definition metadata for caching
|
|
45
|
+
*
|
|
46
|
+
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
|
|
47
|
+
*/
|
|
48
|
+
static retrieveForCache() {
|
|
49
|
+
return super.retrieveREST(null, '/legacy/v1/beta2/data/campaign/');
|
|
50
|
+
}
|
|
38
51
|
|
|
39
52
|
/**
|
|
40
53
|
* Parses campaign asset response body and returns metadata entries mapped to their id
|
|
41
54
|
*
|
|
42
55
|
* @param {string} retrieveDir folder where to save
|
|
43
|
-
* @param {string}
|
|
56
|
+
* @param {string} campaignId of camapaign to retrieve
|
|
44
57
|
* @param {string} name of camapaign for saving
|
|
45
58
|
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Campaign Asset Object
|
|
46
59
|
*/
|
|
47
|
-
static async getAssetTags(retrieveDir,
|
|
48
|
-
const res = await this.client.rest.getBulk(`/hub/v1/campaigns/${
|
|
60
|
+
static async getAssetTags(retrieveDir, campaignId, name) {
|
|
61
|
+
const res = await this.client.rest.getBulk(`/hub/v1/campaigns/${campaignId}/assets`);
|
|
49
62
|
|
|
50
63
|
for (const asset of res.items) {
|
|
51
64
|
await File.writeJSONToFile(
|
|
@@ -36,7 +36,7 @@ class ContentArea extends MetadataType {
|
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
// !dont activate `await File.initPrettier('html');` as we only want to retrieve for migration and formatting might mess with the outcome
|
|
39
|
-
return super.retrieveSOAP(retrieveDir, requestParams);
|
|
39
|
+
return super.retrieveSOAP(retrieveDir, requestParams, key);
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
42
|
* manages post retrieve steps
|