From 74c1d45002c86e0829d0dc455e8b73adca81b786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Thu, 12 Jan 2023 17:12:45 +0100 Subject: [PATCH 001/132] #621: show batch-msg for REST --- lib/util/auth.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/util/auth.js b/lib/util/auth.js index e69169b36..720f7b0f1 100644 --- a/lib/util/auth.js +++ b/lib/util/auth.js @@ -93,7 +93,9 @@ function setupSDK(sessionKey, authObject) { eventHandlers: { onLoop: (type, req) => { Util.logger.info( - ` - Requesting next batch (currently ${req.Results.length} records)` + ` - Requesting next batch (currently ${ + req.Results?.length || req.items?.length + } records)` ); }, onRefresh: (authObject) => { From 228c0c629d6160cfc7490cc259970776a0993563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Thu, 12 Jan 2023 17:23:17 +0100 Subject: [PATCH 002/132] #623: enable getting more than first 50 journeys --- lib/metadataTypes/definitions/Interaction.definition.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index 5c8030380..bef68e179 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -9,7 +9,7 @@ module.exports = { createdNameField: null, lastmodDateField: 'modifiedDate', lastmodNameField: null, - restPagination: false, + restPagination: true, type: 'interaction', typeDescription: 'Journey from Builder (internally called "Interaction").', typeRetrieveByDefault: false, From 5e67e1291cc7a84ff41f735e5847e414ed28b97f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 13 Jan 2023 11:43:51 +0100 Subject: [PATCH 003/132] #625: show rest endpoint for RestErrors --- lib/util/util.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/util/util.js b/lib/util/util.js index 478460f5e..e7175cf08 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -508,7 +508,12 @@ function startLogger() { if (message) { // ! this method only sets exitCode=1 if message-param was set // if not, then this method purely outputs debug information and should not change the exitCode - winstonError(message + ': ' + ex.message); + winstonError(message + ':'); + winstonError(' ' + ex.message); + if (ex.endpoint) { + // ex.endpoint is only available if 'ex' is of type RestError + winstonError(' endpoint: ' + ex.endpoint); + } Util.signalFatalError(); } let stack; From a52ccaa2e9ec9b9060eae50cf7afebc3bd279724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 13 Jan 2023 14:38:01 +0100 Subject: [PATCH 004/132] #628: do not save triggeredSend that have no valid email, list or folder during retrieve --- docs/dist/documentation.md | 12 ++++++ lib/metadataTypes/TriggeredSendDefinition.js | 39 +++++++++++++++++--- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index b223cc782..3bd0fc7a3 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -4727,6 +4727,7 @@ MessageSendActivity MetadataType * [.update(metadata)](#TriggeredSendDefinition.update) ⇒ Promise * [.deleteByKey(buObject, customerKey)](#TriggeredSendDefinition.deleteByKey) ⇒ Promise.<boolean> * [.postRetrieveTasks(metadata)](#TriggeredSendDefinition.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem + * [.setFolderPath(metadata)](#TriggeredSendDefinition.setFolderPath) * [.parseMetadata(metadata)](#TriggeredSendDefinition.parseMetadata) ⇒ TYPE.MetadataTypeItem * [.preDeployTasks(metadata)](#TriggeredSendDefinition.preDeployTasks) ⇒ TYPE.MetadataTypeItem @@ -4795,6 +4796,17 @@ manages post retrieve steps | --- | --- | --- | | metadata | TYPE.MetadataTypeItem | a single query | + + +### TriggeredSendDefinition.setFolderPath(metadata) +generic script that retrieves the folder path from cache and updates the given metadata with it after retrieve + +**Kind**: static method of [TriggeredSendDefinition](#TriggeredSendDefinition) + +| Param | Type | Description | +| --- | --- | --- | +| metadata | TYPE.MetadataTypeItem | a single script activity definition | + ### TriggeredSendDefinition.parseMetadata(metadata) ⇒ TYPE.MetadataTypeItem diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index 2853c1608..3d03d2980 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -127,6 +127,29 @@ class TriggeredSendDefinition extends MetadataType { static postRetrieveTasks(metadata) { return this.parseMetadata(metadata); } + /** + * generic script that retrieves the folder path from cache and updates the given metadata with it after retrieve + * + * @param {TYPE.MetadataTypeItem} metadata a single script activity definition + */ + static setFolderPath(metadata) { + try { + metadata.r__folder_Path = cache.searchForField( + 'folder', + metadata[this.definition.folderIdField], + 'ID', + 'Path' + ); + delete metadata[this.definition.folderIdField]; + } catch (ex) { + Util.logger.verbose( + ` - skipping ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }): Could not find folder (${ex.message})` + ); + throw ex; + } + } /** * parses retrieved Metadata before saving * @@ -137,7 +160,11 @@ class TriggeredSendDefinition extends MetadataType { // remove IsPlatformObject, always has to be 'false' delete metadata.IsPlatformObject; // folder - super.setFolderPath(metadata); + try { + this.setFolderPath(metadata); + } catch { + return; + } // email try { @@ -164,9 +191,10 @@ class TriggeredSendDefinition extends MetadataType { metadata.r__assetMessage_Key = contentBuilderEmailKey; delete metadata.Email; } catch { - Util.logger.warn( - ` - ${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': Could not find email with ID ${metadata.Email.ID} in Classic nor in Content Builder.` + Util.logger.verbose( + ` - skipping ${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': Could not find email with ID ${metadata.Email.ID} in Classic nor in Content Builder.` ); + return; } } // List (optional) @@ -175,9 +203,10 @@ class TriggeredSendDefinition extends MetadataType { metadata.r__list_PathName = cache.getListPathName(metadata.List.ID, 'ID'); delete metadata.List; } catch (ex) { - Util.logger.warn( - ` - ${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': ${ex.message}` + Util.logger.verbose( + ` - skipping ${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': ${ex.message}` ); + return; } } From b72dfc0df920682e37ecf89dbfc5ebb5af8a7042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 13 Jan 2023 14:40:59 +0100 Subject: [PATCH 005/132] #628: remove custom filter for journey builder sends folder --- lib/metadataTypes/TriggeredSendDefinition.js | 28 -------------------- 1 file changed, 28 deletions(-) diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index 3d03d2980..cbdf1d85b 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -90,34 +90,6 @@ class TriggeredSendDefinition extends MetadataType { return super.deleteByKeySOAP(buObject, customerKey, false); } - /** - * checks if the current metadata entry should be saved on retrieve or not - * - * @static - * @param {object} metadataEntry metadata entry - * @returns {boolean} if false, do not save - * @memberof MetadataType - */ - static isFiltered(metadataEntry) { - try { - // get folder path to be able to filter journey-created TSDs - const folderPath = cache.searchForField( - 'folder', - metadataEntry.CategoryID, - 'ID', - 'Path' - ); - - if (folderPath?.startsWith('Journey Builder Sends/')) { - // filter out any triggered sends that were auto-created by journeys - return true; - } - } catch { - // handle it in parseMetadata() - } - return false; - } - /** * manages post retrieve steps * From afdf4068c36a07f52ac7a5f8852c86620ed4bf41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 13 Jan 2023 14:43:02 +0100 Subject: [PATCH 006/132] #628: remove filter on IsPlatformObject because it seems to filter journey TSDs --- lib/metadataTypes/TriggeredSendDefinition.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index cbdf1d85b..c20026327 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -25,18 +25,9 @@ class TriggeredSendDefinition extends MetadataType { /** @type {TYPE.SoapRequestParams} */ let requestParams = { filter: { - leftOperand: { - // somehow that parameter controls visible (non deleted?) email send activities - leftOperand: 'IsPlatformObject', - operator: 'equals', - rightOperand: false, - }, - operator: 'AND', - rightOperand: { - leftOperand: 'TriggeredSendStatus', - operator: 'IN', - rightOperand: ['New', 'Active', 'Inactive'], // New, Active=Running, Inactive=Paused, (Deleted) - }, + leftOperand: 'TriggeredSendStatus', + operator: 'IN', + rightOperand: ['New', 'Active', 'Inactive', 'Moved', 'Canceled'], // New, Active=Running, Inactive=Paused, (Deleted) }, }; if (key) { From 8b101ed819a8f5447db5db10ab30caaa07686b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 13 Jan 2023 15:16:28 +0100 Subject: [PATCH 007/132] #627: add delete support for interaction --- docs/dist/documentation.md | 44 ++++++++++++++++++++++++++++++++ lib/metadataTypes/Interaction.js | 15 +++++++++++ 2 files changed, 59 insertions(+) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index b223cc782..c3aaad4cf 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -2879,6 +2879,13 @@ Script MetadataType **Kind**: global class **Extends**: [MetadataType](#MetadataType) + +* [Interaction](#Interaction) ⇐ [MetadataType](#MetadataType) + * [.retrieve(retrieveDir, [_], [__], [___], [key])](#Interaction.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.deleteByKey(buObject, key)](#Interaction.deleteByKey) ⇒ Promise.<boolean> + * [.update(metadata)](#Interaction.update) ⇒ Promise + * [.create(metadata)](#Interaction.create) ⇒ Promise + ### Interaction.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> @@ -2896,6 +2903,43 @@ Endpoint /interaction/v1/interactions?extras=all&pageSize=50000 return 50000 Scr | [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | + + +### Interaction.deleteByKey(buObject, key) ⇒ Promise.<boolean> +Delete a metadata item from the specified business unit + +**Kind**: static method of [Interaction](#Interaction) +**Returns**: Promise.<boolean> - deletion success status + +| Param | Type | Description | +| --- | --- | --- | +| buObject | TYPE.BuObject | references credentials | +| key | string | Identifier of item | + + + +### Interaction.update(metadata) ⇒ Promise +Updates a single item + +**Kind**: static method of [Interaction](#Interaction) +**Returns**: Promise - Promise + +| Param | Type | Description | +| --- | --- | --- | +| metadata | TYPE.MetadataTypeItem | a single item | + + + +### Interaction.create(metadata) ⇒ Promise +Creates a single item + +**Kind**: static method of [Interaction](#Interaction) +**Returns**: Promise - Promise + +| Param | Type | Description | +| --- | --- | --- | +| metadata | TYPE.MetadataTypeItem | a single item | + ## List ⇐ [MetadataType](#MetadataType) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 64d9df6c8..a0c7f0adf 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -31,6 +31,21 @@ class Interaction extends MetadataType { key ); } + /** + * Delete a metadata item from the specified business unit + * + * @param {TYPE.BuObject} buObject references credentials + * @param {string} key Identifier of item + * @returns {Promise.} deletion success status + */ + static deleteByKey(buObject, key) { + return super.deleteByKeyREST( + buObject, + '/interaction/v1/interactions/key:' + key, + key, + false + ); + } } // Assign definition to static attributes From cd06ab9e3d6bb75db8e673cfc7f4b88adf4f481e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 13 Jan 2023 15:28:55 +0100 Subject: [PATCH 008/132] #627: add UPDATE support for interaction --- docs/dist/documentation.md | 5 +++-- lib/metadataTypes/Interaction.js | 9 +++++++++ lib/metadataTypes/MetadataType.js | 7 +++++-- .../definitions/Interaction.definition.js | 18 +++++++++--------- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index c3aaad4cf..f2453e532 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -3067,7 +3067,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.upsert(metadata, deployDir, [buObject])](#MetadataType.upsert) ⇒ Promise.<TYPE.MetadataTypeMap> * [.createREST(metadataEntry, uri)](#MetadataType.createREST) ⇒ Promise * [.createSOAP(metadataEntry, [overrideType], [handleOutside])](#MetadataType.createSOAP) ⇒ Promise - * [.updateREST(metadataEntry, uri)](#MetadataType.updateREST) ⇒ Promise + * [.updateREST(metadataEntry, uri, [usePut])](#MetadataType.updateREST) ⇒ Promise * [.updateSOAP(metadataEntry, [overrideType], [handleOutside])](#MetadataType.updateSOAP) ⇒ Promise * [._handleSOAPErrors(ex, msg, [metadataEntry], [handleOutside])](#MetadataType._handleSOAPErrors) * [.retrieveSOAP(retrieveDir, buObject, [requestParams], [additionalFields])](#MetadataType.retrieveSOAP) ⇒ Promise.<TYPE.MetadataTypeMapObj> @@ -3373,7 +3373,7 @@ Creates a single metadata entry via fuel-soap (generic lib not wrapper) -### MetadataType.updateREST(metadataEntry, uri) ⇒ Promise +### MetadataType.updateREST(metadataEntry, uri, [usePut]) ⇒ Promise Updates a single metadata entry via REST **Kind**: static method of [MetadataType](#MetadataType) @@ -3383,6 +3383,7 @@ Updates a single metadata entry via REST | --- | --- | --- | | metadataEntry | TYPE.MetadataTypeItem | a single metadata Entry | | uri | string | rest endpoint for PATCH | +| [usePut] | boolean | some update requests require PUT instead of PATCH | diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index a0c7f0adf..5b45c955e 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -46,6 +46,15 @@ class Interaction extends MetadataType { false ); } + /** + * Updates a single item + * + * @param {TYPE.MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static update(metadata) { + return super.updateREST(metadata, '/interaction/v1/interactions/', true); + } } // Assign definition to static attributes diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index cc1070dcb..85e282476 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -624,12 +624,15 @@ class MetadataType { * * @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry * @param {string} uri rest endpoint for PATCH + * @param {boolean} [usePut] some update requests require PUT instead of PATCH * @returns {Promise} Promise */ - static async updateREST(metadataEntry, uri) { + static async updateREST(metadataEntry, uri, usePut) { this.removeNotUpdateableFields(metadataEntry); try { - const response = await this.client.rest.patch(uri, metadataEntry); + const response = usePut + ? await this.client.rest.put(uri, metadataEntry) + : await this.client.rest.patch(uri, metadataEntry); this.checkForErrors(response); // some times, e.g. automation dont return a key in their update response and hence we need to fall back to name Util.logger.info( diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index bef68e179..efe4be58d 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -104,9 +104,9 @@ module.exports = { }, id: { isCreateable: false, - isUpdateable: true, - retrieving: false, - template: false, + isUpdateable: false, + retrieving: true, + template: true, }, key: { isCreateable: true, @@ -128,9 +128,9 @@ module.exports = { }, modifiedDate: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, name: { isCreateable: true, @@ -388,15 +388,15 @@ module.exports = { }, version: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, workflowApiVersion: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, }, }; From 86a51f07b9a889d841bbefecd040c8633224b60b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 13 Jan 2023 15:37:28 +0100 Subject: [PATCH 009/132] #627: add CREATE support for interaction --- lib/metadataTypes/Interaction.js | 10 ++++++++++ .../definitions/Interaction.definition.js | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 5b45c955e..33c794edc 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -55,6 +55,16 @@ class Interaction extends MetadataType { static update(metadata) { return super.updateREST(metadata, '/interaction/v1/interactions/', true); } + + /** + * Creates a single item + * + * @param {TYPE.MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static create(metadata) { + return super.createREST(metadata, '/interaction/v1/interactions/'); + } } // Assign definition to static attributes diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index efe4be58d..305fd0c44 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -393,7 +393,7 @@ module.exports = { template: true, }, workflowApiVersion: { - isCreateable: false, + isCreateable: true, isUpdateable: true, retrieving: true, template: true, From 4732b087a451b30eb833c5cda175522d5255b9c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 13 Jan 2023 15:51:52 +0100 Subject: [PATCH 010/132] #627: allow retrieving single journeys by ID instead of key IDs are visible in URL, Keys are not visible --- lib/metadataTypes/Interaction.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 33c794edc..24ec1340a 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -21,11 +21,20 @@ class Interaction extends MetadataType { * @returns {Promise.} Promise */ static retrieve(retrieveDir, _, __, ___, key) { + let singleKey = ''; + if (key) { + /* eslint-disable unicorn/prefer-ternary */ + if (key.startWidth('id:')) { + // ! allow selecting journeys by ID because that's what users see in the URL + singleKey = '/' + encodeURIComponent(key); + } else { + singleKey = '/key:' + encodeURIComponent(key); + } + /* eslint-enable unicorn/prefer-ternary */ + } return super.retrieveREST( retrieveDir, - `/interaction/v1/interactions${ - key ? '/key:' + encodeURIComponent(key) : '' - }?extras=all`, + `/interaction/v1/interactions${singleKey}?extras=all`, null, null, key From 3e1103dbc2b67a74e648b2bb9fef38d8e45c935c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 13 Jan 2023 19:00:04 +0100 Subject: [PATCH 011/132] #627: fix typo --- lib/metadataTypes/Interaction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 24ec1340a..410a7e105 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -24,7 +24,7 @@ class Interaction extends MetadataType { let singleKey = ''; if (key) { /* eslint-disable unicorn/prefer-ternary */ - if (key.startWidth('id:')) { + if (key.startsWith('id:')) { // ! allow selecting journeys by ID because that's what users see in the URL singleKey = '/' + encodeURIComponent(key); } else { From 59c4aae24050cde7f17af5eacf4ab1b0baaa0f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 13 Jan 2023 19:03:56 +0100 Subject: [PATCH 012/132] #627: remove helper string --- lib/metadataTypes/Interaction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 410a7e105..c79cd25dd 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -26,7 +26,7 @@ class Interaction extends MetadataType { /* eslint-disable unicorn/prefer-ternary */ if (key.startsWith('id:')) { // ! allow selecting journeys by ID because that's what users see in the URL - singleKey = '/' + encodeURIComponent(key); + singleKey = '/' + encodeURIComponent(key.slice(3)); } else { singleKey = '/key:' + encodeURIComponent(key); } From 497a57bd063fc5c8167b62c0f90637c38f1a6524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 13 Jan 2023 19:11:44 +0100 Subject: [PATCH 013/132] #627: ensure interactions retrieved by id get saved with key as name --- lib/metadataTypes/MetadataType.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 85e282476..dab77c637 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -825,6 +825,9 @@ class MetadataType { } } else if (singleRetrieve) { // some types will return a single item intead of an array if the key is supported by their api + if (singleRetrieve.startsWith('id:')) { + singleRetrieve = body[keyField]; + } metadataStructure[singleRetrieve] = body; return metadataStructure; } From e0a40836fb2ab37f25b49a82dc02f3f5555219d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 10:47:21 +0100 Subject: [PATCH 014/132] #627: disable fields for create according to docs --- docs/dist/documentation.md | 40 ++++++++++++++++++- .../definitions/Interaction.definition.js | 10 +++-- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index f2453e532..1ddae2f79 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -2885,6 +2885,8 @@ Script MetadataType * [.deleteByKey(buObject, key)](#Interaction.deleteByKey) ⇒ Promise.<boolean> * [.update(metadata)](#Interaction.update) ⇒ Promise * [.create(metadata)](#Interaction.create) ⇒ Promise + * [.postRetrieveTasks(metadata)](#Interaction.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem + * [.preDeployTasks(metadata)](#Interaction.preDeployTasks) ⇒ TYPE.MetadataTypeItem @@ -2940,6 +2942,30 @@ Creates a single item | --- | --- | --- | | metadata | TYPE.MetadataTypeItem | a single item | + + +### Interaction.postRetrieveTasks(metadata) ⇒ TYPE.MetadataTypeItem +manages post retrieve steps + +**Kind**: static method of [Interaction](#Interaction) +**Returns**: TYPE.MetadataTypeItem - Array with one metadata object and one query string + +| Param | Type | Description | +| --- | --- | --- | +| metadata | TYPE.MetadataTypeItem | a single query | + + + +### Interaction.preDeployTasks(metadata) ⇒ TYPE.MetadataTypeItem +prepares a TSD for deployment + +**Kind**: static method of [Interaction](#Interaction) +**Returns**: TYPE.MetadataTypeItem - metadata object + +| Param | Type | Description | +| --- | --- | --- | +| metadata | TYPE.MetadataTypeItem | of a single TSD | + ## List ⇐ [MetadataType](#MetadataType) @@ -3054,6 +3080,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.postDeployTasks(metadata, originalMetadata)](#MetadataType.postDeployTasks) ⇒ void * [.postRetrieveTasks(metadata, targetDir, [isTemplating])](#MetadataType.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.setFolderPath(metadata)](#MetadataType.setFolderPath) + * [.setFolderId(metadata)](#MetadataType.setFolderId) * [.retrieve(retrieveDir, [additionalFields], buObject, [subType], [key])](#MetadataType.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveChangelog([buObject], [additionalFields], [subType])](#MetadataType.retrieveChangelog) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache(buObject, [subType])](#MetadataType.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> @@ -3188,7 +3215,18 @@ generic script that retrieves the folder path from cache and updates the given m | Param | Type | Description | | --- | --- | --- | -| metadata | TYPE.MetadataTypeItem | a single script activity definition | +| metadata | TYPE.MetadataTypeItem | a single item | + + + +### MetadataType.setFolderId(metadata) +generic script that retrieves the folder path from cache and updates the given metadata with it after retrieve + +**Kind**: static method of [MetadataType](#MetadataType) + +| Param | Type | Description | +| --- | --- | --- | +| metadata | TYPE.MetadataTypeItem | a single item | diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index 305fd0c44..b9d885c80 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -1,3 +1,7 @@ +// overview: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/jb-api-specification.html +// obj definition: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/getting-started-spec.html +// insert: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/postCreateInteraction.html +// update: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/putUpdateInteraction.html module.exports = { bodyIteratorField: 'items', dependencies: [], @@ -61,7 +65,7 @@ module.exports = { template: null, }, definitionId: { - isCreateable: true, + isCreateable: false, isUpdateable: true, retrieving: true, template: true, @@ -109,7 +113,7 @@ module.exports = { template: true, }, key: { - isCreateable: true, + isCreateable: false, isUpdateable: true, retrieving: true, template: true, @@ -151,7 +155,7 @@ module.exports = { template: false, }, status: { - isCreateable: true, + isCreateable: false, isUpdateable: true, retrieving: true, template: true, From ee1c26d8820a6b3ab8df97940c2cba340b34f82b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 11:09:03 +0100 Subject: [PATCH 015/132] #627: added generic setFolderId method --- docs/dist/documentation.md | 26 ++++++++- lib/metadataTypes/Asset.js | 16 ++++-- lib/metadataTypes/Automation.js | 56 ++++++++++++-------- lib/metadataTypes/DataExtension.js | 4 +- lib/metadataTypes/EmailSendDefinition.js | 3 +- lib/metadataTypes/Interaction.js | 11 ++++ lib/metadataTypes/MetadataType.js | 19 ++++++- lib/metadataTypes/Query.js | 5 +- lib/metadataTypes/Script.js | 4 +- lib/metadataTypes/TriggeredSendDefinition.js | 3 +- 10 files changed, 107 insertions(+), 40 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 1ddae2f79..ce5f00942 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -842,6 +842,7 @@ FileTransfer MetadataType * [.buildTemplateForNested(templateDir, targetDir, metadata, templateVariables, templateName)](#Asset.buildTemplateForNested) ⇒ Promise.<void> * [._buildForNested(templateDir, targetDir, metadata, templateVariables, templateName, mode)](#Asset._buildForNested) ⇒ Promise.<void> * [.setFolderPath(metadata)](#Asset.setFolderPath) + * [.setFolderId(metadata)](#Asset.setFolderId) * [._mergeCode(metadata, deployDir, subType, [templateName], [fileListOnly])](#Asset._mergeCode) ⇒ Promise.<Array.<TYPE.CodeExtract>> * [._mergeCode_slots(prefix, metadataSlots, readDirArr, subtypeExtension, subDirArr, fileList, customerKey, [templateName], [fileListOnly])](#Asset._mergeCode_slots) ⇒ Promise.<void> * [._extractCode(metadata)](#Asset._extractCode) ⇒ TYPE.CodeExtractItem @@ -1088,6 +1089,17 @@ generic script that retrieves the folder path from cache and updates the given m | --- | --- | --- | | metadata | TYPE.MetadataTypeItem | a single script activity definition | + + +### Asset.setFolderId(metadata) +Asset-specific script that retrieves the folder ID from cache and updates the given metadata with it before deploy + +**Kind**: static method of [Asset](#Asset) + +| Param | Type | Description | +| --- | --- | --- | +| metadata | TYPE.MetadataTypeItem | a single item | + ### Asset.\_mergeCode(metadata, deployDir, subType, [templateName], [fileListOnly]) ⇒ Promise.<Array.<TYPE.CodeExtract>> @@ -1259,6 +1271,7 @@ Automation MetadataType * [.validateDeployMetadata(metadata)](#Automation.validateDeployMetadata) ⇒ boolean * [.postDeployTasks(metadata, originalMetadata)](#Automation.postDeployTasks) ⇒ Promise.<void> * [.setFolderPath(metadata)](#Automation.setFolderPath) + * [.setFolderId(metadata)](#Automation.setFolderId) * [.parseMetadata(metadata)](#Automation.parseMetadata) ⇒ TYPE.AutomationItem * [._buildSchedule(scheduleObject)](#Automation._buildSchedule) ⇒ TYPE.AutomationScheduleSoap * [._calcTime(offsetServer, dateInput, [offsetInput])](#Automation._calcTime) ⇒ string @@ -1409,6 +1422,17 @@ generic script that retrieves the folder path from cache and updates the given m | --- | --- | --- | | metadata | TYPE.MetadataTypeItem | a single script activity definition | + + +### Automation.setFolderId(metadata) +automation-specific script that retrieves the folder ID from cache and updates the given metadata with it before deploy + +**Kind**: static method of [Automation](#Automation) + +| Param | Type | Description | +| --- | --- | --- | +| metadata | TYPE.MetadataTypeItem | a single item | + ### Automation.parseMetadata(metadata) ⇒ TYPE.AutomationItem @@ -3220,7 +3244,7 @@ generic script that retrieves the folder path from cache and updates the given m ### MetadataType.setFolderId(metadata) -generic script that retrieves the folder path from cache and updates the given metadata with it after retrieve +generic script that retrieves the folder ID from cache and updates the given metadata with it before deploy **Kind**: static method of [MetadataType](#MetadataType) diff --git a/lib/metadataTypes/Asset.js b/lib/metadataTypes/Asset.js index 64d33f4fb..116ac0f5b 100644 --- a/lib/metadataTypes/Asset.js +++ b/lib/metadataTypes/Asset.js @@ -519,10 +519,7 @@ class Asset extends MetadataType { } // folder - metadata.category = { - id: cache.searchForField('folder', metadata.r__folder_Path, 'Path', 'ID'), - }; - delete metadata.r__folder_Path; + this.setFolderId(metadata); // restore asset type id which is needed for deploy metadata.assetType.id = this.definition.typeMapping[metadata.assetType.name]; @@ -790,6 +787,17 @@ class Asset extends MetadataType { ); } } + /** + * Asset-specific script that retrieves the folder ID from cache and updates the given metadata with it before deploy + * + * @param {TYPE.MetadataTypeItem} metadata a single item + */ + static setFolderId(metadata) { + metadata.category = { + id: cache.searchForField('folder', metadata.r__folder_Path, 'Path', 'ID'), + }; + delete metadata.r__folder_Path; + } /** * helper for {@link preDeployTasks} that loads extracted code content back into JSON diff --git a/lib/metadataTypes/Automation.js b/lib/metadataTypes/Automation.js index 33ff94020..453fede5b 100644 --- a/lib/metadataTypes/Automation.js +++ b/lib/metadataTypes/Automation.js @@ -245,28 +245,9 @@ class Automation extends MetadataType { */ static async preDeployTasks(metadata) { if (this.validateDeployMetadata(metadata)) { - try { - metadata.categoryId = cache.searchForField( - 'folder', - metadata.r__folder_Path, - 'Path', - 'ID' - ); - if (metadata.r__folder_Path !== 'my automations') { - Util.logger.warn( - ` - Automation '${ - metadata[this.definition.nameField] - }' is located in subfolder ${ - metadata.r__folder_Path - }. Please note that creating automation folders is not supported via API and hence you will have to create it manually in the GUI if you choose to deploy this automation.` - ); - } - delete metadata.r__folder_Path; - } catch { - throw new Error( - `Folder '${metadata.r__folder_Path}' was not found on the server. Please create this manually in the GUI. Automation-folders cannot be deployed automatically.` - ); - } + // folder + this.setFolderId(metadata); + if (metadata.type === 'scheduled' && metadata?.schedule?.startDate) { // Starting Source == 'Schedule' @@ -493,6 +474,36 @@ class Automation extends MetadataType { } } + /** + * automation-specific script that retrieves the folder ID from cache and updates the given metadata with it before deploy + * + * @param {TYPE.MetadataTypeItem} metadata a single item + */ + static setFolderId(metadata) { + try { + metadata.categoryId = cache.searchForField( + 'folder', + metadata.r__folder_Path, + 'Path', + 'ID' + ); + if (metadata.r__folder_Path !== 'my automations') { + Util.logger.warn( + ` - Automation '${ + metadata[this.definition.nameField] + }' is located in subfolder ${ + metadata.r__folder_Path + }. Please note that creating automation folders is not supported via API and hence you will have to create it manually in the GUI if you choose to deploy this automation.` + ); + } + delete metadata.r__folder_Path; + } catch { + throw new Error( + `Folder '${metadata.r__folder_Path}' was not found on the server. Please create this manually in the GUI. Automation-folders cannot be deployed automatically.` + ); + } + } + /** * parses retrieved Metadata before saving * @@ -500,6 +511,7 @@ class Automation extends MetadataType { * @returns {TYPE.AutomationItem} parsed item */ static parseMetadata(metadata) { + // folder this.setFolderPath(metadata); // automations are often skipped due to lack of support. try { diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index 1645db7f0..09324197e 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -533,8 +533,7 @@ class DataExtension extends MetadataType { */ static async preDeployTasks(metadata) { // folder - metadata.CategoryID = cache.searchForField('folder', metadata.r__folder_Path, 'Path', 'ID'); - delete metadata.r__folder_Path; + super.setFolderId(metadata); // DataExtensionTemplate if (metadata.r__dataExtensionTemplate_Name) { @@ -978,7 +977,6 @@ class DataExtension extends MetadataType { } } } - /** * parses retrieved Metadata before saving * diff --git a/lib/metadataTypes/EmailSendDefinition.js b/lib/metadataTypes/EmailSendDefinition.js index dec09e708..c8e567027 100644 --- a/lib/metadataTypes/EmailSendDefinition.js +++ b/lib/metadataTypes/EmailSendDefinition.js @@ -97,8 +97,7 @@ class EmailSendDefinition extends MetadataType { // re-add IsPlatformObject, required for visibility metadata.IsPlatformObject = false; // folder - metadata.CategoryID = cache.searchForField('folder', metadata.r__folder_Path, 'Path', 'ID'); - delete metadata.r__folder_Path; + super.setFolderId(metadata); // email metadata.Email = {}; if (metadata.r__email_Name) { diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index c79cd25dd..fc7d8fca3 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -74,6 +74,17 @@ class Interaction extends MetadataType { static create(metadata) { return super.createREST(metadata, '/interaction/v1/interactions/'); } + /** + * prepares a TSD for deployment + * + * @param {TYPE.MetadataTypeItem} metadata of a single TSD + * @returns {TYPE.MetadataTypeItem} metadata object + */ + static async preDeployTasks(metadata) { + // folder + super.setFolderId(metadata); + return metadata; + } } // Assign definition to static attributes diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index dab77c637..b9785195c 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -144,7 +144,7 @@ class MetadataType { /** * generic script that retrieves the folder path from cache and updates the given metadata with it after retrieve * - * @param {TYPE.MetadataTypeItem} metadata a single script activity definition + * @param {TYPE.MetadataTypeItem} metadata a single item */ static setFolderPath(metadata) { if (!this.definition.folderIdField) { @@ -166,6 +166,23 @@ class MetadataType { ); } } + /** + * generic script that retrieves the folder ID from cache and updates the given metadata with it before deploy + * + * @param {TYPE.MetadataTypeItem} metadata a single item + */ + static setFolderId(metadata) { + if (!this.definition.folderIdField) { + return; + } + metadata[this.definition.folderIdField] = cache.searchForField( + 'folder', + metadata.r__folder_Path, + 'Path', + 'ID' + ); + delete metadata.r__folder_Path; + } /** * Gets metadata from Marketing Cloud diff --git a/lib/metadataTypes/Query.js b/lib/metadataTypes/Query.js index d5b99cd47..a5f1eaba8 100644 --- a/lib/metadataTypes/Query.js +++ b/lib/metadataTypes/Query.js @@ -129,8 +129,9 @@ class Query extends MetadataType { 'CustomerKey', 'CustomerKey' ); - metadata.categoryId = cache.searchForField('folder', metadata.r__folder_Path, 'Path', 'ID'); - delete metadata.r__folder_Path; + // folder + super.setFolderId(metadata); + metadata.targetUpdateTypeId = this.definition.targetUpdateTypeMapping[metadata.targetUpdateTypeName]; return metadata; diff --git a/lib/metadataTypes/Script.js b/lib/metadataTypes/Script.js index c3839e16c..c509de7a6 100644 --- a/lib/metadataTypes/Script.js +++ b/lib/metadataTypes/Script.js @@ -4,7 +4,6 @@ const TYPE = require('../../types/mcdev.d'); const MetadataType = require('./MetadataType'); const Util = require('../util/util'); const File = require('../util/file'); -const cache = require('../util/cache'); /** * Script MetadataType @@ -128,8 +127,7 @@ class Script extends MetadataType { */ static async preDeployTasks(metadata, dir) { // folder - metadata.categoryId = cache.searchForField('folder', metadata.r__folder_Path, 'Path', 'ID'); - delete metadata.r__folder_Path; + super.setFolderId(metadata); // code metadata.script = await this._mergeCode(metadata, dir); diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index 2853c1608..afa1427d9 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -202,8 +202,7 @@ class TriggeredSendDefinition extends MetadataType { // re-add IsPlatformObject, required for visibility metadata.IsPlatformObject = false; // folder - metadata.CategoryID = cache.searchForField('folder', metadata.r__folder_Path, 'Path', 'ID'); - delete metadata.r__folder_Path; + super.setFolderId(metadata); // email if (metadata.r__email_Name) { // classic From 2ade4bb261ca9e639ac0928322d453dc25f6cf22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 11:11:58 +0100 Subject: [PATCH 016/132] #627: add folder id resolution on retrieve --- lib/metadataTypes/Interaction.js | 13 +++++++++++++ .../definitions/Interaction.definition.js | 9 ++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index fc7d8fca3..c34f35af3 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -74,6 +74,19 @@ class Interaction extends MetadataType { static create(metadata) { return super.createREST(metadata, '/interaction/v1/interactions/'); } + + /** + * manages post retrieve steps + * + * @param {TYPE.MetadataTypeItem} metadata a single query + * @returns {TYPE.MetadataTypeItem} Array with one metadata object and one query string + */ + static postRetrieveTasks(metadata) { + // folder + super.setFolderPath(metadata); + + return metadata; + } /** * prepares a TSD for deployment * diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index b9d885c80..7d2507c72 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -4,7 +4,8 @@ // update: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/putUpdateInteraction.html module.exports = { bodyIteratorField: 'items', - dependencies: [], + dependencies: ['folder'], // 'triggeredSendDefinition', + folderIdField: 'categoryId', hasExtended: false, idField: 'id', keyField: 'key', @@ -402,5 +403,11 @@ module.exports = { retrieving: true, template: true, }, + r__folder_Path: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, }, }; From 8dd17d93cff53894708ba9e49886b71ec818cd09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 11:28:06 +0100 Subject: [PATCH 017/132] #627: add missing fields --- .../definitions/Interaction.definition.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index 7d2507c72..f04e9d721 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -122,7 +122,7 @@ module.exports = { lastPublishedDate: { isCreateable: false, isUpdateable: false, - retrieving: false, + retrieving: true, template: false, }, 'metaData.templateId': { @@ -403,6 +403,15 @@ module.exports = { retrieving: true, template: true, }, + metaData: { + skipValidation: true, + }, + notifiers: { + skipValidation: true, + }, + tags: { + skipValidation: true, + }, r__folder_Path: { isCreateable: false, isUpdateable: false, From 0683a0fd16e6a6d14e6f9ea947f4e8df34bfff84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 12:03:02 +0100 Subject: [PATCH 018/132] #627: add check for eventDefinition --- lib/metadataTypes/Interaction.js | 32 +++++++++++++++++++ .../definitions/Interaction.definition.js | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index c34f35af3..631e0682c 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -2,6 +2,8 @@ const TYPE = require('../../types/mcdev.d'); const MetadataType = require('./MetadataType'); +const Util = require('../util/util'); +const cache = require('../util/cache'); /** * Script MetadataType @@ -85,6 +87,24 @@ class Interaction extends MetadataType { // folder super.setFolderPath(metadata); + // eventDefinition + if (metadata.triggers?.length > 0 && metadata.triggers[0].metaData?.eventDefinitionKey) { + // trigger found; there can only be one entry in this array + try { + cache.searchForField( + 'eventDefinition', + metadata.triggers[0].metaData?.eventDefinitionKey, + 'eventDefinitionKey', + 'eventDefinitionKey' + ); + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + } return metadata; } /** @@ -96,6 +116,18 @@ class Interaction extends MetadataType { static async preDeployTasks(metadata) { // folder super.setFolderId(metadata); + + // eventDefinition + if (metadata.triggers?.length > 0 && metadata.triggers[0].metaData?.eventDefinitionKey) { + // trigger found; there can only be one entry in this array + cache.searchForField( + 'eventDefinition', + metadata.triggers[0].metaData?.eventDefinitionKey, + 'eventDefinitionKey', + 'eventDefinitionKey' + ); + } + return metadata; } } diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index f04e9d721..43b1d80d8 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -4,7 +4,7 @@ // update: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/putUpdateInteraction.html module.exports = { bodyIteratorField: 'items', - dependencies: ['folder'], // 'triggeredSendDefinition', + dependencies: ['folder', 'eventDefinition'], // 'triggeredSendDefinition', folderIdField: 'categoryId', hasExtended: false, idField: 'id', From babf3c3a3ee2ed63f14fd829f64cc07874ffc887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 12:33:09 +0100 Subject: [PATCH 019/132] #627: add DELETE by ID --- lib/metadataTypes/Interaction.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 631e0682c..bf8b91d70 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -50,9 +50,18 @@ class Interaction extends MetadataType { * @returns {Promise.} deletion success status */ static deleteByKey(buObject, key) { + let singleKey = ''; + /* eslint-disable unicorn/prefer-ternary */ + if (key.startsWith('id:')) { + // ! allow selecting journeys by ID because that's what users see in the URL + singleKey = key.slice(3); + } else { + singleKey = 'key:' + encodeURIComponent(key); + } + /* eslint-enable unicorn/prefer-ternary */ return super.deleteByKeyREST( buObject, - '/interaction/v1/interactions/key:' + key, + '/interaction/v1/interactions/' + singleKey, key, false ); From 5b61154f5a205c3d38c6f5e8804d26018a58bf6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 13:02:26 +0100 Subject: [PATCH 020/132] #627: encoding not needed --- lib/metadataTypes/Interaction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index bf8b91d70..eae9d0527 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -28,7 +28,7 @@ class Interaction extends MetadataType { /* eslint-disable unicorn/prefer-ternary */ if (key.startsWith('id:')) { // ! allow selecting journeys by ID because that's what users see in the URL - singleKey = '/' + encodeURIComponent(key.slice(3)); + singleKey = '/' + key.slice(3); } else { singleKey = '/key:' + encodeURIComponent(key); } From 94e4ef2c67865cdb9156a584e8beb6947ec1e91e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 13:04:27 +0100 Subject: [PATCH 021/132] #627: key is required for CREATE as per API response --- lib/metadataTypes/definitions/Interaction.definition.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index 43b1d80d8..54b248830 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -114,7 +114,7 @@ module.exports = { template: true, }, key: { - isCreateable: false, + isCreateable: true, isUpdateable: true, retrieving: true, template: true, From e4dede5a3474a84e7867915d083c5d20b9509d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 14:23:59 +0100 Subject: [PATCH 022/132] #627: add req trigger fields for update/create --- docs/dist/documentation.md | 14 ++++++++++++++ .../definitions/Interaction.definition.js | 16 ++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index ce5f00942..6b260d7a6 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -2344,6 +2344,7 @@ EventDefinition MetadataType * [.retrieveForCache()](#EventDefinition.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveAsTemplate(templateDir, name, templateVariables)](#EventDefinition.retrieveAsTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.postRetrieveTasks(eventDef)](#EventDefinition.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem + * [.deleteByKey(buObject, key)](#EventDefinition.deleteByKey) ⇒ Promise.<boolean> * [.create(EventDefinition)](#EventDefinition.create) ⇒ Promise * [.update(metadataEntry)](#EventDefinition.update) ⇒ Promise * [.preDeployTasks(metadata)](#EventDefinition.preDeployTasks) ⇒ TYPE.MetadataTypeItem @@ -2400,6 +2401,19 @@ manages post retrieve steps | --- | --- | --- | | eventDef | TYPE.MetadataTypeItem | a single item of Event Definition | + + +### EventDefinition.deleteByKey(buObject, key) ⇒ Promise.<boolean> +Delete a metadata item from the specified business unit + +**Kind**: static method of [EventDefinition](#EventDefinition) +**Returns**: Promise.<boolean> - deletion success status + +| Param | Type | Description | +| --- | --- | --- | +| buObject | TYPE.BuObject | references credentials | +| key | string | Identifier of item | + ### EventDefinition.create(EventDefinition) ⇒ Promise diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index 54b248830..0953e9844 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -174,16 +174,16 @@ module.exports = { template: false, }, 'triggers[].key': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'triggers[].name': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'triggers[].description': { isCreateable: true, From 8d5fbf816136f53ec24e13c822ec91f786db6060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 14:28:15 +0100 Subject: [PATCH 023/132] #611: add DELETE support for eventDefinition --- lib/metadataTypes/EventDefinition.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/metadataTypes/EventDefinition.js b/lib/metadataTypes/EventDefinition.js index dd1cdd7dd..80d991970 100644 --- a/lib/metadataTypes/EventDefinition.js +++ b/lib/metadataTypes/EventDefinition.js @@ -116,6 +116,21 @@ class EventDefinition extends MetadataType { this.keepRetrieveFields(val); return val; } + /** + * Delete a metadata item from the specified business unit + * + * @param {TYPE.BuObject} buObject references credentials + * @param {string} key Identifier of item + * @returns {Promise.} deletion success status + */ + static deleteByKey(buObject, key) { + return super.deleteByKeyREST( + buObject, + '/interaction/v1/eventDefinitions/key:' + encodeURIComponent(key), + key, + false + ); + } /** * Creates a single Event Definition From 01f1834615196d83551b79068fe2f431d1436028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 14:53:47 +0100 Subject: [PATCH 024/132] #627: delete specific journey version deletes all versions if not provided! --- docs/dist/documentation.md | 17 ++++++++++------- lib/cli.js | 8 ++++++-- lib/index.js | 7 ++++--- lib/metadataTypes/Interaction.js | 7 +++++-- lib/metadataTypes/MetadataType.js | 3 ++- 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 6b260d7a6..f400585f2 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -472,7 +472,7 @@ main class * [.initProject([credentialsName])](#Mcdev.initProject) ⇒ Promise.<void> * [.findBUs(credentialsName)](#Mcdev.findBUs) ⇒ Promise.<void> * [.document(businessUnit, type)](#Mcdev.document) ⇒ Promise.<void> - * [.deleteByKey(businessUnit, type, customerKey)](#Mcdev.deleteByKey) ⇒ Promise.<void> + * [.deleteByKey(businessUnit, type, customerKey, [version])](#Mcdev.deleteByKey) ⇒ Promise.<void> * [.badKeys(businessUnit)](#Mcdev.badKeys) ⇒ Promise.<void> * [.retrieveAsTemplate(businessUnit, selectedType, name, market)](#Mcdev.retrieveAsTemplate) ⇒ Promise.<TYPE.MultiMetadataTypeList> * [.buildTemplate(businessUnit, selectedType, keyArr, market)](#Mcdev.buildTemplate) ⇒ Promise.<TYPE.MultiMetadataTypeList> @@ -603,7 +603,7 @@ Creates docs for supported metadata types in Markdown and/or HTML format -### Mcdev.deleteByKey(businessUnit, type, customerKey) ⇒ Promise.<void> +### Mcdev.deleteByKey(businessUnit, type, customerKey, [version]) ⇒ Promise.<void> Creates docs for supported metadata types in Markdown and/or HTML format **Kind**: static method of [Mcdev](#Mcdev) @@ -613,7 +613,8 @@ Creates docs for supported metadata types in Markdown and/or HTML format | --- | --- | --- | | businessUnit | string | references credentials from properties.json | | type | string | supported metadata type | -| customerKey | string | Identifier of data extension | +| customerKey | string | Identifier of metadata | +| [version] | number | optional version of metadata | @@ -2920,7 +2921,7 @@ Script MetadataType * [Interaction](#Interaction) ⇐ [MetadataType](#MetadataType) * [.retrieve(retrieveDir, [_], [__], [___], [key])](#Interaction.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [.deleteByKey(buObject, key)](#Interaction.deleteByKey) ⇒ Promise.<boolean> + * [.deleteByKey(buObject, key, [version])](#Interaction.deleteByKey) ⇒ Promise.<boolean> * [.update(metadata)](#Interaction.update) ⇒ Promise * [.create(metadata)](#Interaction.create) ⇒ Promise * [.postRetrieveTasks(metadata)](#Interaction.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem @@ -2945,7 +2946,7 @@ Endpoint /interaction/v1/interactions?extras=all&pageSize=50000 return 50000 Scr -### Interaction.deleteByKey(buObject, key) ⇒ Promise.<boolean> +### Interaction.deleteByKey(buObject, key, [version]) ⇒ Promise.<boolean> Delete a metadata item from the specified business unit **Kind**: static method of [Interaction](#Interaction) @@ -2955,6 +2956,7 @@ Delete a metadata item from the specified business unit | --- | --- | --- | | buObject | TYPE.BuObject | references credentials | | key | string | Identifier of item | +| [version] | number | optional version of metadata | @@ -3155,7 +3157,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.buildDefinition(templateDir, targetDir, templateName, variables)](#MetadataType.buildDefinition) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.checkForErrors(ex)](#MetadataType.checkForErrors) ⇒ Array.<string> * [.document([buObject], [metadata], [isDeploy])](#MetadataType.document) ⇒ void - * [.deleteByKey(buObject, customerKey)](#MetadataType.deleteByKey) ⇒ boolean + * [.deleteByKey(buObject, customerKey, [version])](#MetadataType.deleteByKey) ⇒ boolean * [.postDeleteTasks(buObject, customerKey)](#MetadataType.postDeleteTasks) ⇒ void * [.deleteByKeySOAP(buObject, customerKey, [handleOutside])](#MetadataType.deleteByKeySOAP) ⇒ boolean * [.deleteByKeyREST(buObject, url, key, [handleOutside])](#MetadataType.deleteByKeyREST) ⇒ boolean @@ -3770,7 +3772,7 @@ Gets metadata cache with limited fields and does not store value to disk -### MetadataType.deleteByKey(buObject, customerKey) ⇒ boolean +### MetadataType.deleteByKey(buObject, customerKey, [version]) ⇒ boolean Delete a metadata item from the specified business unit **Kind**: static method of [MetadataType](#MetadataType) @@ -3780,6 +3782,7 @@ Delete a metadata item from the specified business unit | --- | --- | --- | | buObject | TYPE.BuObject | references credentials | | customerKey | string | Identifier of data extension | +| [version] | number | optional version of metadata | diff --git a/lib/cli.js b/lib/cli.js index 2c6fcc474..7c4e07bc5 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -139,7 +139,7 @@ yargs }, }) .command({ - command: 'delete ', + command: 'delete [version]', aliases: ['del'], desc: 'deletes metadata of selected type and external key', builder: (yargs) => { @@ -156,12 +156,16 @@ yargs .positional('EXTERNALKEY', { type: 'string', describe: 'the key to delete', + }) + .positional('VERSION', { + type: 'string', + describe: 'some types have versions (e.g. interaction)', }); }, handler: (argv) => { Mcdev.setSkipInteraction(argv.skipInteraction); Mcdev.setLoggingLevel(argv); - Mcdev.deleteByKey(argv.BU, argv.TYPE, argv.EXTERNALKEY); + Mcdev.deleteByKey(argv.BU, argv.TYPE, argv.EXTERNALKEY, argv.VERSION); }, }) .command({ diff --git a/lib/index.js b/lib/index.js index ee98a608a..55f711e6e 100644 --- a/lib/index.js +++ b/lib/index.js @@ -354,10 +354,11 @@ class Mcdev { * * @param {string} businessUnit references credentials from properties.json * @param {string} type supported metadata type - * @param {string} customerKey Identifier of data extension + * @param {string} customerKey Identifier of metadata + * @param {number} [version] optional version of metadata * @returns {Promise.} - */ - static async deleteByKey(businessUnit, type, customerKey) { + static async deleteByKey(businessUnit, type, customerKey, version) { Util.logger.info('mcdev:: delete'); const properties = await config.getProperties(); if (!(await config.checkProperties(properties))) { @@ -377,7 +378,7 @@ class Mcdev { } try { MetadataTypeInfo[type].properties = properties; - MetadataTypeInfo[type].deleteByKey(buObject, customerKey); + MetadataTypeInfo[type].deleteByKey(buObject, customerKey, version); } catch (ex) { Util.logger.error('mcdev.delete ' + ex.message); } diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index eae9d0527..cbc88235b 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -47,9 +47,10 @@ class Interaction extends MetadataType { * * @param {TYPE.BuObject} buObject references credentials * @param {string} key Identifier of item + * @param {number} [version] optional version of metadata * @returns {Promise.} deletion success status */ - static deleteByKey(buObject, key) { + static deleteByKey(buObject, key, version) { let singleKey = ''; /* eslint-disable unicorn/prefer-ternary */ if (key.startsWith('id:')) { @@ -61,7 +62,9 @@ class Interaction extends MetadataType { /* eslint-enable unicorn/prefer-ternary */ return super.deleteByKeyREST( buObject, - '/interaction/v1/interactions/' + singleKey, + '/interaction/v1/interactions/' + + singleKey + + (version ? `?versionNumber=${version}` : ''), key, false ); diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index b9785195c..250b00ae3 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -1554,9 +1554,10 @@ class MetadataType { * * @param {TYPE.BuObject} buObject references credentials * @param {string} customerKey Identifier of data extension + * @param {number} [version] optional version of metadata * @returns {boolean} deletion success status */ - static deleteByKey(buObject, customerKey) { + static deleteByKey(buObject, customerKey, version) { Util.logger.error(`Deletion is not yet supported for ${this.definition.typeName}!`); return false; } From 008a6fd3cff91453f8308c69eee952c28c5c9c44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 16:53:21 +0100 Subject: [PATCH 025/132] #627: allow auto-creating new draft if none exists --- docs/dist/documentation.md | 40 +++++- lib/metadataTypes/Interaction.js | 78 ++++++++++++ lib/metadataTypes/MetadataType.js | 116 ++++++++++-------- .../definitions/Interaction.definition.js | 4 +- types/mcdev.d.js | 1 + 5 files changed, 181 insertions(+), 58 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index f400585f2..dbd3d87cb 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -195,7 +195,7 @@ Provides default functionality that can be overwritten by child metadata type cl
TypeKeyCombo : Object.<string, string>

object-key=metadata type, value=array of external keys

-
Cache : Object.<string, any>
+
MetadataTypeItemDiff : Object.<string, any>

key=customer key

CodeExtractItem : object
@@ -2921,11 +2921,12 @@ Script MetadataType * [Interaction](#Interaction) ⇐ [MetadataType](#MetadataType) * [.retrieve(retrieveDir, [_], [__], [___], [key])](#Interaction.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [.deleteByKey(buObject, key, [version])](#Interaction.deleteByKey) ⇒ Promise.<boolean> + * [.deleteByKey(buObject, key, version)](#Interaction.deleteByKey) ⇒ Promise.<boolean> * [.update(metadata)](#Interaction.update) ⇒ Promise * [.create(metadata)](#Interaction.create) ⇒ Promise * [.postRetrieveTasks(metadata)](#Interaction.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.preDeployTasks(metadata)](#Interaction.preDeployTasks) ⇒ TYPE.MetadataTypeItem + * [.createOrUpdate(metadata, metadataKey, hasError, metadataToUpdate, metadataToCreate)](#Interaction.createOrUpdate) @@ -2946,7 +2947,7 @@ Endpoint /interaction/v1/interactions?extras=all&pageSize=50000 return 50000 Scr -### Interaction.deleteByKey(buObject, key, [version]) ⇒ Promise.<boolean> +### Interaction.deleteByKey(buObject, key, version) ⇒ Promise.<boolean> Delete a metadata item from the specified business unit **Kind**: static method of [Interaction](#Interaction) @@ -2956,7 +2957,7 @@ Delete a metadata item from the specified business unit | --- | --- | --- | | buObject | TYPE.BuObject | references credentials | | key | string | Identifier of item | -| [version] | number | optional version of metadata | +| version | number | required version of metadata | @@ -3006,6 +3007,19 @@ prepares a TSD for deployment | --- | --- | --- | | metadata | TYPE.MetadataTypeItem | of a single TSD | + + +### Interaction.createOrUpdate(metadata, metadataKey, hasError, metadataToUpdate, metadataToCreate) +**Kind**: static method of [Interaction](#Interaction) + +| Param | Type | Description | +| --- | --- | --- | +| metadata | TYPE.MetadataTypeItem | single metadata itme | +| metadataKey | string | key of item we are looking at | +| hasError | boolean | error flag from previous code | +| metadataToUpdate | Array.<TYPE.MetadataTypeItemDiff> | list of items to update | +| metadataToCreate | Array.<TYPE.MetadataTypeItem> | list of items to create | + ## List ⇐ [MetadataType](#MetadataType) @@ -3132,6 +3146,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.hasChanged(cachedVersion, metadata, [fieldName])](#MetadataType.hasChanged) ⇒ boolean * [.hasChangedGeneric(cachedVersion, metadata, [fieldName], [silent])](#MetadataType.hasChangedGeneric) ⇒ boolean * [.upsert(metadata, deployDir, [buObject])](#MetadataType.upsert) ⇒ Promise.<TYPE.MetadataTypeMap> + * [.createOrUpdate(metadata, metadataKey, hasError, metadataToUpdate, metadataToCreate)](#MetadataType.createOrUpdate) ⇒ void * [.createREST(metadataEntry, uri)](#MetadataType.createREST) ⇒ Promise * [.createSOAP(metadataEntry, [overrideType], [handleOutside])](#MetadataType.createSOAP) ⇒ Promise * [.updateREST(metadataEntry, uri, [usePut])](#MetadataType.updateREST) ⇒ Promise @@ -3422,6 +3437,19 @@ MetadataType upsert, after retrieving from target and comparing to check if crea | deployDir | string | directory where deploy metadata are saved | | [buObject] | TYPE.BuObject | properties for auth | + + +### MetadataType.createOrUpdate(metadata, metadataKey, hasError, metadataToUpdate, metadataToCreate) ⇒ void +**Kind**: static method of [MetadataType](#MetadataType) + +| Param | Type | Description | +| --- | --- | --- | +| metadata | TYPE.MetadataTypeItem | single metadata itme | +| metadataKey | string | key of item we are looking at | +| hasError | boolean | error flag from previous code | +| metadataToUpdate | Array.<TYPE.MetadataTypeItemDiff> | list of items to update | +| metadataToCreate | Array.<TYPE.MetadataTypeItem> | list of items to create | + ### MetadataType.createREST(metadataEntry, uri) ⇒ Promise @@ -7016,9 +7044,9 @@ initiate winston logger object-key=metadata type, value=array of external keys **Kind**: global typedef - + -## Cache : Object.<string, any> +## MetadataTypeItemDiff : Object.<string, any> key=customer key **Kind**: global typedef diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index cbc88235b..bf1ab1856 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -4,6 +4,7 @@ const TYPE = require('../../types/mcdev.d'); const MetadataType = require('./MetadataType'); const Util = require('../util/util'); const cache = require('../util/cache'); +const File = require('../util/file'); /** * Script MetadataType @@ -126,6 +127,10 @@ class Interaction extends MetadataType { * @returns {TYPE.MetadataTypeItem} metadata object */ static async preDeployTasks(metadata) { + if (metadata.status !== 'Draft') { + metadata.status !== 'Draft'; + } + // folder super.setFolderId(metadata); @@ -142,6 +147,79 @@ class Interaction extends MetadataType { return metadata; } + + /** + * + * @param {TYPE.MetadataTypeItem} metadata single metadata itme + * @param {string} metadataKey key of item we are looking at + * @param {boolean} hasError error flag from previous code + * @param {TYPE.MetadataTypeItemDiff[]} metadataToUpdate list of items to update + * @param {TYPE.MetadataTypeItem[]} metadataToCreate list of items to create + */ + static createOrUpdate(metadata, metadataKey, hasError, metadataToUpdate, metadataToCreate) { + const normalizedKey = File.reverseFilterIllegalFilenames( + metadata[metadataKey][this.definition.keyField] + ); + // Update if it already exists; Create it if not + if (Util.logger.level === 'debug' && metadata[metadataKey][this.definition.idField]) { + // TODO: re-evaluate in future releases if & when we managed to solve folder dependencies once and for all + // only used if resource is excluded from cache and we still want to update it + // needed e.g. to rewire lost folders + Util.logger.warn( + ' - Hotfix for non-cachable resource found in deploy folder. Trying update:' + ); + Util.logger.warn(JSON.stringify(metadata[metadataKey])); + if (hasError) { + metadataToUpdate.push(null); + } else { + metadataToUpdate.push({ + before: {}, + after: metadata[metadataKey], + }); + } + } else { + const cachedVersion = cache.getByKey(this.definition.type, normalizedKey); + if (cachedVersion && cachedVersion.status === 'Draft') { + // normal way of processing update files + if (!this.hasChanged(cachedVersion, metadata[metadataKey])) { + hasError = true; + } + + if (hasError) { + // do this in case something went wrong during pre-deploy steps to ensure the total counter is correct + metadataToUpdate.push(null); + } else { + // add ObjectId to allow actual update + metadata[metadataKey][this.definition.idField] = + cachedVersion[this.definition.idField]; + + metadataToUpdate.push({ + before: cachedVersion, + after: metadata[metadataKey], + }); + } + } else { + if (hasError) { + // do this in case something went wrong during pre-deploy steps to ensure the total counter is correct + metadataToCreate.push(null); + } else { + if (cachedVersion) { + Util.logger.info( + ` - Found ${this.definition.type} ${ + metadata[metadataKey][this.definition.nameField] + } (${ + metadata[metadataKey][this.definition.keyField] + }) on BU, but it is not in Draft status. Will create new version ${ + cachedVersion.version + 1 + }.` + ); + } + + metadataToCreate.push(metadata[metadataKey]); + } + } + } + } } // Assign definition to static attributes diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 250b00ae3..4ed9e420c 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -462,57 +462,13 @@ class MetadataType { if (deployableMetadata) { metadata[metadataKey] = deployableMetadata; // create normalizedKey off of whats in the json rather than from "metadataKey" because preDeployTasks might have altered something (type asset) - const normalizedKey = File.reverseFilterIllegalFilenames( - deployableMetadata[this.definition.keyField] + this.createOrUpdate( + metadata, + metadataKey, + hasError, + metadataToUpdate, + metadataToCreate ); - // Update if it already exists; Create it if not - if ( - Util.logger.level === 'debug' && - metadata[metadataKey][this.definition.idField] - ) { - // TODO: re-evaluate in future releases if & when we managed to solve folder dependencies once and for all - // only used if resource is excluded from cache and we still want to update it - // needed e.g. to rewire lost folders - Util.logger.warn( - ' - Hotfix for non-cachable resource found in deploy folder. Trying update:' - ); - Util.logger.warn(JSON.stringify(metadata[metadataKey])); - if (hasError) { - metadataToUpdate.push(null); - } else { - metadataToUpdate.push({ - before: {}, - after: metadata[metadataKey], - }); - } - } else if (cache.getByKey(this.definition.type, normalizedKey)) { - // normal way of processing update files - const cachedVersion = cache.getByKey(this.definition.type, normalizedKey); - if (!this.hasChanged(cachedVersion, metadata[metadataKey])) { - hasError = true; - } - - if (hasError) { - // do this in case something went wrong during pre-deploy steps to ensure the total counter is correct - metadataToUpdate.push(null); - } else { - // add ObjectId to allow actual update - metadata[metadataKey][this.definition.idField] = - cachedVersion[this.definition.idField]; - - metadataToUpdate.push({ - before: cache.getByKey(this.definition.type, normalizedKey), - after: metadata[metadataKey], - }); - } - } else { - if (hasError) { - // do this in case something went wrong during pre-deploy steps to ensure the total counter is correct - metadataToCreate.push(null); - } else { - metadataToCreate.push(metadata[metadataKey]); - } - } } else { filteredByPreDeploy++; } @@ -571,6 +527,66 @@ class MetadataType { } } + /** + * + * @param {TYPE.MetadataTypeItem} metadata single metadata itme + * @param {string} metadataKey key of item we are looking at + * @param {boolean} hasError error flag from previous code + * @param {TYPE.MetadataTypeItemDiff[]} metadataToUpdate list of items to update + * @param {TYPE.MetadataTypeItem[]} metadataToCreate list of items to create + * @returns {void} + */ + static createOrUpdate(metadata, metadataKey, hasError, metadataToUpdate, metadataToCreate) { + const normalizedKey = File.reverseFilterIllegalFilenames( + metadata[metadataKey][this.definition.keyField] + ); + // Update if it already exists; Create it if not + if (Util.logger.level === 'debug' && metadata[metadataKey][this.definition.idField]) { + // TODO: re-evaluate in future releases if & when we managed to solve folder dependencies once and for all + // only used if resource is excluded from cache and we still want to update it + // needed e.g. to rewire lost folders + Util.logger.warn( + ' - Hotfix for non-cachable resource found in deploy folder. Trying update:' + ); + Util.logger.warn(JSON.stringify(metadata[metadataKey])); + if (hasError) { + metadataToUpdate.push(null); + } else { + metadataToUpdate.push({ + before: {}, + after: metadata[metadataKey], + }); + } + } else if (cache.getByKey(this.definition.type, normalizedKey)) { + // normal way of processing update files + const cachedVersion = cache.getByKey(this.definition.type, normalizedKey); + if (!this.hasChanged(cachedVersion, metadata[metadataKey])) { + hasError = true; + } + + if (hasError) { + // do this in case something went wrong during pre-deploy steps to ensure the total counter is correct + metadataToUpdate.push(null); + } else { + // add ObjectId to allow actual update + metadata[metadataKey][this.definition.idField] = + cachedVersion[this.definition.idField]; + + metadataToUpdate.push({ + before: cache.getByKey(this.definition.type, normalizedKey), + after: metadata[metadataKey], + }); + } + } else { + if (hasError) { + // do this in case something went wrong during pre-deploy steps to ensure the total counter is correct + metadataToCreate.push(null); + } else { + metadataToCreate.push(metadata[metadataKey]); + } + } + } + /** * Creates a single metadata entry via REST * diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index 0953e9844..fdbd5a60e 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -393,9 +393,9 @@ module.exports = { }, version: { isCreateable: false, - isUpdateable: true, + isUpdateable: false, retrieving: true, - template: true, + template: false, }, workflowApiVersion: { isCreateable: true, diff --git a/types/mcdev.d.js b/types/mcdev.d.js index 4122dfbcf..2bda803a2 100644 --- a/types/mcdev.d.js +++ b/types/mcdev.d.js @@ -24,6 +24,7 @@ const SDK = require('sfmc-sdk'); * @typedef {{metadata:MetadataTypeMap,type:SupportedMetadataTypes}} MetadataTypeMapObj * @typedef {{metadata:MetadataTypeItem,type:SupportedMetadataTypes}} MetadataTypeItemObj * @typedef {Object.} Cache key=MID + * @typedef {{before: TYPE.MetadataTypeItem, after: TYPE.MetadataTypeItem}} MetadataTypeItemDiff used during update */ /** From e92457b4be08e07625a4a4eb75c891637e1ff42e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 17:07:41 +0100 Subject: [PATCH 026/132] #627: limit DELETE for interaction to require version avoids accidental deletion of entire journey with all its versions --- lib/cli.js | 2 +- lib/index.js | 4 ++-- lib/metadataTypes/Interaction.js | 15 ++++++++++----- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/cli.js b/lib/cli.js index 7c4e07bc5..b9ffff3d0 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -139,7 +139,7 @@ yargs }, }) .command({ - command: 'delete [version]', + command: 'delete [VERSION]', aliases: ['del'], desc: 'deletes metadata of selected type and external key', builder: (yargs) => { diff --git a/lib/index.js b/lib/index.js index 55f711e6e..2c7f5b6c0 100644 --- a/lib/index.js +++ b/lib/index.js @@ -378,9 +378,9 @@ class Mcdev { } try { MetadataTypeInfo[type].properties = properties; - MetadataTypeInfo[type].deleteByKey(buObject, customerKey, version); + await MetadataTypeInfo[type].deleteByKey(buObject, customerKey, version); } catch (ex) { - Util.logger.error('mcdev.delete ' + ex.message); + Util.logger.errorStack(ex, ` - Deleting ${type} failed`); } } } diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index bf1ab1856..1849f9c42 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -48,24 +48,29 @@ class Interaction extends MetadataType { * * @param {TYPE.BuObject} buObject references credentials * @param {string} key Identifier of item - * @param {number} [version] optional version of metadata + * @param {number} version required version of metadata * @returns {Promise.} deletion success status */ static deleteByKey(buObject, key, version) { + if (Number.isNaN(version)) { + throw new TypeError( + 'Version is required for deleting interactions to avoid accidental deletion of the wrong item.' + ); + } let singleKey = ''; /* eslint-disable unicorn/prefer-ternary */ if (key.startsWith('id:')) { // ! allow selecting journeys by ID because that's what users see in the URL singleKey = key.slice(3); } else { - singleKey = 'key:' + encodeURIComponent(key); + throw new Error( + 'Journey versions can only be deleted with their ID, not with their Key.' + ); } /* eslint-enable unicorn/prefer-ternary */ return super.deleteByKeyREST( buObject, - '/interaction/v1/interactions/' + - singleKey + - (version ? `?versionNumber=${version}` : ''), + '/interaction/v1/interactions/' + singleKey + `?versionNumber=${version}`, key, false ); From edfd6cdf4934b0607b95a2935b470c13b999da26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 21:47:00 +0100 Subject: [PATCH 027/132] #627: 'version' req for update to avoid 'Interaction not found'-error --- lib/metadataTypes/definitions/Interaction.definition.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index fdbd5a60e..0953e9844 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -393,9 +393,9 @@ module.exports = { }, version: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, workflowApiVersion: { isCreateable: true, From 614f5976265f6397e194ec7b83d7287c33438e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 21:53:21 +0100 Subject: [PATCH 028/132] #627: version auto-set to last server-version for update to avoid issues could otherwise become an issue during deployments, especially across BUs --- lib/metadataTypes/Interaction.js | 2 ++ lib/metadataTypes/definitions/Interaction.definition.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 1849f9c42..d600cc330 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -197,6 +197,8 @@ class Interaction extends MetadataType { // add ObjectId to allow actual update metadata[metadataKey][this.definition.idField] = cachedVersion[this.definition.idField]; + // add ObjectId to allow actual update + metadata[metadataKey].version = cachedVersion.version; metadataToUpdate.push({ before: cachedVersion, diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index 0953e9844..ff62e16be 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -159,7 +159,7 @@ module.exports = { isCreateable: false, isUpdateable: true, retrieving: true, - template: true, + template: false, }, triggers: { isCreateable: true, From ff88f76d8a5c94a8ee2c53adb78d700cd3da8f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 21:55:11 +0100 Subject: [PATCH 029/132] #627: dont show assumed new version because deleted versions will not be re-assigned on create --- lib/metadataTypes/Interaction.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index d600cc330..66c1cedf9 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -216,9 +216,7 @@ class Interaction extends MetadataType { metadata[metadataKey][this.definition.nameField] } (${ metadata[metadataKey][this.definition.keyField] - }) on BU, but it is not in Draft status. Will create new version ${ - cachedVersion.version + 1 - }.` + }) on BU, but it is not in Draft status. Will create new version.` ); } From 0f88a94a2e13a290b32f6305defd7531081273cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 21:57:30 +0100 Subject: [PATCH 030/132] #627: handle errors during async delete op --- lib/metadataTypes/MetadataType.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 4ed9e420c..dc1093af4 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -1647,7 +1647,7 @@ class MetadataType { const keyObj = {}; keyObj[this.definition.keyField] = key; try { - this.client.rest.delete(url); + await this.client.rest.delete(url); if (!handleOutside) { Util.logger.info(`- deleted ${this.definition.type}: ${key}`); } @@ -1658,10 +1658,7 @@ class MetadataType { if (handleOutside) { throw ex; } else { - const errorMsg = ex?.results?.length - ? `${ex.results[0].StatusMessage} (Code ${ex.results[0].ErrorCode})` - : ex.message; - Util.logger.error(`- error deleting ${this.definition.type} '${key}': ${errorMsg}`); + Util.logger.errorStack(ex, ` - Deleting ${this.definition.type} '${key}' failed`); } return false; From 9b0c1a42aebde47aaf4159b6af854ef4858b031c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 22:15:52 +0100 Subject: [PATCH 031/132] #627: fix & warning for delete interaction --- lib/metadataTypes/Interaction.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 66c1cedf9..c797f2c3a 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -51,7 +51,7 @@ class Interaction extends MetadataType { * @param {number} version required version of metadata * @returns {Promise.} deletion success status */ - static deleteByKey(buObject, key, version) { + static async deleteByKey(buObject, key, version) { if (Number.isNaN(version)) { throw new TypeError( 'Version is required for deleting interactions to avoid accidental deletion of the wrong item.' @@ -63,10 +63,17 @@ class Interaction extends MetadataType { // ! allow selecting journeys by ID because that's what users see in the URL singleKey = key.slice(3); } else { - throw new Error( - 'Journey versions can only be deleted with their ID, not with their Key.' + // delete by key with specified version does not work, therefore we need to get the ID first + const response = await this.client.rest.get( + `/interaction/v1/interactions/key:${key}?extras=` ); + const results = this.parseResponseBody(response, key); + singleKey = results[key].id; + Util.logger.debug(`Deleting interaction ${key} via its ID ${singleKey}`); } + Util.logger.warn( + `Deleting Interactions via this command breaks following retrieve-by-key/id requests until you've deployed/created a new draft version! You can get still get the latest available version of your journey by retrieving all interactions on this BU.` + ); /* eslint-enable unicorn/prefer-ternary */ return super.deleteByKeyREST( buObject, From b077f80b3060bbc21eaa6f8be822f2da381012ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 22:38:38 +0100 Subject: [PATCH 032/132] #627: speed up caching --- lib/metadataTypes/Interaction.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index c797f2c3a..79dd362f5 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -35,9 +35,12 @@ class Interaction extends MetadataType { } /* eslint-enable unicorn/prefer-ternary */ } + // full details for retrieve, only base data for caching; reduces caching time from minutes to seconds + const extras = retrieveDir ? 'all' : ''; + return super.retrieveREST( retrieveDir, - `/interaction/v1/interactions${singleKey}?extras=all`, + `/interaction/v1/interactions${singleKey}?extras=${extras}`, null, null, key From d30f073e51cedf4e21e7784da81dfd779b54aa7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 22:57:30 +0100 Subject: [PATCH 033/132] #627: checks for triggeredSend for retrieve/deploy --- lib/metadataTypes/Interaction.js | 48 +++++++++++++++++++ .../definitions/Interaction.definition.js | 2 +- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 79dd362f5..9e0e13bcf 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -133,6 +133,39 @@ class Interaction extends MetadataType { ); } } + + // triggeredSend + for (const item of metadata.activities) { + // check if all triggeredSends are there + try { + if (item.configurationArguments?.triggeredSendKey) { + // triggeredSendKey is not always set but triggeredSendId is + cache.searchForField( + 'triggeredSendDefinition', + item.configurationArguments.triggeredSendKey, + 'CustomerKey', + 'CustomerKey' + ); + delete item.configurationArguments.triggeredSendId; + } else if (item.configurationArguments?.triggeredSendId) { + // triggeredSendKey is not always set but triggeredSendId is + item.configurationArguments.triggeredSendKey = cache.searchForField( + 'triggeredSendDefinition', + item.configurationArguments.triggeredSendId, + 'ObjectID', + 'CustomerKey' + ); + delete item.configurationArguments.triggeredSendId; + } + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }): Could not find triggeredSendDefinition (${ex.message})` + ); + } + } + return metadata; } /** @@ -160,6 +193,21 @@ class Interaction extends MetadataType { ); } + // triggeredSend + for (const item of metadata.activities) { + // check if all triggeredSends are there + if (!item.configurationArguments?.triggeredSendKey) { + continue; + } + // triggeredSendKey is not always set but triggeredSendId is + item.configurationArguments.triggeredSendId = cache.searchForField( + 'triggeredSendDefinition', + item.configurationArguments.triggeredSendKey, + 'CustomerKey', + 'ObjectID' + ); + } + return metadata; } diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index ff62e16be..88c49528e 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -4,7 +4,7 @@ // update: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/putUpdateInteraction.html module.exports = { bodyIteratorField: 'items', - dependencies: ['folder', 'eventDefinition'], // 'triggeredSendDefinition', + dependencies: ['folder', 'triggeredSendDefinition', 'eventDefinition'], folderIdField: 'categoryId', hasExtended: false, idField: 'id', From f8c45699750379191f522f4b92402fc1a76b32b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jan 2023 22:06:03 +0000 Subject: [PATCH 034/132] Bump mocha from 10.1.0 to 10.2.0 Bumps [mocha](https://github.com/mochajs/mocha) from 10.1.0 to 10.2.0. - [Release notes](https://github.com/mochajs/mocha/releases) - [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md) - [Commits](https://github.com/mochajs/mocha/compare/v10.1.0...v10.2.0) --- updated-dependencies: - dependency-name: mocha dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 379d1b3af..05ce8f71d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,7 +48,7 @@ "husky": "8.0.1", "jsdoc-to-markdown": "8.0.0", "lint-staged": "13.1.0", - "mocha": "10.1.0", + "mocha": "10.2.0", "mock-fs": "5.2.0", "npm-check": "6.0.1", "npm-run-all": "4.1.5", @@ -6367,9 +6367,9 @@ "dev": true }, "node_modules/mocha": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", - "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", "dev": true, "dependencies": { "ansi-colors": "4.1.1", @@ -14555,9 +14555,9 @@ "dev": true }, "mocha": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", - "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", "dev": true, "requires": { "ansi-colors": "4.1.1", diff --git a/package.json b/package.json index 60f770a40..a04347451 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "husky": "8.0.1", "jsdoc-to-markdown": "8.0.0", "lint-staged": "13.1.0", - "mocha": "10.1.0", + "mocha": "10.2.0", "mock-fs": "5.2.0", "npm-check": "6.0.1", "npm-run-all": "4.1.5", From 5588ff2112b570bd3829ce0dfcd4615f4ed89473 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jan 2023 22:14:32 +0000 Subject: [PATCH 035/132] Bump eslint-plugin-unicorn from 45.0.1 to 45.0.2 Bumps [eslint-plugin-unicorn](https://github.com/sindresorhus/eslint-plugin-unicorn) from 45.0.1 to 45.0.2. - [Release notes](https://github.com/sindresorhus/eslint-plugin-unicorn/releases) - [Commits](https://github.com/sindresorhus/eslint-plugin-unicorn/compare/v45.0.1...v45.0.2) --- updated-dependencies: - dependency-name: eslint-plugin-unicorn dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 18 +++++++++--------- package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 05ce8f71d..5c5fd0a25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,7 +44,7 @@ "eslint-plugin-jsdoc": "39.6.4", "eslint-plugin-mocha": "10.1.0", "eslint-plugin-prettier": "4.2.1", - "eslint-plugin-unicorn": "45.0.1", + "eslint-plugin-unicorn": "45.0.2", "husky": "8.0.1", "jsdoc-to-markdown": "8.0.0", "lint-staged": "13.1.0", @@ -3234,13 +3234,13 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "45.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-45.0.1.tgz", - "integrity": "sha512-tLnIw5oDJJc3ILYtlKtqOxPP64FZLTkZkgeuoN6e7x6zw+rhBjOxyvq2c7577LGxXuIhBYrwisZuKNqOOHp3BA==", + "version": "45.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-45.0.2.tgz", + "integrity": "sha512-Y0WUDXRyGDMcKLiwgL3zSMpHrXI00xmdyixEGIg90gHnj0PcHY4moNv3Ppje/kDivdAy5vUeUr7z211ImPv2gw==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.19.1", - "@eslint-community/eslint-utils": "^4.1.0", + "@eslint-community/eslint-utils": "^4.1.2", "ci-info": "^3.6.1", "clean-regexp": "^1.0.0", "esquery": "^1.4.0", @@ -12288,13 +12288,13 @@ } }, "eslint-plugin-unicorn": { - "version": "45.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-45.0.1.tgz", - "integrity": "sha512-tLnIw5oDJJc3ILYtlKtqOxPP64FZLTkZkgeuoN6e7x6zw+rhBjOxyvq2c7577LGxXuIhBYrwisZuKNqOOHp3BA==", + "version": "45.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-45.0.2.tgz", + "integrity": "sha512-Y0WUDXRyGDMcKLiwgL3zSMpHrXI00xmdyixEGIg90gHnj0PcHY4moNv3Ppje/kDivdAy5vUeUr7z211ImPv2gw==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.19.1", - "@eslint-community/eslint-utils": "^4.1.0", + "@eslint-community/eslint-utils": "^4.1.2", "ci-info": "^3.6.1", "clean-regexp": "^1.0.0", "esquery": "^1.4.0", diff --git a/package.json b/package.json index a04347451..d795fc1c1 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "eslint-plugin-jsdoc": "39.6.4", "eslint-plugin-mocha": "10.1.0", "eslint-plugin-prettier": "4.2.1", - "eslint-plugin-unicorn": "45.0.1", + "eslint-plugin-unicorn": "45.0.2", "husky": "8.0.1", "jsdoc-to-markdown": "8.0.0", "lint-staged": "13.1.0", From ac758afe2b7f9e706b360c939120d6c0dd49449e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jan 2023 22:16:16 +0000 Subject: [PATCH 036/132] Bump eslint from 8.29.0 to 8.32.0 Bumps [eslint](https://github.com/eslint/eslint) from 8.29.0 to 8.32.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v8.29.0...v8.32.0) --- updated-dependencies: - dependency-name: eslint dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 70 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5c5fd0a25..4cc2241e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,7 @@ "axios-mock-adapter": "1.21.2", "chai": "4.3.7", "chai-files": "1.4.0", - "eslint": "8.29.0", + "eslint": "8.32.0", "eslint-config-prettier": "8.5.0", "eslint-config-ssjs": "1.1.11", "eslint-plugin-jsdoc": "39.6.4", @@ -535,15 +535,15 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.4.0", - "globals": "^13.15.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -580,14 +580,14 @@ "dev": true }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.6", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.6.tgz", - "integrity": "sha512-jJr+hPTJYKyDILJfhNSHsjiwXYf26Flsz8DvNndOsHs5pwSnpGUEy8yzF0JYhCEvTDdV2vuOK5tt8BVhwO5/hg==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" @@ -3093,13 +3093,13 @@ } }, "node_modules/eslint": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.29.0.tgz", - "integrity": "sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.32.0.tgz", + "integrity": "sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.11.6", + "@eslint/eslintrc": "^1.4.1", + "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", @@ -3118,7 +3118,7 @@ "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.15.0", + "globals": "^13.19.0", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", @@ -4219,9 +4219,9 @@ } }, "node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "version": "13.19.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", + "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -10223,15 +10223,15 @@ } }, "@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.4.0", - "globals": "^13.15.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -10260,14 +10260,14 @@ } }, "@humanwhocodes/config-array": { - "version": "0.11.6", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.6.tgz", - "integrity": "sha512-jJr+hPTJYKyDILJfhNSHsjiwXYf26Flsz8DvNndOsHs5pwSnpGUEy8yzF0JYhCEvTDdV2vuOK5tt8BVhwO5/hg==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" } }, "@humanwhocodes/module-importer": { @@ -12173,13 +12173,13 @@ "dev": true }, "eslint": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.29.0.tgz", - "integrity": "sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.32.0.tgz", + "integrity": "sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.11.6", + "@eslint/eslintrc": "^1.4.1", + "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", @@ -12198,7 +12198,7 @@ "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.15.0", + "globals": "^13.19.0", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", @@ -12974,9 +12974,9 @@ } }, "globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "version": "13.19.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", + "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", "dev": true, "requires": { "type-fest": "^0.20.2" diff --git a/package.json b/package.json index d795fc1c1..5926ea9ab 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "axios-mock-adapter": "1.21.2", "chai": "4.3.7", "chai-files": "1.4.0", - "eslint": "8.29.0", + "eslint": "8.32.0", "eslint-config-prettier": "8.5.0", "eslint-config-ssjs": "1.1.11", "eslint-plugin-jsdoc": "39.6.4", From b6b9e6670716d2fbcbdf2570a80fd2996fe57892 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jan 2023 22:21:47 +0000 Subject: [PATCH 037/132] Bump prettier from 2.8.0 to 2.8.3 Bumps [prettier](https://github.com/prettier/prettier) from 2.8.0 to 2.8.3. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/2.8.0...2.8.3) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4cc2241e9..3802ee99d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "json-to-table": "4.2.1", "mustache": "4.2.0", "p-limit": "3.1.0", - "prettier": "2.8.0", + "prettier": "2.8.3", "prettier-plugin-sql": "0.12.1", "semver": "7.3.8", "sfmc-sdk": "0.6.1", @@ -7718,9 +7718,9 @@ } }, "node_modules/prettier": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.0.tgz", - "integrity": "sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz", + "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==", "bin": { "prettier": "bin-prettier.js" }, @@ -15574,9 +15574,9 @@ "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==" }, "prettier": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.0.tgz", - "integrity": "sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA==" + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz", + "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==" }, "prettier-eslint": { "version": "15.0.1", diff --git a/package.json b/package.json index 5926ea9ab..b896ed704 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "json-to-table": "4.2.1", "mustache": "4.2.0", "p-limit": "3.1.0", - "prettier": "2.8.0", + "prettier": "2.8.3", "prettier-plugin-sql": "0.12.1", "semver": "7.3.8", "sfmc-sdk": "0.6.1", From 96ce1daef4da7e447f66a46040583581f41af4d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 16 Jan 2023 23:30:00 +0100 Subject: [PATCH 038/132] #627: version auto-set to last server-version for update to avoid issues --- lib/metadataTypes/definitions/Interaction.definition.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index 88c49528e..7371dd3fe 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -395,7 +395,7 @@ module.exports = { isCreateable: false, isUpdateable: true, retrieving: true, - template: true, + template: false, }, workflowApiVersion: { isCreateable: true, From 59fd396338fa291b2adcef4bfb093fc6f10042dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jan 2023 22:42:38 +0000 Subject: [PATCH 039/132] Bump eslint-config-prettier from 8.5.0 to 8.6.0 Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 8.5.0 to 8.6.0. - [Release notes](https://github.com/prettier/eslint-config-prettier/releases) - [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/eslint-config-prettier/compare/v8.5.0...v8.6.0) --- updated-dependencies: - dependency-name: eslint-config-prettier dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3802ee99d..aaf0650e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,7 @@ "chai": "4.3.7", "chai-files": "1.4.0", "eslint": "8.32.0", - "eslint-config-prettier": "8.5.0", + "eslint-config-prettier": "8.6.0", "eslint-config-ssjs": "1.1.11", "eslint-plugin-jsdoc": "39.6.4", "eslint-plugin-mocha": "10.1.0", @@ -3149,9 +3149,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz", + "integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -12240,9 +12240,9 @@ } }, "eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz", + "integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==", "dev": true, "requires": {} }, diff --git a/package.json b/package.json index b896ed704..7c6663552 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "chai": "4.3.7", "chai-files": "1.4.0", "eslint": "8.32.0", - "eslint-config-prettier": "8.5.0", + "eslint-config-prettier": "8.6.0", "eslint-config-ssjs": "1.1.11", "eslint-plugin-jsdoc": "39.6.4", "eslint-plugin-mocha": "10.1.0", From 538a90d35e3825eb9f6ce02e065cf2f57ec8eb05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Tue, 17 Jan 2023 00:08:00 +0100 Subject: [PATCH 040/132] #625: bump sfmc-sdk from 0.6.1 to 0.6.2 --- package-lock.json | 30 +++++++++++++++--------------- package.json | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index aaf0650e4..1dfb7974c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "prettier": "2.8.3", "prettier-plugin-sql": "0.12.1", "semver": "7.3.8", - "sfmc-sdk": "0.6.1", + "sfmc-sdk": "0.6.2", "simple-git": "3.15.1", "toposort": "2.0.2", "update-notifier": "5.1.0", @@ -3563,9 +3563,9 @@ "dev": true }, "node_modules/fast-xml-parser": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.8.tgz", - "integrity": "sha512-N4XqZaRMuHMvOFwFlqeBTlvrnXU+QN8wvCl2g9fHzMx2BnLoIYRDwy6XwI8FxogHMFI9OfGQBCddgckvSLTnvg==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.13.tgz", + "integrity": "sha512-g+OboAw8ol1FgTHhKLR7ZHcItNudceiY04BBrvqa0JBWoPhi/+e5r4H5AeW+EsQCroJLJwsuOP3dD3c6cc5uOg==", "dependencies": { "strnum": "^1.0.5" }, @@ -8616,12 +8616,12 @@ "dev": true }, "node_modules/sfmc-sdk": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/sfmc-sdk/-/sfmc-sdk-0.6.1.tgz", - "integrity": "sha512-yzsUpMwtsIZ0klCBlLShKSryPNn4xnPAXbWYbt/zUYGxSUTC7BIhaxq17wPyYyec3ZWButjphBzIAV2Z49H/qg==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/sfmc-sdk/-/sfmc-sdk-0.6.2.tgz", + "integrity": "sha512-9UhnufDFka1rzYr2Ii8zTSiwgozZ0YhoEUTafAzDoz3PXZoRA8qLXlNj2voI/A4Sg44qEpg/1OCk6t7hu30IXA==", "dependencies": { "axios": "^0.27.2", - "fast-xml-parser": "4.0.8", + "fast-xml-parser": "4.0.13", "p-limit": "3.1.0" }, "engines": { @@ -12509,9 +12509,9 @@ "dev": true }, "fast-xml-parser": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.8.tgz", - "integrity": "sha512-N4XqZaRMuHMvOFwFlqeBTlvrnXU+QN8wvCl2g9fHzMx2BnLoIYRDwy6XwI8FxogHMFI9OfGQBCddgckvSLTnvg==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.13.tgz", + "integrity": "sha512-g+OboAw8ol1FgTHhKLR7ZHcItNudceiY04BBrvqa0JBWoPhi/+e5r4H5AeW+EsQCroJLJwsuOP3dD3c6cc5uOg==", "requires": { "strnum": "^1.0.5" } @@ -16238,12 +16238,12 @@ "dev": true }, "sfmc-sdk": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/sfmc-sdk/-/sfmc-sdk-0.6.1.tgz", - "integrity": "sha512-yzsUpMwtsIZ0klCBlLShKSryPNn4xnPAXbWYbt/zUYGxSUTC7BIhaxq17wPyYyec3ZWButjphBzIAV2Z49H/qg==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/sfmc-sdk/-/sfmc-sdk-0.6.2.tgz", + "integrity": "sha512-9UhnufDFka1rzYr2Ii8zTSiwgozZ0YhoEUTafAzDoz3PXZoRA8qLXlNj2voI/A4Sg44qEpg/1OCk6t7hu30IXA==", "requires": { "axios": "^0.27.2", - "fast-xml-parser": "4.0.8", + "fast-xml-parser": "4.0.13", "p-limit": "3.1.0" } }, diff --git a/package.json b/package.json index 7c6663552..93eb22a46 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "prettier": "2.8.3", "prettier-plugin-sql": "0.12.1", "semver": "7.3.8", - "sfmc-sdk": "0.6.1", + "sfmc-sdk": "0.6.2", "simple-git": "3.15.1", "toposort": "2.0.2", "update-notifier": "5.1.0", From f1426608248e938b508375c8040758736557f3dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Tue, 17 Jan 2023 11:14:49 +0100 Subject: [PATCH 041/132] #630: add generic refresh method --- docs/dist/documentation.md | 23 +++++++++++++++++++- lib/cli.js | 21 +++++++++++++++++++ lib/index.js | 35 ++++++++++++++++++++++++++++++- lib/metadataTypes/MetadataType.js | 11 ++++++++++ 4 files changed, 88 insertions(+), 2 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 3bd0fc7a3..a197fe56b 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -473,6 +473,7 @@ main class * [.findBUs(credentialsName)](#Mcdev.findBUs) ⇒ Promise.<void> * [.document(businessUnit, type)](#Mcdev.document) ⇒ Promise.<void> * [.deleteByKey(businessUnit, type, customerKey)](#Mcdev.deleteByKey) ⇒ Promise.<void> + * [.refresh(businessUnit, type)](#Mcdev.refresh) ⇒ Promise.<void> * [.badKeys(businessUnit)](#Mcdev.badKeys) ⇒ Promise.<void> * [.retrieveAsTemplate(businessUnit, selectedType, name, market)](#Mcdev.retrieveAsTemplate) ⇒ Promise.<TYPE.MultiMetadataTypeList> * [.buildTemplate(businessUnit, selectedType, keyArr, market)](#Mcdev.buildTemplate) ⇒ Promise.<TYPE.MultiMetadataTypeList> @@ -604,7 +605,7 @@ Creates docs for supported metadata types in Markdown and/or HTML format ### Mcdev.deleteByKey(businessUnit, type, customerKey) ⇒ Promise.<void> -Creates docs for supported metadata types in Markdown and/or HTML format +deletes metadata from MC instance by key **Kind**: static method of [Mcdev](#Mcdev) **Returns**: Promise.<void> - - @@ -615,6 +616,19 @@ Creates docs for supported metadata types in Markdown and/or HTML format | type | string | supported metadata type | | customerKey | string | Identifier of data extension | + + +### Mcdev.refresh(businessUnit, type) ⇒ Promise.<void> +ensures triggered sends are restarted to ensure they pick up on changes of the underlying emails + +**Kind**: static method of [Mcdev](#Mcdev) +**Returns**: Promise.<void> - - + +| Param | Type | Description | +| --- | --- | --- | +| businessUnit | string | references credentials from properties.json | +| type | string | references credentials from properties.json | + ### Mcdev.badKeys(businessUnit) ⇒ Promise.<void> @@ -3018,6 +3032,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.preDeployTasks(metadata, deployDir, buObject)](#MetadataType.preDeployTasks) ⇒ Promise.<TYPE.MetadataTypeItem> * [.create(metadata, deployDir)](#MetadataType.create) ⇒ void * [.update(metadata, [metadataBefore])](#MetadataType.update) ⇒ void + * [.refresh()](#MetadataType.refresh) ⇒ void * [.hasChanged(cachedVersion, metadata, [fieldName])](#MetadataType.hasChanged) ⇒ boolean * [.hasChangedGeneric(cachedVersion, metadata, [fieldName], [silent])](#MetadataType.hasChangedGeneric) ⇒ boolean * [.upsert(metadata, deployDir, [buObject])](#MetadataType.upsert) ⇒ Promise.<TYPE.MetadataTypeMap> @@ -3257,6 +3272,12 @@ Abstract update method that needs to be implemented in child metadata type | metadata | TYPE.MetadataTypeItem | single metadata entry | | [metadataBefore] | TYPE.MetadataTypeItem | metadata mapped by their keyField | + + +### MetadataType.refresh() ⇒ void +Abstract refresh method that needs to be implemented in child metadata type + +**Kind**: static method of [MetadataType](#MetadataType) ### MetadataType.hasChanged(cachedVersion, metadata, [fieldName]) ⇒ boolean diff --git a/lib/cli.js b/lib/cli.js index 2c6fcc474..6ba9c6ac4 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -350,6 +350,27 @@ yargs Mcdev.getFilesToCommit(argv.BU, argv.TYPE, keyArr); }, }) + .command({ + command: 'refresh ', + aliases: ['re'], + desc: 'ensures that updates are properly published', + builder: (yargs) => { + yargs + .positional('BU', { + type: 'string', + describe: 'the business unit to execute the refresh on', + }) + .positional('TYPE', { + type: 'string', + describe: 'metadata type', + }); + }, + handler: (argv) => { + Mcdev.setSkipInteraction(argv.skipInteraction); + Mcdev.setLoggingLevel(argv); + Mcdev.refresh(argv.BU, argv.TYPE); + }, + }) .command({ command: 'upgrade', aliases: ['up'], diff --git a/lib/index.js b/lib/index.js index ee98a608a..4e7201fed 100644 --- a/lib/index.js +++ b/lib/index.js @@ -350,7 +350,7 @@ class Mcdev { } /** - * Creates docs for supported metadata types in Markdown and/or HTML format + * deletes metadata from MC instance by key * * @param {string} businessUnit references credentials from properties.json * @param {string} type supported metadata type @@ -383,6 +383,39 @@ class Mcdev { } } } + /** + * ensures triggered sends are restarted to ensure they pick up on changes of the underlying emails + * + * @param {string} businessUnit references credentials from properties.json + * @param {string} type references credentials from properties.json + * @returns {Promise.} - + */ + static async refresh(businessUnit, type) { + Util.logger.info('mcdev:: refresh'); + const properties = await config.getProperties(); + if (!(await config.checkProperties(properties))) { + return null; + } + if (!Util._isValidType(type)) { + return; + } + const buObject = await Cli.getCredentialObject(properties, businessUnit); + if (buObject !== null) { + try { + MetadataTypeInfo[type].client = auth.getSDK(buObject); + } catch (ex) { + Util.logger.error(ex.message); + return; + } + try { + MetadataTypeInfo[type].properties = properties; + MetadataTypeInfo[type].buObject = buObject; + await MetadataTypeInfo[type].refresh(); + } catch (ex) { + Util.logger.error('mcdev.refresh ' + ex.message); + } + } + } /** * Converts metadata to legacy format. Output is saved in 'converted' directory diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index cc1070dcb..8a1236f73 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -341,6 +341,17 @@ class MetadataType { ); return; } + /** + * Abstract refresh method that needs to be implemented in child metadata type + * + * @returns {void} + */ + static refresh() { + Util.logger.error( + ` ☇ skipping ${this.definition.type}: refresh is not supported yet for ${this.definition.type}` + ); + return; + } /** * test if metadata was actually changed or not to potentially skip it during deployment From 60563d760ed7938eb00da6e014638ce4b189591c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Tue, 17 Jan 2023 11:29:18 +0100 Subject: [PATCH 042/132] #630: refactoring - get buObject from class, not as fn-param --- docs/dist/documentation.md | 75 ++++++++------------ lib/index.js | 3 +- lib/metadataTypes/DataExtension.js | 16 ++--- lib/metadataTypes/DataExtensionField.js | 10 ++- lib/metadataTypes/EmailSendDefinition.js | 5 +- lib/metadataTypes/EventDefinition.js | 4 +- lib/metadataTypes/Interaction.js | 4 +- lib/metadataTypes/List.js | 5 +- lib/metadataTypes/MetadataType.js | 20 +++--- lib/metadataTypes/TransactionalMessage.js | 4 +- lib/metadataTypes/TransactionalSMS.js | 7 +- lib/metadataTypes/TriggeredSendDefinition.js | 5 +- 12 files changed, 63 insertions(+), 95 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 6d8d54ad2..8c54ff006 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -1639,8 +1639,8 @@ DataExtension MetadataType * [.postRetrieveTasks(metadata)](#DataExtension.postRetrieveTasks) ⇒ TYPE.DataExtensionItem * [.preDeployTasks(metadata)](#DataExtension.preDeployTasks) ⇒ Promise.<TYPE.DataExtensionItem> * [.document(buObject, [metadata])](#DataExtension.document) ⇒ Promise.<void> - * [.deleteByKey(buObject, customerKey)](#DataExtension.deleteByKey) ⇒ Promise.<boolean> - * [.postDeleteTasks(buObject, customerKey)](#DataExtension.postDeleteTasks) ⇒ void + * [.deleteByKey(customerKey)](#DataExtension.deleteByKey) ⇒ Promise.<boolean> + * [.postDeleteTasks(customerKey)](#DataExtension.postDeleteTasks) ⇒ void * [.retrieveForCache(buObject)](#DataExtension.retrieveForCache) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> * [.retrieveAsTemplate(templateDir, name, templateVariables)](#DataExtension.retrieveAsTemplate) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> * [.setFolderPath(metadata)](#DataExtension.setFolderPath) @@ -1777,7 +1777,7 @@ Parses metadata into a readable Markdown/HTML format then saves it -### DataExtension.deleteByKey(buObject, customerKey) ⇒ Promise.<boolean> +### DataExtension.deleteByKey(customerKey) ⇒ Promise.<boolean> Delete a metadata item from the specified business unit **Kind**: static method of [DataExtension](#DataExtension) @@ -1785,19 +1785,17 @@ Delete a metadata item from the specified business unit | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | customerKey | string | Identifier of data extension | -### DataExtension.postDeleteTasks(buObject, customerKey) ⇒ void +### DataExtension.postDeleteTasks(customerKey) ⇒ void clean up after deleting a metadata item **Kind**: static method of [DataExtension](#DataExtension) | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | customerKey | string | Identifier of metadata item | @@ -1866,8 +1864,8 @@ DataExtensionField MetadataType * [.sortDeFields(a, b)](#DataExtensionField.sortDeFields) ⇒ boolean * [.postRetrieveTasks(metadata, forDataExtension)](#DataExtensionField.postRetrieveTasks) ⇒ TYPE.DataExtensionFieldItem * [.prepareDeployColumnsOnUpdate(deployColumns, deKey)](#DataExtensionField.prepareDeployColumnsOnUpdate) ⇒ Object.<string, TYPE.DataExtensionFieldItem> - * [.deleteByKey(buObject, customerKey)](#DataExtensionField.deleteByKey) ⇒ Promise.<boolean> - * [.deleteByKeySOAP(buObject, customerKey, [handleOutside])](#DataExtensionField.deleteByKeySOAP) ⇒ boolean + * [.deleteByKey(customerKey)](#DataExtensionField.deleteByKey) ⇒ Promise.<boolean> + * [.deleteByKeySOAP(customerKey, [handleOutside])](#DataExtensionField.deleteByKeySOAP) ⇒ boolean * [.postDeleteTasks(customerKey)](#DataExtensionField.postDeleteTasks) ⇒ void @@ -1951,7 +1949,7 @@ Removes FieldType field if its the same in deploy and target column, because it -### DataExtensionField.deleteByKey(buObject, customerKey) ⇒ Promise.<boolean> +### DataExtensionField.deleteByKey(customerKey) ⇒ Promise.<boolean> Delete a metadata item from the specified business unit **Kind**: static method of [DataExtensionField](#DataExtensionField) @@ -1959,12 +1957,11 @@ Delete a metadata item from the specified business unit | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | customerKey | string | Identifier of data extension | -### DataExtensionField.deleteByKeySOAP(buObject, customerKey, [handleOutside]) ⇒ boolean +### DataExtensionField.deleteByKeySOAP(customerKey, [handleOutside]) ⇒ boolean Delete a data extension from the specified business unit **Kind**: static method of [DataExtensionField](#DataExtensionField) @@ -1972,7 +1969,6 @@ Delete a data extension from the specified business unit | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | customerKey | string | Identifier of metadata | | [handleOutside] | boolean | if the API reponse is irregular this allows you to handle it outside of this generic method | @@ -2252,7 +2248,7 @@ MessageSendActivity MetadataType * [.retrieve(retrieveDir, [_], [__], [___], [key])](#EmailSendDefinition.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.update(metadataItem)](#EmailSendDefinition.update) ⇒ Promise * [.create(metadataItem)](#EmailSendDefinition.create) ⇒ Promise - * [.deleteByKey(buObject, customerKey)](#EmailSendDefinition.deleteByKey) ⇒ Promise.<boolean> + * [.deleteByKey(customerKey)](#EmailSendDefinition.deleteByKey) ⇒ Promise.<boolean> * [.preDeployTasks(metadata)](#EmailSendDefinition.preDeployTasks) ⇒ Promise.<TYPE.MetadataTypeItem> * [.postRetrieveTasks(metadata)](#EmailSendDefinition.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.parseMetadata(metadata)](#EmailSendDefinition.parseMetadata) ⇒ TYPE.MetadataTypeItem @@ -2299,7 +2295,7 @@ Creates a single item -### EmailSendDefinition.deleteByKey(buObject, customerKey) ⇒ Promise.<boolean> +### EmailSendDefinition.deleteByKey(customerKey) ⇒ Promise.<boolean> Delete a metadata item from the specified business unit **Kind**: static method of [EmailSendDefinition](#EmailSendDefinition) @@ -2307,7 +2303,6 @@ Delete a metadata item from the specified business unit | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | customerKey | string | Identifier of data extension | @@ -2359,7 +2354,7 @@ EventDefinition MetadataType * [.retrieveForCache()](#EventDefinition.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveAsTemplate(templateDir, name, templateVariables)](#EventDefinition.retrieveAsTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.postRetrieveTasks(eventDef)](#EventDefinition.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem - * [.deleteByKey(buObject, key)](#EventDefinition.deleteByKey) ⇒ Promise.<boolean> + * [.deleteByKey(key)](#EventDefinition.deleteByKey) ⇒ Promise.<boolean> * [.create(EventDefinition)](#EventDefinition.create) ⇒ Promise * [.update(metadataEntry)](#EventDefinition.update) ⇒ Promise * [.preDeployTasks(metadata)](#EventDefinition.preDeployTasks) ⇒ TYPE.MetadataTypeItem @@ -2418,7 +2413,7 @@ manages post retrieve steps -### EventDefinition.deleteByKey(buObject, key) ⇒ Promise.<boolean> +### EventDefinition.deleteByKey(key) ⇒ Promise.<boolean> Delete a metadata item from the specified business unit **Kind**: static method of [EventDefinition](#EventDefinition) @@ -2426,7 +2421,6 @@ Delete a metadata item from the specified business unit | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | key | string | Identifier of item | @@ -2935,7 +2929,7 @@ Script MetadataType * [Interaction](#Interaction) ⇐ [MetadataType](#MetadataType) * [.retrieve(retrieveDir, [_], [__], [___], [key])](#Interaction.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [.deleteByKey(buObject, key, version)](#Interaction.deleteByKey) ⇒ Promise.<boolean> + * [.deleteByKey(key, version)](#Interaction.deleteByKey) ⇒ Promise.<boolean> * [.update(metadata)](#Interaction.update) ⇒ Promise * [.create(metadata)](#Interaction.create) ⇒ Promise * [.postRetrieveTasks(metadata)](#Interaction.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem @@ -2961,7 +2955,7 @@ Endpoint /interaction/v1/interactions?extras=all&pageSize=50000 return 50000 Scr -### Interaction.deleteByKey(buObject, key, version) ⇒ Promise.<boolean> +### Interaction.deleteByKey(key, version) ⇒ Promise.<boolean> Delete a metadata item from the specified business unit **Kind**: static method of [Interaction](#Interaction) @@ -2969,7 +2963,6 @@ Delete a metadata item from the specified business unit | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | key | string | Identifier of item | | version | number | required version of metadata | @@ -3046,7 +3039,7 @@ List MetadataType * [.retrieve(retrieveDir, [_], buObject, [___], [key])](#List.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache(buObject)](#List.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [._retrieveParentAllSubs(buObject, results)](#List._retrieveParentAllSubs) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [.deleteByKey(buObject, customerKey)](#List.deleteByKey) ⇒ Promise.<boolean> + * [.deleteByKey(customerKey)](#List.deleteByKey) ⇒ Promise.<boolean> * [.postRetrieveTasks(list)](#List.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.parseMetadata(metadata, [parseForCache])](#List.parseMetadata) ⇒ TYPE.MetadataTypeItem @@ -3093,7 +3086,7 @@ helper for @link retrieveForCache and @link retrieve -### List.deleteByKey(buObject, customerKey) ⇒ Promise.<boolean> +### List.deleteByKey(customerKey) ⇒ Promise.<boolean> Delete a metadata item from the specified business unit **Kind**: static method of [List](#List) @@ -3101,7 +3094,6 @@ Delete a metadata item from the specified business unit | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | customerKey | string | Identifier of data extension | @@ -3187,10 +3179,10 @@ Provides default functionality that can be overwritten by child metadata type cl * [.buildDefinition(templateDir, targetDir, templateName, variables)](#MetadataType.buildDefinition) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.checkForErrors(ex)](#MetadataType.checkForErrors) ⇒ Array.<string> * [.document([buObject], [metadata], [isDeploy])](#MetadataType.document) ⇒ void - * [.deleteByKey(buObject, customerKey, [version])](#MetadataType.deleteByKey) ⇒ boolean - * [.postDeleteTasks(buObject, customerKey)](#MetadataType.postDeleteTasks) ⇒ void - * [.deleteByKeySOAP(buObject, customerKey, [handleOutside])](#MetadataType.deleteByKeySOAP) ⇒ boolean - * [.deleteByKeyREST(buObject, url, key, [handleOutside])](#MetadataType.deleteByKeyREST) ⇒ boolean + * [.deleteByKey(customerKey, [version])](#MetadataType.deleteByKey) ⇒ boolean + * [.postDeleteTasks(customerKey)](#MetadataType.postDeleteTasks) ⇒ void + * [.deleteByKeySOAP(customerKey, [handleOutside])](#MetadataType.deleteByKeySOAP) ⇒ boolean + * [.deleteByKeyREST(url, key, [handleOutside])](#MetadataType.deleteByKeyREST) ⇒ boolean * [.readBUMetadataForType(readDir, [listBadKeys], [buMetadata])](#MetadataType.readBUMetadataForType) ⇒ object * [.getFilesToCommit(keyArr)](#MetadataType.getFilesToCommit) ⇒ Promise.<Array.<string>> @@ -3821,7 +3813,7 @@ Gets metadata cache with limited fields and does not store value to disk -### MetadataType.deleteByKey(buObject, customerKey, [version]) ⇒ boolean +### MetadataType.deleteByKey(customerKey, [version]) ⇒ boolean Delete a metadata item from the specified business unit **Kind**: static method of [MetadataType](#MetadataType) @@ -3829,25 +3821,23 @@ Delete a metadata item from the specified business unit | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | customerKey | string | Identifier of data extension | | [version] | number | optional version of metadata | -### MetadataType.postDeleteTasks(buObject, customerKey) ⇒ void +### MetadataType.postDeleteTasks(customerKey) ⇒ void clean up after deleting a metadata item **Kind**: static method of [MetadataType](#MetadataType) | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | customerKey | string | Identifier of metadata item | -### MetadataType.deleteByKeySOAP(buObject, customerKey, [handleOutside]) ⇒ boolean +### MetadataType.deleteByKeySOAP(customerKey, [handleOutside]) ⇒ boolean Delete a data extension from the specified business unit **Kind**: static method of [MetadataType](#MetadataType) @@ -3855,13 +3845,12 @@ Delete a data extension from the specified business unit | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | customerKey | string | Identifier of metadata | | [handleOutside] | boolean | if the API reponse is irregular this allows you to handle it outside of this generic method | -### MetadataType.deleteByKeyREST(buObject, url, key, [handleOutside]) ⇒ boolean +### MetadataType.deleteByKeyREST(url, key, [handleOutside]) ⇒ boolean Delete a data extension from the specified business unit **Kind**: static method of [MetadataType](#MetadataType) @@ -3869,7 +3858,6 @@ Delete a data extension from the specified business unit | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | url | string | endpoint | | key | string | Identifier of metadata | | [handleOutside] | boolean | if the API reponse is irregular this allows you to handle it outside of this generic method | @@ -4623,7 +4611,7 @@ TransactionalMessage MetadataType * [.retrieveForCache()](#TransactionalMessage.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.update(metadata)](#TransactionalMessage.update) ⇒ Promise * [.create(metadata)](#TransactionalMessage.create) ⇒ Promise - * [.deleteByKey(buObject, key)](#TransactionalMessage.deleteByKey) ⇒ Promise.<boolean> + * [.deleteByKey(key)](#TransactionalMessage.deleteByKey) ⇒ Promise.<boolean> @@ -4675,7 +4663,7 @@ Creates a single item -### TransactionalMessage.deleteByKey(buObject, key) ⇒ Promise.<boolean> +### TransactionalMessage.deleteByKey(key) ⇒ Promise.<boolean> Delete a metadata item from the specified business unit **Kind**: static method of [TransactionalMessage](#TransactionalMessage) @@ -4683,7 +4671,6 @@ Delete a metadata item from the specified business unit | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | key | string | Identifier of item | @@ -4731,7 +4718,7 @@ TransactionalSMS MetadataType **Extends**: [TransactionalMessage](#TransactionalMessage) * [TransactionalSMS](#TransactionalSMS) ⇐ [TransactionalMessage](#TransactionalMessage) - * [.postDeleteTasks(buObject, customerKey)](#TransactionalSMS.postDeleteTasks) ⇒ void + * [.postDeleteTasks(customerKey)](#TransactionalSMS.postDeleteTasks) ⇒ void * [.preDeployTasks(metadata, dir)](#TransactionalSMS.preDeployTasks) ⇒ TYPE.MetadataTypeItem * [._mergeCode(metadata, deployDir, [templateName])](#TransactionalSMS._mergeCode) ⇒ Promise.<string> * [.postRetrieveTasks(metadata)](#TransactionalSMS.postRetrieveTasks) ⇒ TYPE.CodeExtractItem @@ -4744,14 +4731,13 @@ TransactionalSMS MetadataType -### TransactionalSMS.postDeleteTasks(buObject, customerKey) ⇒ void +### TransactionalSMS.postDeleteTasks(customerKey) ⇒ void clean up after deleting a metadata item **Kind**: static method of [TransactionalSMS](#TransactionalSMS) | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | customerKey | string | Identifier of metadata item | @@ -4898,7 +4884,7 @@ MessageSendActivity MetadataType * [.retrieve(retrieveDir, [_], [__], [___], [key])](#TriggeredSendDefinition.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.create(metadata)](#TriggeredSendDefinition.create) ⇒ Promise * [.update(metadata)](#TriggeredSendDefinition.update) ⇒ Promise - * [.deleteByKey(buObject, customerKey)](#TriggeredSendDefinition.deleteByKey) ⇒ Promise.<boolean> + * [.deleteByKey(customerKey)](#TriggeredSendDefinition.deleteByKey) ⇒ Promise.<boolean> * [.postRetrieveTasks(metadata)](#TriggeredSendDefinition.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.setFolderPath(metadata)](#TriggeredSendDefinition.setFolderPath) * [.parseMetadata(metadata)](#TriggeredSendDefinition.parseMetadata) ⇒ TYPE.MetadataTypeItem @@ -4946,7 +4932,7 @@ Updates a single TSD. -### TriggeredSendDefinition.deleteByKey(buObject, customerKey) ⇒ Promise.<boolean> +### TriggeredSendDefinition.deleteByKey(customerKey) ⇒ Promise.<boolean> Delete a metadata item from the specified business unit **Kind**: static method of [TriggeredSendDefinition](#TriggeredSendDefinition) @@ -4954,7 +4940,6 @@ Delete a metadata item from the specified business unit | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | references credentials | | customerKey | string | Identifier of data extension | diff --git a/lib/index.js b/lib/index.js index e01a254d8..05b5f0cd6 100644 --- a/lib/index.js +++ b/lib/index.js @@ -378,7 +378,8 @@ class Mcdev { } try { MetadataTypeInfo[type].properties = properties; - await MetadataTypeInfo[type].deleteByKey(buObject, customerKey, version); + MetadataTypeInfo[type].buObject = buObject; + await MetadataTypeInfo[type].deleteByKey(customerKey, version); } catch (ex) { Util.logger.errorStack(ex, ` - Deleting ${type} failed`); } diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index 09324197e..b9c271981 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -820,27 +820,25 @@ class DataExtension extends MetadataType { /** * Delete a metadata item from the specified business unit * - * @param {TYPE.BuObject} buObject references credentials * @param {string} customerKey Identifier of data extension * @returns {Promise.} deletion success status */ - static deleteByKey(buObject, customerKey) { - return super.deleteByKeySOAP(buObject, customerKey, false); + static deleteByKey(customerKey) { + return super.deleteByKeySOAP(customerKey, false); } /** * clean up after deleting a metadata item * - * @param {TYPE.BuObject} buObject references credentials * @param {string} customerKey Identifier of metadata item * @returns {void} */ - static async postDeleteTasks(buObject, customerKey) { + static async postDeleteTasks(customerKey) { // delete local copy: retrieve/cred/bu/dataExtension/...json const jsonFile = File.normalizePath([ this.properties.directories.retrieve, - buObject.credential, - buObject.businessUnit, + this.buObject.credential, + this.buObject.businessUnit, this.definition.type, `${customerKey}.${this.definition.type}-meta.json`, ]); @@ -849,8 +847,8 @@ class DataExtension extends MetadataType { const mdFile = File.normalizePath([ this.properties.directories.docs, 'dataExtension', - buObject.credential, - buObject.businessUnit, + this.buObject.credential, + this.buObject.businessUnit, `${customerKey}.${this.definition.type}.md`, ]); await File.remove(mdFile); diff --git a/lib/metadataTypes/DataExtensionField.js b/lib/metadataTypes/DataExtensionField.js index 90b96d1ff..fb96596ac 100644 --- a/lib/metadataTypes/DataExtensionField.js +++ b/lib/metadataTypes/DataExtensionField.js @@ -253,23 +253,21 @@ class DataExtensionField extends MetadataType { /** * Delete a metadata item from the specified business unit * - * @param {TYPE.BuObject} buObject references credentials * @param {string} customerKey Identifier of data extension * @returns {Promise.} deletion success status */ - static deleteByKey(buObject, customerKey) { - return this.deleteByKeySOAP(buObject, customerKey, false); + static deleteByKey(customerKey) { + return this.deleteByKeySOAP(customerKey, false); } /** * Delete a data extension from the specified business unit * - * @param {TYPE.BuObject} buObject references credentials * @param {string} customerKey Identifier of metadata * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method * @returns {boolean} deletion success flag */ - static async deleteByKeySOAP(buObject, customerKey, handleOutside) { + static async deleteByKeySOAP(customerKey, handleOutside) { const [deKey, fieldKey] = customerKey.split('.'); customerKey = `[${deKey}].[${fieldKey}]`; @@ -309,7 +307,7 @@ class DataExtensionField extends MetadataType { if (!handleOutside) { Util.logger.info(`- deleted ${this.definition.type}: ${customerKey}`); } - this.postDeleteTasks(buObject, customerKey); + this.postDeleteTasks(customerKey); return true; } catch (ex) { if (handleOutside) { diff --git a/lib/metadataTypes/EmailSendDefinition.js b/lib/metadataTypes/EmailSendDefinition.js index c8e567027..c6d3c954c 100644 --- a/lib/metadataTypes/EmailSendDefinition.js +++ b/lib/metadataTypes/EmailSendDefinition.js @@ -79,12 +79,11 @@ class EmailSendDefinition extends MetadataType { /** * Delete a metadata item from the specified business unit * - * @param {TYPE.BuObject} buObject references credentials * @param {string} customerKey Identifier of data extension * @returns {Promise.} deletion success status */ - static deleteByKey(buObject, customerKey) { - return super.deleteByKeySOAP(buObject, customerKey, false); + static deleteByKey(customerKey) { + return super.deleteByKeySOAP(customerKey, false); } /** diff --git a/lib/metadataTypes/EventDefinition.js b/lib/metadataTypes/EventDefinition.js index 80d991970..da37f3c2a 100644 --- a/lib/metadataTypes/EventDefinition.js +++ b/lib/metadataTypes/EventDefinition.js @@ -119,13 +119,11 @@ class EventDefinition extends MetadataType { /** * Delete a metadata item from the specified business unit * - * @param {TYPE.BuObject} buObject references credentials * @param {string} key Identifier of item * @returns {Promise.} deletion success status */ - static deleteByKey(buObject, key) { + static deleteByKey(key) { return super.deleteByKeyREST( - buObject, '/interaction/v1/eventDefinitions/key:' + encodeURIComponent(key), key, false diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 9e0e13bcf..bb29285aa 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -49,12 +49,11 @@ class Interaction extends MetadataType { /** * Delete a metadata item from the specified business unit * - * @param {TYPE.BuObject} buObject references credentials * @param {string} key Identifier of item * @param {number} version required version of metadata * @returns {Promise.} deletion success status */ - static async deleteByKey(buObject, key, version) { + static async deleteByKey(key, version) { if (Number.isNaN(version)) { throw new TypeError( 'Version is required for deleting interactions to avoid accidental deletion of the wrong item.' @@ -79,7 +78,6 @@ class Interaction extends MetadataType { ); /* eslint-enable unicorn/prefer-ternary */ return super.deleteByKeyREST( - buObject, '/interaction/v1/interactions/' + singleKey + `?versionNumber=${version}`, key, false diff --git a/lib/metadataTypes/List.js b/lib/metadataTypes/List.js index a13146000..632802b8b 100644 --- a/lib/metadataTypes/List.js +++ b/lib/metadataTypes/List.js @@ -153,12 +153,11 @@ class List extends MetadataType { /** * Delete a metadata item from the specified business unit * - * @param {TYPE.BuObject} buObject references credentials * @param {string} customerKey Identifier of data extension * @returns {Promise.} deletion success status */ - static deleteByKey(buObject, customerKey) { - return super.deleteByKeySOAP(buObject, customerKey, false); + static deleteByKey(customerKey) { + return super.deleteByKeySOAP(customerKey, false); } /** diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 0a056c8e0..40d403ab6 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -1579,28 +1579,26 @@ class MetadataType { /** * Delete a metadata item from the specified business unit * - * @param {TYPE.BuObject} buObject references credentials * @param {string} customerKey Identifier of data extension * @param {number} [version] optional version of metadata * @returns {boolean} deletion success status */ - static deleteByKey(buObject, customerKey, version) { + static deleteByKey(customerKey, version) { Util.logger.error(`Deletion is not yet supported for ${this.definition.typeName}!`); return false; } /** * clean up after deleting a metadata item * - * @param {TYPE.BuObject} buObject references credentials * @param {string} customerKey Identifier of metadata item * @returns {void} */ - static async postDeleteTasks(buObject, customerKey) { + static async postDeleteTasks(customerKey) { // delete local copy: retrieve/cred/bu/type/...json const jsonFile = File.normalizePath([ this.properties.directories.retrieve, - buObject.credential, - buObject.businessUnit, + this.buObject.credential, + this.buObject.businessUnit, this.definition.type, `${customerKey}.${this.definition.type}-meta.json`, ]); @@ -1610,12 +1608,11 @@ class MetadataType { /** * Delete a data extension from the specified business unit * - * @param {TYPE.BuObject} buObject references credentials * @param {string} customerKey Identifier of metadata * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method * @returns {boolean} deletion success flag */ - static async deleteByKeySOAP(buObject, customerKey, handleOutside) { + static async deleteByKeySOAP(customerKey, handleOutside) { const keyObj = {}; keyObj[this.definition.keyField] = customerKey; try { @@ -1627,7 +1624,7 @@ class MetadataType { if (!handleOutside) { Util.logger.info(`- deleted ${this.definition.type}: ${customerKey}`); } - this.postDeleteTasks(buObject, customerKey); + this.postDeleteTasks(customerKey); return true; } catch (ex) { @@ -1648,13 +1645,12 @@ class MetadataType { /** * Delete a data extension from the specified business unit * - * @param {TYPE.BuObject} buObject references credentials * @param {string} url endpoint * @param {string} key Identifier of metadata * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method * @returns {boolean} deletion success flag */ - static async deleteByKeyREST(buObject, url, key, handleOutside) { + static async deleteByKeyREST(url, key, handleOutside) { const keyObj = {}; keyObj[this.definition.keyField] = key; try { @@ -1662,7 +1658,7 @@ class MetadataType { if (!handleOutside) { Util.logger.info(`- deleted ${this.definition.type}: ${key}`); } - this.postDeleteTasks(buObject, key); + this.postDeleteTasks(key); return true; } catch (ex) { diff --git a/lib/metadataTypes/TransactionalMessage.js b/lib/metadataTypes/TransactionalMessage.js index 67c22ee68..ec7f3fb6f 100644 --- a/lib/metadataTypes/TransactionalMessage.js +++ b/lib/metadataTypes/TransactionalMessage.js @@ -106,13 +106,11 @@ class TransactionalMessage extends MetadataType { /** * Delete a metadata item from the specified business unit * - * @param {TYPE.BuObject} buObject references credentials * @param {string} key Identifier of item * @returns {Promise.} deletion success status */ - static deleteByKey(buObject, key) { + static deleteByKey(key) { return super.deleteByKeyREST( - buObject, '/messaging/v1/' + this.subType + '/definitions/' + key, key, false diff --git a/lib/metadataTypes/TransactionalSMS.js b/lib/metadataTypes/TransactionalSMS.js index d1f12f730..0d3546114 100644 --- a/lib/metadataTypes/TransactionalSMS.js +++ b/lib/metadataTypes/TransactionalSMS.js @@ -17,16 +17,15 @@ class TransactionalSMS extends TransactionalMessage { /** * clean up after deleting a metadata item * - * @param {TYPE.BuObject} buObject references credentials * @param {string} customerKey Identifier of metadata item * @returns {void} */ - static async postDeleteTasks(buObject, customerKey) { + static async postDeleteTasks(customerKey) { // delete local copy: retrieve/cred/bu/type/...json const fileName = File.normalizePath([ this.properties.directories.retrieve, - buObject.credential, - buObject.businessUnit, + this.buObject.credential, + this.buObject.businessUnit, this.definition.type, `${customerKey}.${this.definition.type}-meta.`, ]); diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index c2983ee07..abbf8b8da 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -73,12 +73,11 @@ class TriggeredSendDefinition extends MetadataType { /** * Delete a metadata item from the specified business unit * - * @param {TYPE.BuObject} buObject references credentials * @param {string} customerKey Identifier of data extension * @returns {Promise.} deletion success status */ - static deleteByKey(buObject, customerKey) { - return super.deleteByKeySOAP(buObject, customerKey, false); + static deleteByKey(customerKey) { + return super.deleteByKeySOAP(customerKey, false); } /** From 0d44ac7024c9719c9f47091d7d79dd8cef43431d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Tue, 17 Jan 2023 11:31:15 +0100 Subject: [PATCH 043/132] #630: move to standardized type check --- lib/index.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/index.js b/lib/index.js index 05b5f0cd6..b7d02fdcd 100644 --- a/lib/index.js +++ b/lib/index.js @@ -360,16 +360,15 @@ class Mcdev { */ static async deleteByKey(businessUnit, type, customerKey, version) { Util.logger.info('mcdev:: delete'); + if (!Util._isValidType(type)) { + return; + } const properties = await config.getProperties(); if (!(await config.checkProperties(properties))) { return null; } const buObject = await Cli.getCredentialObject(properties, businessUnit); if (buObject !== null) { - if ('string' !== typeof type) { - Util.logger.error('mcdev.delete failed: Bad metadata type passed in'); - return; - } try { MetadataTypeInfo[type].client = auth.getSDK(buObject); } catch (ex) { @@ -394,13 +393,13 @@ class Mcdev { */ static async refresh(businessUnit, type) { Util.logger.info('mcdev:: refresh'); + if (!Util._isValidType(type)) { + return; + } const properties = await config.getProperties(); if (!(await config.checkProperties(properties))) { return null; } - if (!Util._isValidType(type)) { - return; - } const buObject = await Cli.getCredentialObject(properties, businessUnit); if (buObject !== null) { try { From fe1aa561bd6e2ad0f65b24c7314b25aa8b305622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Tue, 17 Jan 2023 11:46:33 +0100 Subject: [PATCH 044/132] #630: fix eslint warnings for return values --- docs/dist/documentation.md | 12 ++++++------ lib/metadataTypes/MetadataType.js | 2 +- lib/metadataTypes/TriggeredSendDefinition.js | 2 +- lib/util/util.js | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 8c54ff006..0f827fe44 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -3177,7 +3177,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.findSubType(templateDir, templateName)](#MetadataType.findSubType) ⇒ Promise.<string> * [.readSecondaryFolder(templateDir, typeDirArr, templateName, fileName, ex)](#MetadataType.readSecondaryFolder) ⇒ object * [.buildDefinition(templateDir, targetDir, templateName, variables)](#MetadataType.buildDefinition) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [.checkForErrors(ex)](#MetadataType.checkForErrors) ⇒ Array.<string> + * [.checkForErrors(ex)](#MetadataType.checkForErrors) ⇒ Array.<string> \| void * [.document([buObject], [metadata], [isDeploy])](#MetadataType.document) ⇒ void * [.deleteByKey(customerKey, [version])](#MetadataType.deleteByKey) ⇒ boolean * [.postDeleteTasks(customerKey)](#MetadataType.postDeleteTasks) ⇒ void @@ -3788,11 +3788,11 @@ parsing is required (for example scripts & queries) -### MetadataType.checkForErrors(ex) ⇒ Array.<string> +### MetadataType.checkForErrors(ex) ⇒ Array.<string> \| void Standardizes a check for multiple messages **Kind**: static method of [MetadataType](#MetadataType) -**Returns**: Array.<string> - formatted Error Message +**Returns**: Array.<string> \| void - formatted Error Message | Param | Type | Description | | --- | --- | --- | @@ -4887,7 +4887,7 @@ MessageSendActivity MetadataType * [.deleteByKey(customerKey)](#TriggeredSendDefinition.deleteByKey) ⇒ Promise.<boolean> * [.postRetrieveTasks(metadata)](#TriggeredSendDefinition.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.setFolderPath(metadata)](#TriggeredSendDefinition.setFolderPath) - * [.parseMetadata(metadata)](#TriggeredSendDefinition.parseMetadata) ⇒ TYPE.MetadataTypeItem + * [.parseMetadata(metadata)](#TriggeredSendDefinition.parseMetadata) ⇒ TYPE.MetadataTypeItem \| void * [.preDeployTasks(metadata)](#TriggeredSendDefinition.preDeployTasks) ⇒ TYPE.MetadataTypeItem @@ -4967,11 +4967,11 @@ generic script that retrieves the folder path from cache and updates the given m -### TriggeredSendDefinition.parseMetadata(metadata) ⇒ TYPE.MetadataTypeItem +### TriggeredSendDefinition.parseMetadata(metadata) ⇒ TYPE.MetadataTypeItem \| void parses retrieved Metadata before saving **Kind**: static method of [TriggeredSendDefinition](#TriggeredSendDefinition) -**Returns**: TYPE.MetadataTypeItem - Array with one metadata object and one sql string +**Returns**: TYPE.MetadataTypeItem \| void - Array with one metadata object and one sql string | Param | Type | Description | | --- | --- | --- | diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 40d403ab6..a5fd1803d 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -1528,7 +1528,7 @@ class MetadataType { * Standardizes a check for multiple messages * * @param {object} ex response payload from REST API - * @returns {string[]} formatted Error Message + * @returns {string[] | void} formatted Error Message */ static checkForErrors(ex) { if (ex?.response?.status >= 400 && ex?.response?.status < 600) { diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index abbf8b8da..98177a1c6 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -116,7 +116,7 @@ class TriggeredSendDefinition extends MetadataType { * parses retrieved Metadata before saving * * @param {TYPE.MetadataTypeItem} metadata a single query activity definition - * @returns {TYPE.MetadataTypeItem} Array with one metadata object and one sql string + * @returns {TYPE.MetadataTypeItem | void} Array with one metadata object and one sql string */ static parseMetadata(metadata) { // remove IsPlatformObject, always has to be 'false' diff --git a/lib/util/util.js b/lib/util/util.js index e7175cf08..18c99b2d2 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -161,14 +161,14 @@ const Util = { const [type, subType] = selectedType ? selectedType.split('-') : []; if (type && !MetadataDefinitions[type]) { Util.logger.error(`:: '${type}' is not a valid metadata type`); - return; + return false; } else if ( type && subType && (!MetadataDefinitions[type] || !MetadataDefinitions[type].subTypes.includes(subType)) ) { Util.logger.error(`:: '${selectedType}' is not a valid metadata type`); - return; + return false; } return true; }, From 1ca5a4055581b64caba7ba9e1549adc08cae90f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Tue, 17 Jan 2023 11:51:57 +0100 Subject: [PATCH 045/132] #630: making type optional, because only 1 type is supported at this time --- docs/dist/documentation.md | 10 ++++++---- lib/cli.js | 2 +- lib/index.js | 5 +++-- lib/util/util.js | 11 ++++++++--- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 0f827fe44..9a9742c1b 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -5057,7 +5057,7 @@ CLI entry for SFMC DevTools * [.signalFatalError()](#Util.signalFatalError) ⇒ void * [.isTrue(attrValue)](#Util.isTrue) ⇒ boolean * [.isFalse(attrValue)](#Util.isFalse) ⇒ boolean - * [._isValidType(selectedType)](#Util._isValidType) ⇒ boolean + * [._isValidType(selectedType, [handleOutside])](#Util._isValidType) ⇒ boolean * [.getRetrieveTypeChoices()](#Util.getRetrieveTypeChoices) ⇒ Array.<TYPE.SupportedMetadataTypes> * [.metadataLogger(level, type, method, payload, [source])](#Util.metadataLogger) ⇒ void * [.replaceByObject(str, obj)](#Util.replaceByObject) ⇒ string \| object @@ -5175,7 +5175,7 @@ SFMC accepts multiple false values for Boolean attributes for which we are check -### Util.\_isValidType(selectedType) ⇒ boolean +### Util.\_isValidType(selectedType, [handleOutside]) ⇒ boolean helper for [retrieve](#Mcdev.retrieve), [retrieveAsTemplate](#Mcdev.retrieveAsTemplate) and [deploy](#Mcdev.deploy) **Kind**: static method of [Util](#Util) @@ -5184,6 +5184,7 @@ helper for [retrieve](#Mcdev.retrieve), [retrieveAsTemplate](#Mcdev.retrieveAsTe | Param | Type | Description | | --- | --- | --- | | selectedType | TYPE.SupportedMetadataTypes | type or type-subtype | +| [handleOutside] | boolean | if the API reponse is irregular this allows you to handle it outside of this generic method | @@ -6762,7 +6763,7 @@ Util that contains logger and simple util methods * [.signalFatalError()](#Util.signalFatalError) ⇒ void * [.isTrue(attrValue)](#Util.isTrue) ⇒ boolean * [.isFalse(attrValue)](#Util.isFalse) ⇒ boolean - * [._isValidType(selectedType)](#Util._isValidType) ⇒ boolean + * [._isValidType(selectedType, [handleOutside])](#Util._isValidType) ⇒ boolean * [.getRetrieveTypeChoices()](#Util.getRetrieveTypeChoices) ⇒ Array.<TYPE.SupportedMetadataTypes> * [.metadataLogger(level, type, method, payload, [source])](#Util.metadataLogger) ⇒ void * [.replaceByObject(str, obj)](#Util.replaceByObject) ⇒ string \| object @@ -6880,7 +6881,7 @@ SFMC accepts multiple false values for Boolean attributes for which we are check -### Util.\_isValidType(selectedType) ⇒ boolean +### Util.\_isValidType(selectedType, [handleOutside]) ⇒ boolean helper for [retrieve](#Mcdev.retrieve), [retrieveAsTemplate](#Mcdev.retrieveAsTemplate) and [deploy](#Mcdev.deploy) **Kind**: static method of [Util](#Util) @@ -6889,6 +6890,7 @@ helper for [retrieve](#Mcdev.retrieve), [retrieveAsTemplate](#Mcdev.retrieveAsTe | Param | Type | Description | | --- | --- | --- | | selectedType | TYPE.SupportedMetadataTypes | type or type-subtype | +| [handleOutside] | boolean | if the API reponse is irregular this allows you to handle it outside of this generic method | diff --git a/lib/cli.js b/lib/cli.js index fccd2f3d5..5e822bd4d 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -355,7 +355,7 @@ yargs }, }) .command({ - command: 'refresh ', + command: 'refresh [TYPE]', aliases: ['re'], desc: 'ensures that updates are properly published', builder: (yargs) => { diff --git a/lib/index.js b/lib/index.js index b7d02fdcd..3e0ebbdd5 100644 --- a/lib/index.js +++ b/lib/index.js @@ -393,8 +393,9 @@ class Mcdev { */ static async refresh(businessUnit, type) { Util.logger.info('mcdev:: refresh'); - if (!Util._isValidType(type)) { - return; + if (!type || !Util._isValidType(type, true)) { + type = 'triggeredSendDefinition'; + Util.logger.info(' - setting type to ' + type); } const properties = await config.getProperties(); if (!(await config.checkProperties(properties))) { diff --git a/lib/util/util.js b/lib/util/util.js index 18c99b2d2..9394f27f7 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -155,19 +155,24 @@ const Util = { * helper for {@link Mcdev.retrieve}, {@link Mcdev.retrieveAsTemplate} and {@link Mcdev.deploy} * * @param {TYPE.SupportedMetadataTypes} selectedType type or type-subtype + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method * @returns {boolean} type ok or not */ - _isValidType(selectedType) { + _isValidType(selectedType, handleOutside) { const [type, subType] = selectedType ? selectedType.split('-') : []; if (type && !MetadataDefinitions[type]) { - Util.logger.error(`:: '${type}' is not a valid metadata type`); + if (!handleOutside) { + Util.logger.error(`:: '${type}' is not a valid metadata type`); + } return false; } else if ( type && subType && (!MetadataDefinitions[type] || !MetadataDefinitions[type].subTypes.includes(subType)) ) { - Util.logger.error(`:: '${selectedType}' is not a valid metadata type`); + if (!handleOutside) { + Util.logger.error(`:: '${selectedType}' is not a valid metadata type`); + } return false; } return true; From 42199fdf9789c8f6764b50795e76ea2d37672cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Tue, 17 Jan 2023 14:57:18 +0100 Subject: [PATCH 046/132] #630: add TSD refresh logic to ensure changes to emails are getting picked up --- docs/dist/documentation.md | 21 ++++++++ lib/metadataTypes/TriggeredSendDefinition.js | 52 ++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 9a9742c1b..9c7af9dff 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -4889,6 +4889,8 @@ MessageSendActivity MetadataType * [.setFolderPath(metadata)](#TriggeredSendDefinition.setFolderPath) * [.parseMetadata(metadata)](#TriggeredSendDefinition.parseMetadata) ⇒ TYPE.MetadataTypeItem \| void * [.preDeployTasks(metadata)](#TriggeredSendDefinition.preDeployTasks) ⇒ TYPE.MetadataTypeItem + * [.refresh()](#TriggeredSendDefinition.refresh) ⇒ Promise.<void> + * [._refreshItem(key)](#TriggeredSendDefinition._refreshItem) ⇒ Promise.<void> @@ -4989,6 +4991,25 @@ prepares a TSD for deployment | --- | --- | --- | | metadata | TYPE.MetadataTypeItem | of a single TSD | + + +### TriggeredSendDefinition.refresh() ⇒ Promise.<void> +TSD-specific refresh method that finds active TSDs and refreshes them + +**Kind**: static method of [TriggeredSendDefinition](#TriggeredSendDefinition) +**Returns**: Promise.<void> - - + + +### TriggeredSendDefinition.\_refreshItem(key) ⇒ Promise.<void> +helper for [refresh](refresh) that pauses, publishes and starts a triggered send + +**Kind**: static method of [TriggeredSendDefinition](#TriggeredSendDefinition) +**Returns**: Promise.<void> - - + +| Param | Type | Description | +| --- | --- | --- | +| key | string | external key of triggered send item | + ## Retriever diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index 98177a1c6..708625c00 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -233,6 +233,58 @@ class TriggeredSendDefinition extends MetadataType { return metadata; } + /** + * TSD-specific refresh method that finds active TSDs and refreshes them + * + * @returns {Promise.} - + */ + static async refresh() { + // cache ACTIVE triggeredSends from the server + /** @type {TYPE.SoapRequestParams} */ + const requestParams = { + filter: { + leftOperand: 'TriggeredSendStatus', + operator: 'IN', + rightOperand: ['Active'], // Active=Running, Inactive=Paused + }, + }; + const metadata = (await super.retrieveSOAP(null, null, requestParams)).metadata; + + // then executes pause, publish, start on them. + const refreshList = []; + const keyList = Object.keys(metadata); + Util.logger.info(`Refreshing ${keyList.length} ${this.definition.typeName}...`); + Util.logger.debug(`Refreshing keys: ${keyList.join(', ')}`); + for (const key of Object.keys(metadata)) { + refreshList.push(this._refreshItem(key)); + } + await Promise.all(refreshList); + Util.logger.info(`Refresh done.`); + } + + /** + * helper for {@link refresh} that pauses, publishes and starts a triggered send + * + * @param {string} key external key of triggered send item + * @returns {Promise.} - + */ + static async _refreshItem(key) { + const item = {}; + item[this.definition.keyField] = key; + // pause + item.TriggeredSendStatus = 'Inactive'; + await this.update(item); + delete item.TriggeredSendStatus; + + // publish + item.RefreshContent = 'true'; + await this.update(item); + delete item.RefreshContent; + + // start + item.TriggeredSendStatus = 'Active'; + await this.update(item); + } } // Assign definition to static attributes From 63dd048a37b85afd0e6fba28fa9ea7f1f298181f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Tue, 17 Jan 2023 16:57:47 +0100 Subject: [PATCH 047/132] #630: Allow limiting refresh by given TSD keys --- docs/dist/documentation.md | 14 +++++--- lib/cli.js | 16 ++++----- lib/index.js | 5 +-- lib/metadataTypes/TriggeredSendDefinition.js | 34 +++++++++++--------- 4 files changed, 39 insertions(+), 30 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 9c7af9dff..0fcc778a2 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -473,7 +473,7 @@ main class * [.findBUs(credentialsName)](#Mcdev.findBUs) ⇒ Promise.<void> * [.document(businessUnit, type)](#Mcdev.document) ⇒ Promise.<void> * [.deleteByKey(businessUnit, type, customerKey, [version])](#Mcdev.deleteByKey) ⇒ Promise.<void> - * [.refresh(businessUnit, type)](#Mcdev.refresh) ⇒ Promise.<void> + * [.refresh(businessUnit, type, [keyArr])](#Mcdev.refresh) ⇒ Promise.<void> * [.badKeys(businessUnit)](#Mcdev.badKeys) ⇒ Promise.<void> * [.retrieveAsTemplate(businessUnit, selectedType, name, market)](#Mcdev.retrieveAsTemplate) ⇒ Promise.<TYPE.MultiMetadataTypeList> * [.buildTemplate(businessUnit, selectedType, keyArr, market)](#Mcdev.buildTemplate) ⇒ Promise.<TYPE.MultiMetadataTypeList> @@ -619,7 +619,7 @@ deletes metadata from MC instance by key -### Mcdev.refresh(businessUnit, type) ⇒ Promise.<void> +### Mcdev.refresh(businessUnit, type, [keyArr]) ⇒ Promise.<void> ensures triggered sends are restarted to ensure they pick up on changes of the underlying emails **Kind**: static method of [Mcdev](#Mcdev) @@ -629,6 +629,7 @@ ensures triggered sends are restarted to ensure they pick up on changes of the u | --- | --- | --- | | businessUnit | string | references credentials from properties.json | | type | string | references credentials from properties.json | +| [keyArr] | Array.<string> | metadata keys | @@ -4889,7 +4890,7 @@ MessageSendActivity MetadataType * [.setFolderPath(metadata)](#TriggeredSendDefinition.setFolderPath) * [.parseMetadata(metadata)](#TriggeredSendDefinition.parseMetadata) ⇒ TYPE.MetadataTypeItem \| void * [.preDeployTasks(metadata)](#TriggeredSendDefinition.preDeployTasks) ⇒ TYPE.MetadataTypeItem - * [.refresh()](#TriggeredSendDefinition.refresh) ⇒ Promise.<void> + * [.refresh([keyArr])](#TriggeredSendDefinition.refresh) ⇒ Promise.<void> * [._refreshItem(key)](#TriggeredSendDefinition._refreshItem) ⇒ Promise.<void> @@ -4993,11 +4994,16 @@ prepares a TSD for deployment -### TriggeredSendDefinition.refresh() ⇒ Promise.<void> +### TriggeredSendDefinition.refresh([keyArr]) ⇒ Promise.<void> TSD-specific refresh method that finds active TSDs and refreshes them **Kind**: static method of [TriggeredSendDefinition](#TriggeredSendDefinition) **Returns**: Promise.<void> - - + +| Param | Type | Description | +| --- | --- | --- | +| [keyArr] | Array.<string> | metadata keys | + ### TriggeredSendDefinition.\_refreshItem(key) ⇒ Promise.<void> diff --git a/lib/cli.js b/lib/cli.js index 5e822bd4d..6fe45e267 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -225,9 +225,7 @@ yargs handler: (argv) => { Mcdev.setSkipInteraction(argv.skipInteraction); Mcdev.setLoggingLevel(argv); - const keyArr = csvToArray(argv.KEY); - - Mcdev.buildTemplate(argv.BU, argv.TYPE, keyArr, argv.MARKET); + Mcdev.buildTemplate(argv.BU, argv.TYPE, csvToArray(argv.KEY), argv.MARKET); }, }) .command({ @@ -349,13 +347,11 @@ yargs handler: (argv) => { Mcdev.setSkipInteraction(argv.skipInteraction); Mcdev.setLoggingLevel(argv); - const keyArr = csvToArray(argv.KEY); - - Mcdev.getFilesToCommit(argv.BU, argv.TYPE, keyArr); + Mcdev.getFilesToCommit(argv.BU, argv.TYPE, csvToArray(argv.KEY)); }, }) .command({ - command: 'refresh [TYPE]', + command: 'refresh [TYPE] [KEY]', aliases: ['re'], desc: 'ensures that updates are properly published', builder: (yargs) => { @@ -367,12 +363,16 @@ yargs .positional('TYPE', { type: 'string', describe: 'metadata type', + }) + .positional('KEY', { + type: 'string', + describe: 'key(s) of the metadata component(s)', }); }, handler: (argv) => { Mcdev.setSkipInteraction(argv.skipInteraction); Mcdev.setLoggingLevel(argv); - Mcdev.refresh(argv.BU, argv.TYPE); + Mcdev.refresh(argv.BU, argv.TYPE, csvToArray(argv.KEY)); }, }) .command({ diff --git a/lib/index.js b/lib/index.js index 3e0ebbdd5..761148ac4 100644 --- a/lib/index.js +++ b/lib/index.js @@ -389,9 +389,10 @@ class Mcdev { * * @param {string} businessUnit references credentials from properties.json * @param {string} type references credentials from properties.json + * @param {string[]} [keyArr] metadata keys * @returns {Promise.} - */ - static async refresh(businessUnit, type) { + static async refresh(businessUnit, type, keyArr) { Util.logger.info('mcdev:: refresh'); if (!type || !Util._isValidType(type, true)) { type = 'triggeredSendDefinition'; @@ -412,7 +413,7 @@ class Mcdev { try { MetadataTypeInfo[type].properties = properties; MetadataTypeInfo[type].buObject = buObject; - await MetadataTypeInfo[type].refresh(); + await MetadataTypeInfo[type].refresh(keyArr); } catch (ex) { Util.logger.error('mcdev.refresh ' + ex.message); } diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index 708625c00..8c5d9140e 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -236,26 +236,28 @@ class TriggeredSendDefinition extends MetadataType { /** * TSD-specific refresh method that finds active TSDs and refreshes them * + * @param {string[]} [keyArr] metadata keys * @returns {Promise.} - */ - static async refresh() { - // cache ACTIVE triggeredSends from the server - /** @type {TYPE.SoapRequestParams} */ - const requestParams = { - filter: { - leftOperand: 'TriggeredSendStatus', - operator: 'IN', - rightOperand: ['Active'], // Active=Running, Inactive=Paused - }, - }; - const metadata = (await super.retrieveSOAP(null, null, requestParams)).metadata; - + static async refresh(keyArr) { + if (!keyArr) { + // cache ACTIVE triggeredSends from the server + /** @type {TYPE.SoapRequestParams} */ + const requestParams = { + filter: { + leftOperand: 'TriggeredSendStatus', + operator: 'IN', + rightOperand: ['Active'], // Active=Running, Inactive=Paused + }, + }; + const metadata = (await super.retrieveSOAP(null, null, requestParams)).metadata; + keyArr = Object.keys(metadata); + } // then executes pause, publish, start on them. const refreshList = []; - const keyList = Object.keys(metadata); - Util.logger.info(`Refreshing ${keyList.length} ${this.definition.typeName}...`); - Util.logger.debug(`Refreshing keys: ${keyList.join(', ')}`); - for (const key of Object.keys(metadata)) { + Util.logger.info(`Refreshing ${keyArr.length} ${this.definition.typeName}...`); + Util.logger.debug(`Refreshing keys: ${keyArr.join(', ')}`); + for (const key of keyArr) { refreshList.push(this._refreshItem(key)); } await Promise.all(refreshList); From 95aaec78a2c14563a6a708e5c7438b2bc4e4b2f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 18 Jan 2023 11:01:57 +0100 Subject: [PATCH 048/132] #630: equalize retrieveAsCache's params across classes --- docs/dist/documentation.md | 60 ++++++++++--------- lib/Deployer.js | 6 +- lib/Retriever.js | 9 ++- lib/metadataTypes/Asset.js | 17 +++--- lib/metadataTypes/DataExtension.js | 2 +- lib/metadataTypes/Folder.js | 16 ++--- lib/metadataTypes/List.js | 2 +- lib/metadataTypes/MetadataType.js | 17 +++--- .../definitions/Folder.definition.js | 30 ++++++++++ 9 files changed, 101 insertions(+), 58 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 48dd837c9..b3499e4eb 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -827,8 +827,8 @@ FileTransfer MetadataType **Extends**: [MetadataType](#MetadataType) * [Asset](#Asset) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, _, __, [selectedSubType], [key])](#Asset.retrieve) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> - * [.retrieveForCache(_, [selectedSubType])](#Asset.retrieveForCache) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> + * [.retrieve(retrieveDir, _, __, [subTypeArr], [key])](#Asset.retrieve) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> + * [.retrieveForCache(_, __, [subTypeArr])](#Asset.retrieveForCache) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> * [.retrieveAsTemplate(templateDir, name, templateVariables, [selectedSubType])](#Asset.retrieveAsTemplate) ⇒ Promise.<{metadata: TYPE.AssetItem, type: string}> * [.create(metadata)](#Asset.create) ⇒ Promise * [.update(metadata)](#Asset.update) ⇒ Promise @@ -855,7 +855,7 @@ FileTransfer MetadataType -### Asset.retrieve(retrieveDir, _, __, [selectedSubType], [key]) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> +### Asset.retrieve(retrieveDir, _, __, [subTypeArr], [key]) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> Retrieves Metadata of Asset **Kind**: static method of [Asset](#Asset) @@ -866,12 +866,12 @@ Retrieves Metadata of Asset | retrieveDir | string | Directory where retrieved metadata directory will be saved | | _ | void | - | | __ | void | - | -| [selectedSubType] | TYPE.AssetSubType | optionally limit to a single subtype | +| [subTypeArr] | Array.<TYPE.AssetSubType> | optionally limit to a single subtype | | [key] | string | customer key | -### Asset.retrieveForCache(_, [selectedSubType]) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> +### Asset.retrieveForCache(_, __, [subTypeArr]) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> Retrieves asset metadata for caching **Kind**: static method of [Asset](#Asset) @@ -879,8 +879,9 @@ Retrieves asset metadata for caching | Param | Type | Description | | --- | --- | --- | -| _ | void | - | -| [selectedSubType] | string | optionally limit to a single subtype | +| _ | void | unused | +| __ | void | unused | +| [subTypeArr] | Array.<string> | optionally limit to a single subtype | @@ -2614,8 +2615,8 @@ Folder MetadataType **Extends**: [MetadataType](#MetadataType) * [Folder](#Folder) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [additionalFields], buObject, [___], [key], [contentTypeList])](#Folder.retrieve) ⇒ Promise - * [.retrieveForCache(buObject, [contentTypeList])](#Folder.retrieveForCache) ⇒ Promise + * [.retrieve(retrieveDir, [additionalFields], buObject, [subTypeArr], [key])](#Folder.retrieve) ⇒ Promise + * [.retrieveForCache(buObject, _, [subTypeArr])](#Folder.retrieveForCache) ⇒ Promise * [.upsert(metadata)](#Folder.upsert) ⇒ Promise.<object> * [.create(metadataEntry)](#Folder.create) ⇒ Promise * [.update(metadataEntry)](#Folder.update) ⇒ Promise @@ -2627,7 +2628,7 @@ Folder MetadataType -### Folder.retrieve(retrieveDir, [additionalFields], buObject, [___], [key], [contentTypeList]) ⇒ Promise +### Folder.retrieve(retrieveDir, [additionalFields], buObject, [subTypeArr], [key]) ⇒ Promise Retrieves metadata of metadata type into local filesystem. executes callback with retrieved metadata **Kind**: static method of [Folder](#Folder) @@ -2638,13 +2639,12 @@ Retrieves metadata of metadata type into local filesystem. executes callback wit | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [additionalFields] | Array.<string> | Returns specified fields even if their retrieve definition is not set to true | | buObject | TYPE.BuObject | properties for auth | -| [___] | void | unused parameter | +| [subTypeArr] | Array.<string> | content type of folder | | [key] | string | customer key of single item to retrieve | -| [contentTypeList] | Array.<string> | content type of folder | -### Folder.retrieveForCache(buObject, [contentTypeList]) ⇒ Promise +### Folder.retrieveForCache(buObject, _, [subTypeArr]) ⇒ Promise Retrieves folder metadata for caching **Kind**: static method of [Folder](#Folder) @@ -2653,7 +2653,8 @@ Retrieves folder metadata for caching | Param | Type | Description | | --- | --- | --- | | buObject | TYPE.BuObject | properties for auth | -| [contentTypeList] | Array.<string> | content type of folder | +| _ | void | unused | +| [subTypeArr] | Array.<string> | content type of folder | @@ -3135,9 +3136,9 @@ Provides default functionality that can be overwritten by child metadata type cl * [.postRetrieveTasks(metadata, targetDir, [isTemplating])](#MetadataType.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.setFolderPath(metadata)](#MetadataType.setFolderPath) * [.setFolderId(metadata)](#MetadataType.setFolderId) - * [.retrieve(retrieveDir, [additionalFields], buObject, [subType], [key])](#MetadataType.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [.retrieveChangelog([buObject], [additionalFields], [subType])](#MetadataType.retrieveChangelog) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [.retrieveForCache(buObject, [subType])](#MetadataType.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [additionalFields], buObject, [subTypeArr], [key])](#MetadataType.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieveChangelog([buObject], [additionalFields], [subTypeArr])](#MetadataType.retrieveChangelog) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieveForCache(buObject, [additionalFields], [subTypeArr])](#MetadataType.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveAsTemplate(templateDir, name, templateVariables, [subType])](#MetadataType.retrieveAsTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.buildTemplate(retrieveDir, templateDir, key, templateVariables)](#MetadataType.buildTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.preDeployTasks(metadata, deployDir, buObject)](#MetadataType.preDeployTasks) ⇒ Promise.<TYPE.MetadataTypeItem> @@ -3170,7 +3171,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.findSubType(templateDir, templateName)](#MetadataType.findSubType) ⇒ Promise.<string> * [.readSecondaryFolder(templateDir, typeDirArr, templateName, fileName, ex)](#MetadataType.readSecondaryFolder) ⇒ object * [.buildDefinition(templateDir, targetDir, templateName, variables)](#MetadataType.buildDefinition) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [.checkForErrors(ex)](#MetadataType.checkForErrors) ⇒ Array.<string> + * [.checkForErrors(ex)](#MetadataType.checkForErrors) ⇒ Array.<string> \| void * [.document([buObject], [metadata], [isDeploy])](#MetadataType.document) ⇒ void * [.deleteByKey(buObject, customerKey, [version])](#MetadataType.deleteByKey) ⇒ boolean * [.postDeleteTasks(buObject, customerKey)](#MetadataType.postDeleteTasks) ⇒ void @@ -3285,7 +3286,7 @@ generic script that retrieves the folder ID from cache and updates the given met -### MetadataType.retrieve(retrieveDir, [additionalFields], buObject, [subType], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### MetadataType.retrieve(retrieveDir, [additionalFields], buObject, [subTypeArr], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Gets metadata from Marketing Cloud **Kind**: static method of [MetadataType](#MetadataType) @@ -3296,12 +3297,12 @@ Gets metadata from Marketing Cloud | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [additionalFields] | Array.<string> | Returns specified fields even if their retrieve definition is not set to true | | buObject | TYPE.BuObject | properties for auth | -| [subType] | string | optionally limit to a single subtype | +| [subTypeArr] | Array.<string> | optionally limit to a single subtype | | [key] | string | customer key of single item to retrieve | -### MetadataType.retrieveChangelog([buObject], [additionalFields], [subType]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### MetadataType.retrieveChangelog([buObject], [additionalFields], [subTypeArr]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Gets metadata from Marketing Cloud **Kind**: static method of [MetadataType](#MetadataType) @@ -3311,11 +3312,11 @@ Gets metadata from Marketing Cloud | --- | --- | --- | | [buObject] | TYPE.BuObject | properties for auth | | [additionalFields] | Array.<string> | Returns specified fields even if their retrieve definition is not set to true | -| [subType] | string | optionally limit to a single subtype | +| [subTypeArr] | Array.<string> | optionally limit to a single subtype | -### MetadataType.retrieveForCache(buObject, [subType]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### MetadataType.retrieveForCache(buObject, [additionalFields], [subTypeArr]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Gets metadata cache with limited fields and does not store value to disk **Kind**: static method of [MetadataType](#MetadataType) @@ -3324,7 +3325,8 @@ Gets metadata cache with limited fields and does not store value to disk | Param | Type | Description | | --- | --- | --- | | buObject | TYPE.BuObject | properties for auth | -| [subType] | string | optionally limit to a single subtype | +| [additionalFields] | Array.<string> | Returns specified fields even if their retrieve definition is not set to true | +| [subTypeArr] | Array.<string> | optionally limit to a single subtype | @@ -3775,11 +3777,11 @@ parsing is required (for example scripts & queries) -### MetadataType.checkForErrors(ex) ⇒ Array.<string> +### MetadataType.checkForErrors(ex) ⇒ Array.<string> \| void Standardizes a check for multiple messages **Kind**: static method of [MetadataType](#MetadataType) -**Returns**: Array.<string> - formatted Error Message +**Returns**: Array.<string> \| void - formatted Error Message | Param | Type | Description | | --- | --- | --- | @@ -4880,7 +4882,7 @@ MessageSendActivity MetadataType * [.deleteByKey(buObject, customerKey)](#TriggeredSendDefinition.deleteByKey) ⇒ Promise.<boolean> * [.postRetrieveTasks(metadata)](#TriggeredSendDefinition.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.setFolderPath(metadata)](#TriggeredSendDefinition.setFolderPath) - * [.parseMetadata(metadata)](#TriggeredSendDefinition.parseMetadata) ⇒ TYPE.MetadataTypeItem + * [.parseMetadata(metadata)](#TriggeredSendDefinition.parseMetadata) ⇒ TYPE.MetadataTypeItem \| void * [.preDeployTasks(metadata)](#TriggeredSendDefinition.preDeployTasks) ⇒ TYPE.MetadataTypeItem @@ -4961,11 +4963,11 @@ generic script that retrieves the folder path from cache and updates the given m -### TriggeredSendDefinition.parseMetadata(metadata) ⇒ TYPE.MetadataTypeItem +### TriggeredSendDefinition.parseMetadata(metadata) ⇒ TYPE.MetadataTypeItem \| void parses retrieved Metadata before saving **Kind**: static method of [TriggeredSendDefinition](#TriggeredSendDefinition) -**Returns**: TYPE.MetadataTypeItem - Array with one metadata object and one sql string +**Returns**: TYPE.MetadataTypeItem \| void - Array with one metadata object and one sql string | Param | Type | Description | | --- | --- | --- | diff --git a/lib/Deployer.js b/lib/Deployer.js index 08aa90519..f85769e4f 100644 --- a/lib/Deployer.js +++ b/lib/Deployer.js @@ -252,7 +252,11 @@ class Deployer { MetadataTypeInfo[type].properties = this.properties; MetadataTypeInfo[type].buObject = this.buObject; Util.logger.info('Caching dependent Metadata: ' + metadataType); - const result = await MetadataTypeInfo[type].retrieveForCache(this.buObject, subType); + const result = await MetadataTypeInfo[type].retrieveForCache( + this.buObject, + null, + subType ? [subType] : null + ); cache.setMetadata(type, result.metadata); } /** @type {TYPE.MultiMetadataTypeMap} */ diff --git a/lib/Retriever.js b/lib/Retriever.js index 08083d86a..fb70fe560 100644 --- a/lib/Retriever.js +++ b/lib/Retriever.js @@ -83,7 +83,11 @@ class Retriever { continue; } Util.logger.info(`Caching dependent Metadata: ${metadataType}`); - result = await MetadataTypeInfo[type].retrieveForCache(this.buObject, subType); + result = await MetadataTypeInfo[type].retrieveForCache( + this.buObject, + null, + subType ? [subType] : null + ); } else if (templateVariables) { Util.logger.info(`Retrieving as Template: ${metadataType}`); @@ -108,7 +112,8 @@ class Retriever { Util.logger.info(`Caching dependent Metadata: ${metadataType}`); cacheResult = await MetadataTypeInfo[type].retrieveForCache( this.buObject, - subType + null, + subType ? [subType] : null ); } Util.logger.info( diff --git a/lib/metadataTypes/Asset.js b/lib/metadataTypes/Asset.js index 116ac0f5b..1b2eda36f 100644 --- a/lib/metadataTypes/Asset.js +++ b/lib/metadataTypes/Asset.js @@ -20,16 +20,16 @@ class Asset extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} _ - * @param {void} __ - - * @param {TYPE.AssetSubType} [selectedSubType] optionally limit to a single subtype + * @param {TYPE.AssetSubType[]} [subTypeArr] optionally limit to a single subtype * @param {string} [key] customer key * @returns {Promise.<{metadata: TYPE.AssetMap, type: string}>} Promise */ - static async retrieve(retrieveDir, _, __, selectedSubType, key) { + static async retrieve(retrieveDir, _, __, subTypeArr, key) { const items = []; - const subTypes = selectedSubType ? [selectedSubType] : this._getSubTypes(); + subTypeArr = subTypeArr || this._getSubTypes(); await File.initPrettier(); // loop through subtypes and return results of each subType for caching (saving is handled per subtype) - for (const subType of subTypes) { + for (const subType of subTypeArr) { // each subtype contains multiple different specific types (images contains jpg and png for example) // we use await here to limit the risk of too many concurrent api requests at time items.push( @@ -55,12 +55,13 @@ class Asset extends MetadataType { /** * Retrieves asset metadata for caching * - * @param {void} _ - - * @param {string} [selectedSubType] optionally limit to a single subtype + * @param {void} _ unused + * @param {void} __ unused + * @param {string[]} [subTypeArr] optionally limit to a single subtype * @returns {Promise.<{metadata: TYPE.AssetMap, type: string}>} Promise */ - static retrieveForCache(_, selectedSubType) { - return this.retrieve(null, null, null, selectedSubType); + static retrieveForCache(_, __, subTypeArr) { + return this.retrieve(null, null, null, subTypeArr); } /** diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index 09324197e..5fae2595a 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -360,7 +360,7 @@ class DataExtension extends MetadataType { Util.logger.info(' - Caching dependent Metadata: folder (shared via _ParentBU_)'); Folder.client = this.client; Folder.properties = this.properties; - const result = await Folder.retrieveForCache(buObjectParentBu, [ + const result = await Folder.retrieveForCache(buObjectParentBu, null, [ 'shared_data', 'synchronizeddataextension', 'salesforcedataextension', diff --git a/lib/metadataTypes/Folder.js b/lib/metadataTypes/Folder.js index a4ac1f614..bc8fb8fff 100644 --- a/lib/metadataTypes/Folder.js +++ b/lib/metadataTypes/Folder.js @@ -19,20 +19,19 @@ class Folder extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true * @param {TYPE.BuObject} buObject properties for auth - * @param {void} [___] unused parameter + * @param {string[]} [subTypeArr] content type of folder * @param {string} [key] customer key of single item to retrieve - * @param {string[]} [contentTypeList] content type of folder * @returns {Promise} Promise */ - static async retrieve(retrieveDir, additionalFields, buObject, ___, key, contentTypeList) { + static async retrieve(retrieveDir, additionalFields, buObject, subTypeArr, key) { if (key) { Util.logger.error(`Folder.retrieve() does not support key parameter`); } - const queryAllFolders = await this.retrieveHelper(additionalFields, true, contentTypeList); + const queryAllFolders = await this.retrieveHelper(additionalFields, true, subTypeArr); if (buObject.eid !== buObject.mid) { queryAllFolders.push( - ...(await this.retrieveHelper(additionalFields, false, contentTypeList)) + ...(await this.retrieveHelper(additionalFields, false, subTypeArr)) ); } const sortPairs = toposort(queryAllFolders.map((a) => [a.ParentFolder.ID, a.ID])); @@ -153,11 +152,12 @@ class Folder extends MetadataType { * Retrieves folder metadata for caching * * @param {TYPE.BuObject} buObject properties for auth - * @param {string[]} [contentTypeList] content type of folder + * @param {void} _ unused + * @param {string[]} [subTypeArr] content type of folder * @returns {Promise} Promise */ - static retrieveForCache(buObject, contentTypeList) { - return this.retrieve(null, null, buObject, null, null, contentTypeList); + static retrieveForCache(buObject, _, subTypeArr) { + return this.retrieve(null, null, buObject, subTypeArr, null); } /** diff --git a/lib/metadataTypes/List.js b/lib/metadataTypes/List.js index a13146000..7a29b969e 100644 --- a/lib/metadataTypes/List.js +++ b/lib/metadataTypes/List.js @@ -60,7 +60,7 @@ class List extends MetadataType { Util.logger.info(' - Caching dependent Metadata: folder'); Folder.client = this.client; Folder.properties = this.properties; - const result = await Folder.retrieveForCache(buObject, [ + const result = await Folder.retrieveForCache(buObject, null, [ 'list', 'mysubs', 'suppression_list', diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index dc1093af4..2241e1096 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -190,11 +190,11 @@ class MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true * @param {TYPE.BuObject} buObject properties for auth - * @param {string} [subType] optionally limit to a single subtype + * @param {string[]} [subTypeArr] optionally limit to a single subtype * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} metadata */ - static retrieve(retrieveDir, additionalFields, buObject, subType, key) { + static retrieve(retrieveDir, additionalFields, buObject, subTypeArr, key) { Util.metadataLogger('error', this.definition.type, 'retrieve', `Not Supported`); const metadata = {}; return { metadata: null, type: this.definition.type }; @@ -204,22 +204,23 @@ class MetadataType { * * @param {TYPE.BuObject} [buObject] properties for auth * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @param {string} [subType] optionally limit to a single subtype + * @param {string[]} [subTypeArr] optionally limit to a single subtype * @returns {Promise.} metadata */ - static retrieveChangelog(buObject, additionalFields, subType) { - return this.retrieveForCache(buObject, subType); + static retrieveChangelog(buObject, additionalFields, subTypeArr) { + return this.retrieveForCache(buObject, subTypeArr); } /** * Gets metadata cache with limited fields and does not store value to disk * * @param {TYPE.BuObject} buObject properties for auth - * @param {string} [subType] optionally limit to a single subtype + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @param {string[]} [subTypeArr] optionally limit to a single subtype * @returns {Promise.} metadata */ - static async retrieveForCache(buObject, subType) { - return this.retrieve(null, null, buObject, subType); + static async retrieveForCache(buObject, additionalFields, subTypeArr) { + return this.retrieve(null, additionalFields, buObject, subTypeArr); } /** * Gets metadata cache with limited fields and does not store value to disk diff --git a/lib/metadataTypes/definitions/Folder.definition.js b/lib/metadataTypes/definitions/Folder.definition.js index f0e6b0d2d..97e01b2e4 100644 --- a/lib/metadataTypes/definitions/Folder.definition.js +++ b/lib/metadataTypes/definitions/Folder.definition.js @@ -1,6 +1,36 @@ module.exports = { bodyIteratorField: 'Results', dependencies: [], + subTypes: [ + 'asset-shared', + 'asset', + 'contextual_suppression_list', + 'dataextension', + 'filteractivity', + 'filterdefinition', + 'journey', + 'list', + 'mysubs', + 'mysubs', + 'publication', + 'queryactivity', + 'salesforcedataextension', + 'shared_content', + 'shared_data', + 'shared_dataextension', + 'shared_email', + 'shared_item', + 'shared_portfolio', + 'shared_publication', + 'shared_salesforcedataextension', + 'shared_suppression_list', + 'shared_template', + 'ssjsactivity', + 'suppression_list', + 'synchronizeddataextension', + 'triggered_send_journeybuilder', + 'triggered_send', + ], deployFolderTypes: [ // lower-case values! 'asset', From 7fece46a081918521eeb8b8c754dcd105e043b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 18 Jan 2023 11:05:47 +0100 Subject: [PATCH 049/132] #636: jsdoc eslint warning fixes --- lib/metadataTypes/Asset.js | 2 +- lib/metadataTypes/MetadataType.js | 2 +- lib/metadataTypes/TriggeredSendDefinition.js | 2 +- lib/util/util.js | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/metadataTypes/Asset.js b/lib/metadataTypes/Asset.js index 1b2eda36f..2e23b5a8e 100644 --- a/lib/metadataTypes/Asset.js +++ b/lib/metadataTypes/Asset.js @@ -608,7 +608,7 @@ class Asset extends MetadataType { * * @private * @param {TYPE.AssetItem} metadata a single asset - * @returns {TYPE.AssetSubType} subtype + * @returns {TYPE.AssetSubType | void} subtype */ static _getSubtype(metadata) { for (const sub in this.definition.extendedSubTypes) { diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 2241e1096..145208993 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -1518,7 +1518,7 @@ class MetadataType { * Standardizes a check for multiple messages * * @param {object} ex response payload from REST API - * @returns {string[]} formatted Error Message + * @returns {string[] | void} formatted Error Message */ static checkForErrors(ex) { if (ex?.response?.status >= 400 && ex?.response?.status < 600) { diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index c2983ee07..ffdd54487 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -117,7 +117,7 @@ class TriggeredSendDefinition extends MetadataType { * parses retrieved Metadata before saving * * @param {TYPE.MetadataTypeItem} metadata a single query activity definition - * @returns {TYPE.MetadataTypeItem} Array with one metadata object and one sql string + * @returns {TYPE.MetadataTypeItem | void} Array with one metadata object and one sql string */ static parseMetadata(metadata) { // remove IsPlatformObject, always has to be 'false' diff --git a/lib/util/util.js b/lib/util/util.js index e7175cf08..18c99b2d2 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -161,14 +161,14 @@ const Util = { const [type, subType] = selectedType ? selectedType.split('-') : []; if (type && !MetadataDefinitions[type]) { Util.logger.error(`:: '${type}' is not a valid metadata type`); - return; + return false; } else if ( type && subType && (!MetadataDefinitions[type] || !MetadataDefinitions[type].subTypes.includes(subType)) ) { Util.logger.error(`:: '${selectedType}' is not a valid metadata type`); - return; + return false; } return true; }, From 0516c27dfc78777e8d6e3a24d4449a8c926e8bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 18 Jan 2023 13:50:35 +0100 Subject: [PATCH 050/132] #636: ensure subtypes are passed to retrieveForCache as a list instead of 1-by-1 --- docs/dist/documentation.md | 12 ++++++------ lib/Deployer.js | 11 ++++++----- lib/Retriever.js | 20 ++++++++++++-------- lib/util/util.js | 25 +++++++++++++++++++++---- 4 files changed, 45 insertions(+), 23 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index b3499e4eb..2860b5a7e 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -5058,7 +5058,7 @@ CLI entry for SFMC DevTools * [.metadataLogger(level, type, method, payload, [source])](#Util.metadataLogger) ⇒ void * [.replaceByObject(str, obj)](#Util.replaceByObject) ⇒ string \| object * [.inverseGet(objs, val)](#Util.inverseGet) ⇒ string - * [.getMetadataHierachy(metadataTypes)](#Util.getMetadataHierachy) ⇒ Array.<string> + * [.getMetadataHierachy(metadataTypes)](#Util.getMetadataHierachy) ⇒ Object.<string, Array.<string>> * [.resolveObjPath(path, obj)](#Util.resolveObjPath) ⇒ any * [.execSync(cmd, [args], [hideOutput])](#Util.execSync) ⇒ string * [.templateSearchResult(results, keyToSearch, searchValue)](#Util.templateSearchResult) ⇒ TYPE.MetadataTypeItem @@ -5232,11 +5232,11 @@ get key of an object based on the first matching value -### Util.getMetadataHierachy(metadataTypes) ⇒ Array.<string> +### Util.getMetadataHierachy(metadataTypes) ⇒ Object.<string, Array.<string>> Returns Order in which metadata needs to be retrieved/deployed **Kind**: static method of [Util](#Util) -**Returns**: Array.<string> - retrieve/deploy order as array +**Returns**: Object.<string, Array.<string>> - retrieve/deploy order as array | Param | Type | Description | | --- | --- | --- | @@ -6763,7 +6763,7 @@ Util that contains logger and simple util methods * [.metadataLogger(level, type, method, payload, [source])](#Util.metadataLogger) ⇒ void * [.replaceByObject(str, obj)](#Util.replaceByObject) ⇒ string \| object * [.inverseGet(objs, val)](#Util.inverseGet) ⇒ string - * [.getMetadataHierachy(metadataTypes)](#Util.getMetadataHierachy) ⇒ Array.<string> + * [.getMetadataHierachy(metadataTypes)](#Util.getMetadataHierachy) ⇒ Object.<string, Array.<string>> * [.resolveObjPath(path, obj)](#Util.resolveObjPath) ⇒ any * [.execSync(cmd, [args], [hideOutput])](#Util.execSync) ⇒ string * [.templateSearchResult(results, keyToSearch, searchValue)](#Util.templateSearchResult) ⇒ TYPE.MetadataTypeItem @@ -6937,11 +6937,11 @@ get key of an object based on the first matching value -### Util.getMetadataHierachy(metadataTypes) ⇒ Array.<string> +### Util.getMetadataHierachy(metadataTypes) ⇒ Object.<string, Array.<string>> Returns Order in which metadata needs to be retrieved/deployed **Kind**: static method of [Util](#Util) -**Returns**: Array.<string> - retrieve/deploy order as array +**Returns**: Object.<string, Array.<string>> - retrieve/deploy order as array | Param | Type | Description | | --- | --- | --- | diff --git a/lib/Deployer.js b/lib/Deployer.js index f85769e4f..ffcfca25f 100644 --- a/lib/Deployer.js +++ b/lib/Deployer.js @@ -245,8 +245,9 @@ class Deployer { ); const deployOrder = Util.getMetadataHierachy(foundDeployTypes); // build cache, including all metadata types which will be deployed (Avoids retrieve later) - for (const metadataType of deployOrder) { - const [type, subType] = metadataType.split('-'); + for (const metadataType in deployOrder) { + const type = metadataType; + const subTypeArr = deployOrder[metadataType]; // add metadata & client to metadata process class instead of passing cache/mapping every time MetadataTypeInfo[type].client = auth.getSDK(this.buObject); MetadataTypeInfo[type].properties = this.properties; @@ -255,17 +256,17 @@ class Deployer { const result = await MetadataTypeInfo[type].retrieveForCache( this.buObject, null, - subType ? [subType] : null + subTypeArr ); cache.setMetadata(type, result.metadata); } /** @type {TYPE.MultiMetadataTypeMap} */ const multiMetadataTypeMap = {}; // deploy metadata files, extending cache once deploys - for (const metadataType of deployOrder) { + for (const metadataType in deployOrder) { // TODO rewrite to allow deploying only a specific sub-type // const [type, subType] = metadataType.split('-'); - const type = metadataType.split('-')[0]; + const type = metadataType; if (this.metadata[type]) { Util.logger.info('Deploying: ' + metadataType); diff --git a/lib/Retriever.js b/lib/Retriever.js index fb70fe560..129f88c9c 100644 --- a/lib/Retriever.js +++ b/lib/Retriever.js @@ -66,9 +66,10 @@ class Retriever { }; // ensure we know which real dependencies we have to ensure we cache those completely const dependencies = this._getTypeDependencies(metadataTypes); - - for (const metadataType of Util.getMetadataHierachy(metadataTypes)) { - const [type, subType] = metadataType.split('-'); + const deployOrder = Util.getMetadataHierachy(metadataTypes); + for (const metadataType in deployOrder) { + const type = metadataType; + const subTypeArr = deployOrder[metadataType]; // if types were added by getMetadataHierachy() for caching, make sure the key-list is set to [null] for them which will retrieve all typeKeyMap[metadataType] = typeKeyMap[metadataType] || [null]; // add client to metadata process class instead of passing every time @@ -78,6 +79,7 @@ class Retriever { try { let result; if (!metadataTypes.includes(type) && !metadataTypes.includes(metadataType)) { + // type not in list of types to retrieve, but is a dependency of one of them if (changelogOnly && type !== 'folder') { // no extra caching needed for list view except for folders continue; @@ -86,9 +88,10 @@ class Retriever { result = await MetadataTypeInfo[type].retrieveForCache( this.buObject, null, - subType ? [subType] : null + subTypeArr ); } else if (templateVariables) { + // type is in list of types to retrieve and we have template variables Util.logger.info(`Retrieving as Template: ${metadataType}`); result = await Promise.all( @@ -97,11 +100,12 @@ class Retriever { this.templateDir, name, templateVariables, - subType + subTypeArr?.[0] // this might cause issues if one were to try to use the method with multiple subtypes ) ) ); } else { + // type is in list of types to retrieve and we don't have template variables let cacheResult = null; if ( (typeKeyMap[metadataType].length > 1 || @@ -113,7 +117,7 @@ class Retriever { cacheResult = await MetadataTypeInfo[type].retrieveForCache( this.buObject, null, - subType ? [subType] : null + subTypeArr ); } Util.logger.info( @@ -125,14 +129,14 @@ class Retriever { }`) ); result = await (changelogOnly - ? MetadataTypeInfo[type].retrieveChangelog(this.buObject, null, subType) + ? MetadataTypeInfo[type].retrieveChangelog(this.buObject, null, subTypeArr) : Promise.all( typeKeyMap[metadataType].map((key) => MetadataTypeInfo[type].retrieve( this.savePath, null, this.buObject, - subType, + subTypeArr, key ) ) diff --git a/lib/util/util.js b/lib/util/util.js index 18c99b2d2..653134e37 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -293,7 +293,7 @@ const Util = { * Returns Order in which metadata needs to be retrieved/deployed * * @param {string[]} metadataTypes which should be retrieved/deployed - * @returns {string[]} retrieve/deploy order as array + * @returns {Object.} retrieve/deploy order as array */ getMetadataHierachy(metadataTypes) { const dependencies = []; @@ -320,10 +320,11 @@ const Util = { dependencies.push([undefined, metadataType]); } } + const allDeps = dependencies.map((dep) => dep[0]); // remove subtypes if main type is in the list for (const type of Object.keys(subTypeDeps) - // only look at subtype deps that are also supposed to be retrieved fully - .filter((type) => metadataTypes.includes(type))) { + // only look at subtype deps that are also supposed to be retrieved or cached fully + .filter((type) => metadataTypes.includes(type) || allDeps.includes(type))) { // convert set into array to walk its elements for (const subType of subTypeDeps[type]) { for (const item of dependencies) { @@ -336,7 +337,23 @@ const Util = { } // sort list & remove the undefined dependencies - return toposort(dependencies).filter((a) => !!a); + const flatList = toposort(dependencies).filter((a) => !!a); + const finalList = {}; + // group subtypes per type + for (const type of flatList) { + if (type.includes('-')) { + const key = type.split('-')[0]; + if (finalList[key]) { + continue; + } + finalList[key] = subTypeDeps[key] + ? [...subTypeDeps[key]].map((a) => a.split('-')[1]) + : null; + } else { + finalList[type] = null; + } + } + return finalList; }, /** From c91194ef57c8b91610635afa0c2dd2844b2d3806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 18 Jan 2023 15:42:25 +0100 Subject: [PATCH 051/132] #636: centralize logging selected subtypes --- docs/dist/documentation.md | 50 ++++++++++++++++++++++++++++++ lib/Deployer.js | 3 +- lib/Retriever.js | 2 ++ lib/metadataTypes/DataExtension.js | 12 ++++--- lib/metadataTypes/List.js | 14 +++++---- lib/metadataTypes/MetadataType.js | 7 +---- lib/util/util.js | 20 ++++++++++++ 7 files changed, 90 insertions(+), 18 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 2860b5a7e..654e6e669 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -5063,6 +5063,8 @@ CLI entry for SFMC DevTools * [.execSync(cmd, [args], [hideOutput])](#Util.execSync) ⇒ string * [.templateSearchResult(results, keyToSearch, searchValue)](#Util.templateSearchResult) ⇒ TYPE.MetadataTypeItem * [.setLoggingLevel(argv)](#Util.setLoggingLevel) ⇒ void + * [.logSubtypes(subTypeArr)](#Util.logSubtypes) ⇒ void + * [.getKeysString(keyArr)](#Util.getKeysString) ⇒ string @@ -5297,6 +5299,29 @@ configures what is displayed in the console | [argv.verbose] | boolean | chatty user CLI output | | [argv.debug] | boolean | enables developer output & features | + + +### Util.logSubtypes(subTypeArr) ⇒ void +helper to print the subtypes we filtered by + +**Kind**: static method of [Util](#Util) + +| Param | Type | Description | +| --- | --- | --- | +| subTypeArr | Array.<string> | list of subtypes to be printed | + + + +### Util.getKeysString(keyArr) ⇒ string +helper to print the subtypes we filtered by + +**Kind**: static method of [Util](#Util) +**Returns**: string - string to be appended to log message + +| Param | Type | Description | +| --- | --- | --- | +| keyArr | Array.<string> \| string | list of subtypes to be printed | + ## MetadataTypeDefinitions @@ -6768,6 +6793,8 @@ Util that contains logger and simple util methods * [.execSync(cmd, [args], [hideOutput])](#Util.execSync) ⇒ string * [.templateSearchResult(results, keyToSearch, searchValue)](#Util.templateSearchResult) ⇒ TYPE.MetadataTypeItem * [.setLoggingLevel(argv)](#Util.setLoggingLevel) ⇒ void + * [.logSubtypes(subTypeArr)](#Util.logSubtypes) ⇒ void + * [.getKeysString(keyArr)](#Util.getKeysString) ⇒ string @@ -7002,6 +7029,29 @@ configures what is displayed in the console | [argv.verbose] | boolean | chatty user CLI output | | [argv.debug] | boolean | enables developer output & features | + + +### Util.logSubtypes(subTypeArr) ⇒ void +helper to print the subtypes we filtered by + +**Kind**: static method of [Util](#Util) + +| Param | Type | Description | +| --- | --- | --- | +| subTypeArr | Array.<string> | list of subtypes to be printed | + + + +### Util.getKeysString(keyArr) ⇒ string +helper to print the subtypes we filtered by + +**Kind**: static method of [Util](#Util) +**Returns**: string - string to be appended to log message + +| Param | Type | Description | +| --- | --- | --- | +| keyArr | Array.<string> \| string | list of subtypes to be printed | + ## csvToArray(csv) ⇒ Array.<string> diff --git a/lib/Deployer.js b/lib/Deployer.js index ffcfca25f..59a9cb699 100644 --- a/lib/Deployer.js +++ b/lib/Deployer.js @@ -252,7 +252,8 @@ class Deployer { MetadataTypeInfo[type].client = auth.getSDK(this.buObject); MetadataTypeInfo[type].properties = this.properties; MetadataTypeInfo[type].buObject = this.buObject; - Util.logger.info('Caching dependent Metadata: ' + metadataType); + Util.logger.info(`Caching dependent Metadata: ${metadataType}`); + Util.logSubtypes(subTypeArr); const result = await MetadataTypeInfo[type].retrieveForCache( this.buObject, null, diff --git a/lib/Retriever.js b/lib/Retriever.js index 129f88c9c..09bb1f0bf 100644 --- a/lib/Retriever.js +++ b/lib/Retriever.js @@ -85,6 +85,7 @@ class Retriever { continue; } Util.logger.info(`Caching dependent Metadata: ${metadataType}`); + Util.logSubtypes(subTypeArr); result = await MetadataTypeInfo[type].retrieveForCache( this.buObject, null, @@ -114,6 +115,7 @@ class Retriever { ) { // if we have a key-list and the type is a dependency, we need to cache the whole type Util.logger.info(`Caching dependent Metadata: ${metadataType}`); + Util.logSubtypes(subTypeArr); cacheResult = await MetadataTypeInfo[type].retrieveForCache( this.buObject, null, diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index 5fae2595a..4cdbb06da 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -357,16 +357,18 @@ class DataExtension extends MetadataType { const metadataParentBu = await this._retrieveAll(additionalFields); // get shared folders to match our shared / synched Data Extensions - Util.logger.info(' - Caching dependent Metadata: folder (shared via _ParentBU_)'); - Folder.client = this.client; - Folder.properties = this.properties; - const result = await Folder.retrieveForCache(buObjectParentBu, null, [ + const subTypeArr = [ 'shared_data', 'synchronizeddataextension', 'salesforcedataextension', 'shared_dataextension', 'dataextension', - ]); + ]; + Util.logger.info(' - Caching dependent Metadata: folder (shared via _ParentBU_)'); + Util.logSubtypes(subTypeArr); + Folder.client = this.client; + Folder.properties = this.properties; + const result = await Folder.retrieveForCache(buObjectParentBu, null, subTypeArr); cache.mergeMetadata('folder', result.metadata, buObject.eid); // get the types and clean out non-shared ones diff --git a/lib/metadataTypes/List.js b/lib/metadataTypes/List.js index 7a29b969e..988857c60 100644 --- a/lib/metadataTypes/List.js +++ b/lib/metadataTypes/List.js @@ -56,17 +56,19 @@ class List extends MetadataType { static async retrieveForCache(buObject) { const results = await this.retrieve(null, null, buObject); if (!cache.getCache()?.folder) { - Util.logger.debug('folders not cached but required for list'); - Util.logger.info(' - Caching dependent Metadata: folder'); - Folder.client = this.client; - Folder.properties = this.properties; - const result = await Folder.retrieveForCache(buObject, null, [ + const subTypeArr = [ 'list', 'mysubs', 'suppression_list', 'publication', 'contextual_suppression_list', - ]); + ]; + Util.logger.debug('folders not cached but required for list'); + Util.logger.info(' - Caching dependent Metadata: folder'); + Util.logSubtypes(subTypeArr); + Folder.client = this.client; + Folder.properties = this.properties; + const result = await Folder.retrieveForCache(buObject, null, subTypeArr); cache.setMetadata('folder', result.metadata); } for (const metadataEntry in results.metadata) { diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 145208993..2875217fb 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -807,11 +807,6 @@ class MetadataType { } if (retrieveDir) { - // defined colors for optionally printing the keys we filtered by - const color = { - reset: '\x1B[0m', - dim: '\x1B[2m', - }; const savedMetadata = await this.saveResults( results, retrieveDir, @@ -824,7 +819,7 @@ class MetadataType { })` + (singleRetrieve === null ? '' - : ` ${color.dim}(Key: ${singleRetrieve})${color.reset}`) + : ` ${Util.color.dim}(Key: ${singleRetrieve})${Util.color.reset}`) ); } diff --git a/lib/util/util.js b/lib/util/util.js index 653134e37..7b7e8d7ed 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -447,6 +447,26 @@ const Util = { Util.logger.debug('CLI logger set to: debug'); } }, + // defined colors for logging things in different colors + color: { + reset: '\x1B[0m', + dim: '\x1B[2m', + }, + /** + * helper to print the subtypes we filtered by + * + * @param {string[]} subTypeArr list of subtypes to be printed + * @returns {void} + */ + logSubtypes(subTypeArr) { + if (subTypeArr && subTypeArr.length > 0) { + Util.logger.info( + `${Util.color.dim} - Subtype${subTypeArr.length > 1 ? 's' : ''}: ${subTypeArr.join( + ', ' + )}${Util.color.reset}` + ); + } + }, }; /** * wrapper around our standard winston logging to console and logfile From 326b9fa517164324216459ff3b0477d542bd0baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 18 Jan 2023 15:47:04 +0100 Subject: [PATCH 052/132] #636: centralize logging selected keys --- lib/Retriever.js | 9 +-------- lib/metadataTypes/Asset.js | 3 ++- lib/metadataTypes/Automation.js | 3 ++- lib/metadataTypes/Campaign.js | 4 +++- lib/metadataTypes/DataExtension.js | 3 ++- lib/metadataTypes/MetadataType.js | 5 +---- lib/metadataTypes/Role.js | 3 ++- lib/metadataTypes/TransactionalMessage.js | 7 +------ lib/util/util.js | 21 +++++++++++++++++++++ 9 files changed, 35 insertions(+), 23 deletions(-) diff --git a/lib/Retriever.js b/lib/Retriever.js index 09bb1f0bf..f0de8d41b 100644 --- a/lib/Retriever.js +++ b/lib/Retriever.js @@ -59,11 +59,6 @@ class Retriever { // assuming TypeKeyCombo was provided typeKeyMap = namesOrKeys; } - // defined colors for optionally printing the keys we filtered by - const color = { - reset: '\x1B[0m', - dim: '\x1B[2m', - }; // ensure we know which real dependencies we have to ensure we cache those completely const dependencies = this._getTypeDependencies(metadataTypes); const deployOrder = Util.getMetadataHierachy(metadataTypes); @@ -126,9 +121,7 @@ class Retriever { `Retrieving: ${metadataType}` + (typeKeyMap[metadataType][0] === null ? '' - : ` ${color.dim}(Keys: ${typeKeyMap[metadataType].join(', ')})${ - color.reset - }`) + : Util.getKeysString(typeKeyMap[metadataType])) ); result = await (changelogOnly ? MetadataTypeInfo[type].retrieveChangelog(this.buObject, null, subTypeArr) diff --git a/lib/metadataTypes/Asset.js b/lib/metadataTypes/Asset.js index 2e23b5a8e..0fd329aa5 100644 --- a/lib/metadataTypes/Asset.js +++ b/lib/metadataTypes/Asset.js @@ -46,7 +46,8 @@ class Asset extends MetadataType { const metadata = this.parseResponseBody({ items: items }); if (retrieveDir) { Util.logger.info( - `Downloaded: ${this.definition.type} (${Object.keys(metadata).length})` + `Downloaded: ${this.definition.type} (${Object.keys(metadata).length})` + + Util.getKeysString(key) ); } return { metadata: metadata, type: this.definition.type }; diff --git a/lib/metadataTypes/Automation.js b/lib/metadataTypes/Automation.js index 453fede5b..7835217a5 100644 --- a/lib/metadataTypes/Automation.js +++ b/lib/metadataTypes/Automation.js @@ -49,7 +49,8 @@ class Automation extends MetadataType { // * retrieveDir is mandatory in this method as it is not used for caching (there is a seperate method for that) const savedMetadata = await this.saveResults(parsed, retrieveDir, null, null); Util.logger.info( - `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + + Util.getKeysString(key) ); if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) { await this.document(this.buObject, savedMetadata); diff --git a/lib/metadataTypes/Campaign.js b/lib/metadataTypes/Campaign.js index 62ccc8683..77283cd99 100644 --- a/lib/metadataTypes/Campaign.js +++ b/lib/metadataTypes/Campaign.js @@ -30,7 +30,9 @@ class Campaign extends MetadataType { this.getAssetTags(retrieveDir, res.metadata[key].id, key) ) ); - Util.logger.info(`Downloaded: campaignAssets (${campaignAssets.flat().length})`); + Util.logger.info( + `Downloaded: campaignAssets (${campaignAssets.flat().length})` + Util.getKeysString(key) + ); return res; } diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index 4cdbb06da..bb19286eb 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -408,7 +408,8 @@ class DataExtension extends MetadataType { if (retrieveDir) { const savedMetadata = await super.saveResults(metadata, retrieveDir, null); Util.logger.info( - `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + + Util.getKeysString(key) ); if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) { await this.document(buObject, savedMetadata); diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 2875217fb..ff2cfb8a0 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -816,10 +816,7 @@ class MetadataType { Util.logger.info( `Downloaded: ${overrideType || this.definition.type} (${ Object.keys(savedMetadata).length - })` + - (singleRetrieve === null - ? '' - : ` ${Util.color.dim}(Key: ${singleRetrieve})${Util.color.reset}`) + })` + Util.getKeysString(singleRetrieve) ); } diff --git a/lib/metadataTypes/Role.js b/lib/metadataTypes/Role.js index eb3b73996..8a0b419e1 100644 --- a/lib/metadataTypes/Role.js +++ b/lib/metadataTypes/Role.js @@ -67,7 +67,8 @@ class Role extends MetadataType { if (retrieveDir) { const savedMetadata = await super.saveResults(parsed, retrieveDir, null); Util.logger.info( - `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + + Util.getKeysString(key) ); if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) { await this.document(buObject, savedMetadata); diff --git a/lib/metadataTypes/TransactionalMessage.js b/lib/metadataTypes/TransactionalMessage.js index 67c22ee68..01879ee23 100644 --- a/lib/metadataTypes/TransactionalMessage.js +++ b/lib/metadataTypes/TransactionalMessage.js @@ -60,14 +60,9 @@ class TransactionalMessage extends MetadataType { // * retrieveDir is mandatory in this method as it is not used for caching (there is a seperate method for that) const savedMetadata = await this.saveResults(parsed, retrieveDir, null, null); - // defined colors for optionally printing the keys we filtered by - const color = { - reset: '\x1B[0m', - dim: '\x1B[2m', - }; Util.logger.info( `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + - (key === null ? '' : ` ${color.dim}(Key: ${key})${color.reset}`) + Util.getKeysString(key) ); return { metadata: savedMetadata, type: this.definition.type }; diff --git a/lib/util/util.js b/lib/util/util.js index 7b7e8d7ed..924dd85f6 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -467,6 +467,27 @@ const Util = { ); } }, + /** + * helper to print the subtypes we filtered by + * + * @param {string[] | string} keyArr list of subtypes to be printed + * @returns {string} string to be appended to log message + */ + getKeysString(keyArr) { + if (!keyArr) { + return ''; + } + if (!Array.isArray(keyArr)) { + // if only one key, make it an array + keyArr = [keyArr]; + } + if (keyArr.length > 0) { + return `${Util.color.dim} - Key${keyArr.length > 1 ? 's' : ''}: ${keyArr.join(', ')}${ + Util.color.reset + }`; + } + return ''; + }, }; /** * wrapper around our standard winston logging to console and logfile From 5a5b0a1557f163644c4ecd0b1c3fdbfbb321232a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 18 Jan 2023 16:05:44 +0100 Subject: [PATCH 053/132] #636: limit retrieved folders to whats absolutely necessary per type --- lib/metadataTypes/definitions/Asset.definition.js | 2 +- lib/metadataTypes/definitions/Automation.definition.js | 2 +- .../definitions/DataExtension.definition.js | 10 +++++++++- lib/metadataTypes/definitions/Email.definition.js | 2 +- .../definitions/EmailSendDefinition.definition.js | 2 +- lib/metadataTypes/definitions/ImportFile.definition.js | 2 +- .../definitions/Interaction.definition.js | 2 +- lib/metadataTypes/definitions/List.definition.js | 2 +- lib/metadataTypes/definitions/Query.definition.js | 2 +- lib/metadataTypes/definitions/Script.definition.js | 2 +- .../definitions/TriggeredSendDefinition.definition.js | 8 +++++++- 11 files changed, 25 insertions(+), 11 deletions(-) diff --git a/lib/metadataTypes/definitions/Asset.definition.js b/lib/metadataTypes/definitions/Asset.definition.js index 074a8880d..c763bb2c5 100644 --- a/lib/metadataTypes/definitions/Asset.definition.js +++ b/lib/metadataTypes/definitions/Asset.definition.js @@ -1,7 +1,7 @@ // asset types https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/base-asset-types.htm module.exports = { bodyIteratorField: 'items', - dependencies: ['folder'], + dependencies: ['folder-asset', 'folder-asset-shared'], folderType: 'asset', hasExtended: false, idField: 'id', diff --git a/lib/metadataTypes/definitions/Automation.definition.js b/lib/metadataTypes/definitions/Automation.definition.js index b380c9607..db53a2cdb 100644 --- a/lib/metadataTypes/definitions/Automation.definition.js +++ b/lib/metadataTypes/definitions/Automation.definition.js @@ -27,7 +27,7 @@ module.exports = { 'dataExtract', 'emailSendDefinition', 'fileTransfer', - 'folder', + 'folder-automations', 'importFile', 'query', 'script', diff --git a/lib/metadataTypes/definitions/DataExtension.definition.js b/lib/metadataTypes/definitions/DataExtension.definition.js index 1eda1ab02..c47574bd8 100644 --- a/lib/metadataTypes/definitions/DataExtension.definition.js +++ b/lib/metadataTypes/definitions/DataExtension.definition.js @@ -1,6 +1,14 @@ module.exports = { bodyIteratorField: 'Results', - dependencies: ['folder', 'dataExtensionTemplate'], + dependencies: [ + 'folder-dataextension', + 'folder-salesforcedataextension', + 'folder-shared_data', + 'folder-shared_dataextension', + 'folder-shared_salesforcedataextension', + 'folder-synchronizeddataextension', + 'dataExtensionTemplate', + ], folderType: 'dataextension', filter: { CustomerKey: [ diff --git a/lib/metadataTypes/definitions/Email.definition.js b/lib/metadataTypes/definitions/Email.definition.js index 56aaa2d11..249a6fa0a 100644 --- a/lib/metadataTypes/definitions/Email.definition.js +++ b/lib/metadataTypes/definitions/Email.definition.js @@ -1,6 +1,6 @@ module.exports = { bodyIteratorField: 'Results', - dependencies: ['folder'], + dependencies: ['folder-email', 'folder-shared_email_default'], hasExtended: false, idField: 'ID', keepId: true, diff --git a/lib/metadataTypes/definitions/EmailSendDefinition.definition.js b/lib/metadataTypes/definitions/EmailSendDefinition.definition.js index b44f94f45..9263ef82f 100644 --- a/lib/metadataTypes/definitions/EmailSendDefinition.definition.js +++ b/lib/metadataTypes/definitions/EmailSendDefinition.definition.js @@ -1,6 +1,6 @@ module.exports = { bodyIteratorField: 'Results', - dependencies: ['folder', 'email', 'asset-message', 'dataExtension', 'list'], // filter, SendClassification, SenderProfile, DeliveryProfile + dependencies: ['folder-userinitiatedsends', 'email', 'asset-message', 'dataExtension', 'list'], // filter, SendClassification, SenderProfile, DeliveryProfile folderType: 'userinitiatedsends', hasExtended: false, idField: 'ObjectID', diff --git a/lib/metadataTypes/definitions/ImportFile.definition.js b/lib/metadataTypes/definitions/ImportFile.definition.js index 7a20b283a..188e4f1e2 100644 --- a/lib/metadataTypes/definitions/ImportFile.definition.js +++ b/lib/metadataTypes/definitions/ImportFile.definition.js @@ -1,6 +1,6 @@ module.exports = { bodyIteratorField: 'items', - dependencies: ['folder', 'ftpLocation', 'dataExtension', 'list'], // folder has to be kept in here to resolve lists correctly + dependencies: ['ftpLocation', 'dataExtension', 'list'], destinationObjectTypeMapping: { unknown: 783, DataExtension: 310, diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index 7371dd3fe..93af23482 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -4,7 +4,7 @@ // update: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/putUpdateInteraction.html module.exports = { bodyIteratorField: 'items', - dependencies: ['folder', 'triggeredSendDefinition', 'eventDefinition'], + dependencies: ['folder-journey', 'triggeredSendDefinition', 'eventDefinition'], folderIdField: 'categoryId', hasExtended: false, idField: 'id', diff --git a/lib/metadataTypes/definitions/List.definition.js b/lib/metadataTypes/definitions/List.definition.js index d2126fb96..867a2c64b 100644 --- a/lib/metadataTypes/definitions/List.definition.js +++ b/lib/metadataTypes/definitions/List.definition.js @@ -1,6 +1,6 @@ module.exports = { bodyIteratorField: 'Results', - dependencies: ['folder'], + dependencies: ['folder-mysubs', 'folder-list', 'folder-publication'], folderType: 'list', hasExtended: false, idField: 'ObjectID', diff --git a/lib/metadataTypes/definitions/Query.definition.js b/lib/metadataTypes/definitions/Query.definition.js index f5c57f0d4..1e14a6aa0 100644 --- a/lib/metadataTypes/definitions/Query.definition.js +++ b/lib/metadataTypes/definitions/Query.definition.js @@ -1,6 +1,6 @@ module.exports = { bodyIteratorField: 'items', - dependencies: ['folder', 'dataExtension'], + dependencies: ['folder-queryactivity', 'dataExtension'], folderType: 'queryactivity', filter: { description: ['Query created by Query Studio'], diff --git a/lib/metadataTypes/definitions/Script.definition.js b/lib/metadataTypes/definitions/Script.definition.js index f2c824735..0c38bd745 100644 --- a/lib/metadataTypes/definitions/Script.definition.js +++ b/lib/metadataTypes/definitions/Script.definition.js @@ -1,6 +1,6 @@ module.exports = { bodyIteratorField: 'items', - dependencies: ['folder'], + dependencies: ['folder-ssjsactivity'], folderType: 'ssjsactivity', hasExtended: false, idField: 'ssjsActivityId', diff --git a/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js b/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js index 705aa5059..38e2becec 100644 --- a/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js +++ b/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js @@ -1,6 +1,12 @@ module.exports = { bodyIteratorField: 'Results', - dependencies: ['folder', 'email', 'asset-message', 'list'], // SendClassification, SenderProfile, DeliveryProfile + dependencies: [ + 'folder-triggered_send', + 'folder-triggered_send_journeybuilder', + 'email', + 'asset-message', + 'list', + ], // SendClassification, SenderProfile, DeliveryProfile folderType: 'triggered_send', hasExtended: false, idField: 'ObjectID', From 3028e243f890fab0a581cc3eb45ab2835de60f3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 18 Jan 2023 16:27:10 +0100 Subject: [PATCH 054/132] #638: ensure token requests are not counted --- test/dataExtension.test.js | 20 ++++++++++---------- test/query.test.js | 16 ++++++++-------- test/transactionalEmail.test.js | 12 ++++++------ test/transactionalPush.test.js | 14 ++++++++------ test/transactionalSMS.test.js | 12 ++++++------ test/utils.js | 24 ++++++++++++++++++++++++ 6 files changed, 62 insertions(+), 36 deletions(-) diff --git a/test/dataExtension.test.js b/test/dataExtension.test.js index 6e3c1320d..6900de377 100644 --- a/test/dataExtension.test.js +++ b/test/dataExtension.test.js @@ -29,9 +29,9 @@ describe('dataExtension', () => { 'returned metadata was not equal expected' ); assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, - 6, - 'Unexpected number of requests made' + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); @@ -65,9 +65,9 @@ describe('dataExtension', () => { 'returned metadata was not equal expected for update' ); assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, - 12, - 'Unexpected number of requests made' + testUtils.getAPIHistoryLength(), + 11, + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); @@ -112,9 +112,9 @@ describe('dataExtension', () => { 'returned deployment file was not equal expected' ); assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 5, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); @@ -159,9 +159,9 @@ describe('dataExtension', () => { 'returned deployment file was not equal expected' ); assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 5, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); diff --git a/test/query.test.js b/test/query.test.js index 76f4682fa..9b35ae11b 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -38,9 +38,9 @@ describe('query', () => { file(testUtils.getExpectedFile('9999999', 'query', 'get', 'sql')) ); assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 6, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); @@ -80,9 +80,9 @@ describe('query', () => { ); // check number of API calls assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 8, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); @@ -126,9 +126,9 @@ describe('query', () => { file(testUtils.getActualDeployFile('testExistingQuery', 'query', 'sql')) ).to.equal(file(testUtils.getExpectedFile('9999999', 'query', 'build', 'sql'))); assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 6, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); @@ -173,9 +173,9 @@ describe('query', () => { ).to.equal(file(testUtils.getExpectedFile('9999999', 'query', 'build', 'sql'))); assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 6, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); diff --git a/test/transactionalEmail.test.js b/test/transactionalEmail.test.js index 489535791..0598a4067 100644 --- a/test/transactionalEmail.test.js +++ b/test/transactionalEmail.test.js @@ -32,9 +32,9 @@ describe('transactionalEmail', () => { 'returned JSON was not equal expected' ); assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 12, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); @@ -68,9 +68,9 @@ describe('transactionalEmail', () => { ); // check number of API calls assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 13, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); @@ -110,9 +110,9 @@ describe('transactionalEmail', () => { 'returned deployment JSON was not equal expected' ); assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 12, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); diff --git a/test/transactionalPush.test.js b/test/transactionalPush.test.js index 4fa770568..49d008a09 100644 --- a/test/transactionalPush.test.js +++ b/test/transactionalPush.test.js @@ -32,9 +32,9 @@ describe('transactionalPush', () => { 'returned JSON was not equal expected' ); assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 3, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); @@ -68,9 +68,10 @@ describe('transactionalPush', () => { ); // check number of API calls assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 4, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests', + testUtils.getAPIHistoryDebug() ); return; }); @@ -110,9 +111,10 @@ describe('transactionalPush', () => { 'returned deployment JSON was not equal expected' ); assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 3, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests', + testUtils.getAPIHistoryDebug() ); return; }); diff --git a/test/transactionalSMS.test.js b/test/transactionalSMS.test.js index 79a6d28f4..7c6c48847 100644 --- a/test/transactionalSMS.test.js +++ b/test/transactionalSMS.test.js @@ -39,9 +39,9 @@ describe('transactionalSMS', () => { file(testUtils.getExpectedFile('9999999', 'transactionalSMS', 'get', 'amp')) ); assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 4, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); @@ -85,9 +85,9 @@ describe('transactionalSMS', () => { ); // check number of API calls assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 5, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); @@ -139,9 +139,9 @@ describe('transactionalSMS', () => { file(testUtils.getExpectedFile('9999999', 'transactionalSMS', 'build', 'amp')) ); assert.equal( - Object.values(testUtils.getAPIHistory()).flat().length, + testUtils.getAPIHistoryLength(), 4, - 'Unexpected number of requests made' + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; }); diff --git a/test/utils.js b/test/utils.js index d2d1ab5c6..86b2c73e3 100644 --- a/test/utils.js +++ b/test/utils.js @@ -138,12 +138,36 @@ exports.mockReset = () => { fsmock.restore(); apimock.restore(); }; +/** + * helper to return amount of api callouts + * + * @param {boolean} [includeToken] if true, will include token calls in count + * @returns {object} of API history + */ +exports.getAPIHistoryLength = (includeToken) => { + const historyArr = Object.values(apimock.history).flat(); + if (includeToken) { + return historyArr.length; + } + return historyArr.filter((item) => item.url !== '/v2/token').length; +}; /** * helper to return api history * * @returns {object} of API history */ exports.getAPIHistory = () => apimock.history; +/** + * helper to return most important fields for each api call + * + * @returns {object} of API history + */ +exports.getAPIHistoryDebug = () => { + const historyArr = Object.values(apimock.history) + .flat() + .map((item) => ({ url: item.url, data: item.data })); + return historyArr; +}; /** * escapes string for regex From c4bd665b1d6f33ec57cc6ef92a27d46aacd6be30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 20 Jan 2023 13:45:01 +0100 Subject: [PATCH 055/132] #630: improve error handling and log output for refresh TSD --- docs/dist/documentation.md | 24 ++++- lib/metadataTypes/MetadataType.js | 19 +++- lib/metadataTypes/TriggeredSendDefinition.js | 103 ++++++++++++++++--- 3 files changed, 122 insertions(+), 24 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 0fcc778a2..aa75b0fa1 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -3160,6 +3160,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.updateREST(metadataEntry, uri, [usePut])](#MetadataType.updateREST) ⇒ Promise * [.updateSOAP(metadataEntry, [overrideType], [handleOutside])](#MetadataType.updateSOAP) ⇒ Promise * [._handleSOAPErrors(ex, msg, [metadataEntry], [handleOutside])](#MetadataType._handleSOAPErrors) + * [.getSOAPErrorMsg(ex)](#MetadataType.getSOAPErrorMsg) ⇒ string * [.retrieveSOAP(retrieveDir, buObject, [requestParams], [additionalFields])](#MetadataType.retrieveSOAP) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveREST(retrieveDir, uri, [overrideType], [templateVariables], [singleRetrieve])](#MetadataType.retrieveREST) ⇒ Promise.<{metadata: (TYPE.MetadataTypeMap\|TYPE.MetadataTypeItem), type: string}> * [.parseResponseBody(body, [singleRetrieve])](#MetadataType.parseResponseBody) ⇒ TYPE.MetadataTypeMap @@ -3531,6 +3532,18 @@ Updates a single metadata entry via fuel-soap (generic lib not wrapper) | [metadataEntry] | TYPE.MetadataTypeItem | single metadata entry | | [handleOutside] | boolean | if the API reponse is irregular this allows you to handle it outside of this generic method | + + +### MetadataType.getSOAPErrorMsg(ex) ⇒ string +helper for [_handleSOAPErrors](_handleSOAPErrors) + +**Kind**: static method of [MetadataType](#MetadataType) +**Returns**: string - error message + +| Param | Type | Description | +| --- | --- | --- | +| ex | Error | error that occured | + ### MetadataType.retrieveSOAP(retrieveDir, buObject, [requestParams], [additionalFields]) ⇒ Promise.<TYPE.MetadataTypeMapObj> @@ -4884,14 +4897,14 @@ MessageSendActivity MetadataType * [TriggeredSendDefinition](#TriggeredSendDefinition) ⇐ [MetadataType](#MetadataType) * [.retrieve(retrieveDir, [_], [__], [___], [key])](#TriggeredSendDefinition.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.create(metadata)](#TriggeredSendDefinition.create) ⇒ Promise - * [.update(metadata)](#TriggeredSendDefinition.update) ⇒ Promise + * [.update(metadata, [handleOutside])](#TriggeredSendDefinition.update) ⇒ Promise * [.deleteByKey(customerKey)](#TriggeredSendDefinition.deleteByKey) ⇒ Promise.<boolean> * [.postRetrieveTasks(metadata)](#TriggeredSendDefinition.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.setFolderPath(metadata)](#TriggeredSendDefinition.setFolderPath) * [.parseMetadata(metadata)](#TriggeredSendDefinition.parseMetadata) ⇒ TYPE.MetadataTypeItem \| void * [.preDeployTasks(metadata)](#TriggeredSendDefinition.preDeployTasks) ⇒ TYPE.MetadataTypeItem * [.refresh([keyArr])](#TriggeredSendDefinition.refresh) ⇒ Promise.<void> - * [._refreshItem(key)](#TriggeredSendDefinition._refreshItem) ⇒ Promise.<void> + * [._refreshItem(key)](#TriggeredSendDefinition._refreshItem) ⇒ Promise.<boolean> @@ -4923,7 +4936,7 @@ Create a single TSD. -### TriggeredSendDefinition.update(metadata) ⇒ Promise +### TriggeredSendDefinition.update(metadata, [handleOutside]) ⇒ Promise Updates a single TSD. **Kind**: static method of [TriggeredSendDefinition](#TriggeredSendDefinition) @@ -4932,6 +4945,7 @@ Updates a single TSD. | Param | Type | Description | | --- | --- | --- | | metadata | TYPE.MetadataTypeItem | single metadata entry | +| [handleOutside] | boolean | if the API reponse is irregular this allows you to handle it outside of this generic method | @@ -5006,11 +5020,11 @@ TSD-specific refresh method that finds active TSDs and refreshes them -### TriggeredSendDefinition.\_refreshItem(key) ⇒ Promise.<void> +### TriggeredSendDefinition.\_refreshItem(key) ⇒ Promise.<boolean> helper for [refresh](refresh) that pauses, publishes and starts a triggered send **Kind**: static method of [TriggeredSendDefinition](#TriggeredSendDefinition) -**Returns**: Promise.<void> - - +**Returns**: Promise.<boolean> - true if refresh was successful | Param | Type | Description | | --- | --- | --- | diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index a5fd1803d..65bb523a5 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -742,13 +742,22 @@ class MetadataType { if (handleOutside) { throw ex; } else { - const errorMsg = ex?.json?.Results?.length - ? `${ex.json.Results[0].StatusMessage} (Code ${ex.json.Results[0].ErrorCode})` - : ex.message; + const errorMsg = this.getSOAPErrorMsg(ex); const name = metadataEntry ? ` '${metadataEntry[this.definition.keyField]}'` : ''; Util.logger.error(` ☇ error ${msg} ${this.definition.type}${name}: ${errorMsg}`); } } + /** + * helper for {@link _handleSOAPErrors} + * + * @param {Error} ex error that occured + * @returns {string} error message + */ + static getSOAPErrorMsg(ex) { + return ex?.json?.Results?.length + ? `${ex.json.Results[0].StatusMessage} (Code ${ex.json.Results[0].ErrorCode})` + : ex.message; + } /** * Retrieves SOAP via generic fuel-soap wrapper based metadata of metadata type into local filesystem. executes callback with retrieved metadata * @@ -915,8 +924,8 @@ class MetadataType { // revert back placeholder to dots const originHelper = origin ? origin + '.' + fieldPath : fieldPath; - if (this.definition.fields[originHelper]?.skipValidation) { - // skip if current field should not be validated + if (this.definition.fields[originHelper]?.skipValidation || originHelper === '@_xsi:type') { + // skip if current field should not be validated OR if field is internal helper field xsi:type return; } else if ( Array.isArray(fieldContent) && diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index 8c5d9140e..30a73119d 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -62,12 +62,13 @@ class TriggeredSendDefinition extends MetadataType { * Updates a single TSD. * * @param {TYPE.MetadataTypeItem} metadata single metadata entry + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method * @returns {Promise} Promise */ - static update(metadata) { + static update(metadata, handleOutside) { // * in case of update and active definition, we need to pause first. - // * this should be done manually to not accidentally purge production queues - return super.updateSOAP(metadata); + // * this should be done manually to not accidentally pause production queues without restarting them + return super.updateSOAP(metadata, null, handleOutside); } /** @@ -260,32 +261,106 @@ class TriggeredSendDefinition extends MetadataType { for (const key of keyArr) { refreshList.push(this._refreshItem(key)); } - await Promise.all(refreshList); - Util.logger.info(`Refresh done.`); + const successCounter = (await Promise.all(refreshList)).filter(Boolean).length; + Util.logger.info(`Refreshed ${successCounter} of ${keyArr.length}`); } /** * helper for {@link refresh} that pauses, publishes and starts a triggered send * * @param {string} key external key of triggered send item - * @returns {Promise.} - + * @returns {Promise.} true if refresh was successful */ static async _refreshItem(key) { const item = {}; + let test; item[this.definition.keyField] = key; + // check triggeredSend-key exists on the server AND its status==ACTIVE + /** @type {TYPE.SoapRequestParams} */ + const requestParams = { + filter: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + }; + try { + test = ( + await super.retrieveSOAP(null, null, requestParams, [ + 'CustomerKey', + 'TriggeredSendStatus', + ]) + )?.metadata; + } catch (ex) { + const errorMsg = super.getSOAPErrorMsg(ex); + Util.logger.error(` ☇ skipping ${this.definition.typeName}: ${key} - ${errorMsg}}`); + return false; + } + if (!test[key]) { + Util.logger.error( + ` ☇ skipping ${this.definition.typeName}: ${key} - not found on server` + ); + return false; + } + if (test[key].TriggeredSendStatus !== 'Active') { + Util.logger.error( + ` ☇ skipping ${this.definition.typeName}: ${key} - refresh only needed for running entries (TriggeredSendStatus=Active)` + ); + return false; + } + // pause - item.TriggeredSendStatus = 'Inactive'; - await this.update(item); - delete item.TriggeredSendStatus; + try { + item.TriggeredSendStatus = 'Inactive'; + test = await this.update(item, true); + if (test.OverallStatus !== 'OK') { + throw new Error(test.Results[0].StatusMessage); + } + delete item.TriggeredSendStatus; + Util.logger.info(` - paused ${this.definition.typeName}: ${key}`); + } catch (ex) { + const errorMsg = super.getSOAPErrorMsg(ex); + + Util.logger.error( + ` - failed to pause ${this.definition.typeName}: ${key} - ${errorMsg}` + ); + return false; + } // publish - item.RefreshContent = 'true'; - await this.update(item); - delete item.RefreshContent; + try { + item.RefreshContent = 'true'; + test = await this.update(item, true); + if (test.OverallStatus !== 'OK') { + throw new Error(test.Results[0].StatusMessage); + } + delete item.RefreshContent; + Util.logger.info(` - published ${this.definition.typeName}: ${key}`); + } catch (ex) { + const errorMsg = super.getSOAPErrorMsg(ex); + Util.logger.error( + ` - failed to publish ${this.definition.typeName}: ${key} - ${errorMsg}` + ); + return false; + } // start - item.TriggeredSendStatus = 'Active'; - await this.update(item); + try { + item.TriggeredSendStatus = 'Active'; + test = await this.update(item, true); + if (test.OverallStatus !== 'OK') { + throw new Error(test.Results[0].StatusMessage); + } + delete item.RefreshContent; + Util.logger.info(` - started ${this.definition.typeName}: ${key}`); + } catch (ex) { + const errorMsg = super.getSOAPErrorMsg(ex); + Util.logger.error( + ` - failed to publish ${this.definition.typeName}: ${key} - ${errorMsg}` + ); + return false; + } + return true; } } From dd421550e8b2f9804d222ccd842dceb703d58b72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 20 Jan 2023 17:32:34 +0100 Subject: [PATCH 056/132] #630: add missing custom field --- docs/dist/documentation.md | 11 +++++++++-- .../definitions/TriggeredSendDefinition.definition.js | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index aa75b0fa1..7c26b5ffb 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -4904,7 +4904,8 @@ MessageSendActivity MetadataType * [.parseMetadata(metadata)](#TriggeredSendDefinition.parseMetadata) ⇒ TYPE.MetadataTypeItem \| void * [.preDeployTasks(metadata)](#TriggeredSendDefinition.preDeployTasks) ⇒ TYPE.MetadataTypeItem * [.refresh([keyArr])](#TriggeredSendDefinition.refresh) ⇒ Promise.<void> - * [._refreshItem(key)](#TriggeredSendDefinition._refreshItem) ⇒ Promise.<boolean> + * [._findRefreshableItems()](#TriggeredSendDefinition._findRefreshableItems) ⇒ Promise.<Array.<string>> + * [._refreshItem(key, checkKey)](#TriggeredSendDefinition._refreshItem) ⇒ Promise.<boolean> @@ -5018,9 +5019,14 @@ TSD-specific refresh method that finds active TSDs and refreshes them | --- | --- | --- | | [keyArr] | Array.<string> | metadata keys | + + +### TriggeredSendDefinition.\_findRefreshableItems() ⇒ Promise.<Array.<string>> +**Kind**: static method of [TriggeredSendDefinition](#TriggeredSendDefinition) +**Returns**: Promise.<Array.<string>> - keyArr -### TriggeredSendDefinition.\_refreshItem(key) ⇒ Promise.<boolean> +### TriggeredSendDefinition.\_refreshItem(key, checkKey) ⇒ Promise.<boolean> helper for [refresh](refresh) that pauses, publishes and starts a triggered send **Kind**: static method of [TriggeredSendDefinition](#TriggeredSendDefinition) @@ -5029,6 +5035,7 @@ helper for [refresh](refresh) that pauses, publishes and starts a triggered send | Param | Type | Description | | --- | --- | --- | | key | string | external key of triggered send item | +| checkKey | boolean | whether to check if key exists on the server | diff --git a/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js b/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js index 705aa5059..9ee1f360e 100644 --- a/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js +++ b/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js @@ -525,5 +525,6 @@ module.exports = { r__folder_Path: { skipValidation: true }, r__assetMessage_Name: { skipValidation: true }, r__assetMessage_Key: { skipValidation: true }, + r__list_PathName: { skipValidation: true }, }, }; From ba74846ff8cb012bc0f454329f02a264fa6dd0e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 20 Jan 2023 17:40:34 +0100 Subject: [PATCH 057/132] #630: allow refreshing all active TSDs on a BU automatically --- docs/dist/documentation.md | 2 + lib/index.js | 1 + lib/metadataTypes/TriggeredSendDefinition.js | 140 +++++++++++++------ 3 files changed, 99 insertions(+), 44 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 7c26b5ffb..b8e99cb93 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -5022,6 +5022,8 @@ TSD-specific refresh method that finds active TSDs and refreshes them ### TriggeredSendDefinition.\_findRefreshableItems() ⇒ Promise.<Array.<string>> +helper for [refresh](refresh) that finds active TSDs on the server and filters it by the same rules that [retrieve](retrieve) is using to avoid refreshing TSDs with broken dependencies + **Kind**: static method of [TriggeredSendDefinition](#TriggeredSendDefinition) **Returns**: Promise.<Array.<string>> - keyArr diff --git a/lib/index.js b/lib/index.js index 761148ac4..8de82302c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -411,6 +411,7 @@ class Mcdev { return; } try { + cache.initCache(buObject); MetadataTypeInfo[type].properties = properties; MetadataTypeInfo[type].buObject = buObject; await MetadataTypeInfo[type].refresh(keyArr); diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index 30a73119d..1d9317afd 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -5,6 +5,12 @@ const MetadataType = require('./MetadataType'); const Util = require('../util/util'); const cache = require('../util/cache'); +const cacheTypes = { + asset: require('./Asset'), + folder: require('./Folder'), + list: require('./List'), +}; + /** * MessageSendActivity MetadataType * @@ -241,72 +247,118 @@ class TriggeredSendDefinition extends MetadataType { * @returns {Promise.} - */ static async refresh(keyArr) { + let checkKey = true; if (!keyArr) { - // cache ACTIVE triggeredSends from the server - /** @type {TYPE.SoapRequestParams} */ - const requestParams = { - filter: { - leftOperand: 'TriggeredSendStatus', - operator: 'IN', - rightOperand: ['Active'], // Active=Running, Inactive=Paused - }, - }; - const metadata = (await super.retrieveSOAP(null, null, requestParams)).metadata; - keyArr = Object.keys(metadata); + keyArr = await this._findRefreshableItems(); + checkKey = false; } // then executes pause, publish, start on them. const refreshList = []; Util.logger.info(`Refreshing ${keyArr.length} ${this.definition.typeName}...`); Util.logger.debug(`Refreshing keys: ${keyArr.join(', ')}`); for (const key of keyArr) { - refreshList.push(this._refreshItem(key)); + refreshList.push(this._refreshItem(key, checkKey)); } const successCounter = (await Promise.all(refreshList)).filter(Boolean).length; Util.logger.info(`Refreshed ${successCounter} of ${keyArr.length}`); } + /** + * helper for {@link refresh} that finds active TSDs on the server and filters it by the same rules that {@link retrieve} is using to avoid refreshing TSDs with broken dependencies + * + * @returns {Promise.} keyArr + */ + static async _findRefreshableItems() { + Util.logger.info('Finding refreshable items...'); + // cache dependencies to test for broken links + // skip deprecated classic emails here, assuming they cannot be updated and hence are not relevant for {@link refresh} + const requiredCache = { + folder: [ + 'list', + 'mysubs', + 'suppression_list', + 'publication', + 'contextual_suppression_list', + 'triggered_send', + 'triggered_send_journeybuilder', + ], + asset: 'message', + list: null, + }; + for (const [type, subTypeArr] of Object.entries(requiredCache)) { + if (!cache.getCache()?.[type]) { + Util.logger.info(` - Caching dependent Metadata: ${type}`); + cacheTypes[type].client = this.client; + cacheTypes[type].buObject = this.buObject; + cacheTypes[type].properties = this.properties; + + const result = await cacheTypes[type].retrieveForCache(this.buObject, subTypeArr); + cache.setMetadata(type, result.metadata); + } + } + // cache ACTIVE triggeredSends from the server + /** @type {TYPE.SoapRequestParams} */ + const requestParams = { + filter: { + leftOperand: 'TriggeredSendStatus', + operator: 'IN', + rightOperand: ['dummy', 'Active'], // using equals does not work for this field for an unknown reason and IN requires at least 2 values, hence the 'dummy' entry + }, + }; + const metadata = (await super.retrieveSOAP(null, null, requestParams)).metadata; + const keyArr = Object.keys(metadata).filter((key) => { + const test = this.postRetrieveTasks(metadata[key]); + return test?.CustomerKey || false; + }); + Util.logger.info(`Found ${keyArr.length} refreshable items.`); + return keyArr; + } + /** * helper for {@link refresh} that pauses, publishes and starts a triggered send * * @param {string} key external key of triggered send item + * @param {boolean} checkKey whether to check if key exists on the server * @returns {Promise.} true if refresh was successful */ - static async _refreshItem(key) { + static async _refreshItem(key, checkKey) { const item = {}; let test; item[this.definition.keyField] = key; // check triggeredSend-key exists on the server AND its status==ACTIVE - /** @type {TYPE.SoapRequestParams} */ - const requestParams = { - filter: { - leftOperand: 'CustomerKey', - operator: 'equals', - rightOperand: key, - }, - }; - try { - test = ( - await super.retrieveSOAP(null, null, requestParams, [ - 'CustomerKey', - 'TriggeredSendStatus', - ]) - )?.metadata; - } catch (ex) { - const errorMsg = super.getSOAPErrorMsg(ex); - Util.logger.error(` ☇ skipping ${this.definition.typeName}: ${key} - ${errorMsg}}`); - return false; - } - if (!test[key]) { - Util.logger.error( - ` ☇ skipping ${this.definition.typeName}: ${key} - not found on server` - ); - return false; - } - if (test[key].TriggeredSendStatus !== 'Active') { - Util.logger.error( - ` ☇ skipping ${this.definition.typeName}: ${key} - refresh only needed for running entries (TriggeredSendStatus=Active)` - ); - return false; + if (checkKey) { + /** @type {TYPE.SoapRequestParams} */ + const requestParams = { + filter: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + }; + try { + test = ( + await super.retrieveSOAP(null, null, requestParams, [ + 'CustomerKey', + 'TriggeredSendStatus', + ]) + )?.metadata; + } catch (ex) { + const errorMsg = super.getSOAPErrorMsg(ex); + Util.logger.error(` ☇ skipping ${this.definition.typeName}: ${key} - ${errorMsg}}`); + return false; + } + if (!test[key]) { + Util.logger.error( + ` ☇ skipping ${this.definition.typeName}: ${key} - not found on server` + ); + return false; + } + if (test[key].TriggeredSendStatus !== 'Active') { + Util.logger.error( + ` ☇ skipping ${this.definition.typeName}: ${key} - refresh only needed for running entries (TriggeredSendStatus=Active)` + ); + return false; + } } // pause From 62b58bdf4b43120ca5574ffbd659b8e1b8732e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 20 Jan 2023 17:44:01 +0100 Subject: [PATCH 058/132] #630: improve logging --- lib/index.js | 2 +- lib/metadataTypes/TriggeredSendDefinition.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index 8de82302c..96b6b138c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -416,7 +416,7 @@ class Mcdev { MetadataTypeInfo[type].buObject = buObject; await MetadataTypeInfo[type].refresh(keyArr); } catch (ex) { - Util.logger.error('mcdev.refresh ' + ex.message); + Util.logger.errorStack(ex, 'mcdev.refresh ' + ex.message); } } } diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index 1d9317afd..088e236a9 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -132,6 +132,9 @@ class TriggeredSendDefinition extends MetadataType { try { this.setFolderPath(metadata); } catch { + Util.logger.verbose( + ` - skipping ${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': Could not find folder.` + ); return; } From a795c9d4fd4285c5bd90c1c5dfddd15f186fd6e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sat, 21 Jan 2023 12:19:14 +0100 Subject: [PATCH 059/132] #642: fix success counter for SOAP create/update --- docs/dist/documentation.md | 24 ++++++++++++------------ lib/metadataTypes/MetadataType.js | 12 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 3bd0fc7a3..3e9331bb9 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -3021,10 +3021,10 @@ Provides default functionality that can be overwritten by child metadata type cl * [.hasChanged(cachedVersion, metadata, [fieldName])](#MetadataType.hasChanged) ⇒ boolean * [.hasChangedGeneric(cachedVersion, metadata, [fieldName], [silent])](#MetadataType.hasChangedGeneric) ⇒ boolean * [.upsert(metadata, deployDir, [buObject])](#MetadataType.upsert) ⇒ Promise.<TYPE.MetadataTypeMap> - * [.createREST(metadataEntry, uri)](#MetadataType.createREST) ⇒ Promise - * [.createSOAP(metadataEntry, [overrideType], [handleOutside])](#MetadataType.createSOAP) ⇒ Promise - * [.updateREST(metadataEntry, uri)](#MetadataType.updateREST) ⇒ Promise - * [.updateSOAP(metadataEntry, [overrideType], [handleOutside])](#MetadataType.updateSOAP) ⇒ Promise + * [.createREST(metadataEntry, uri)](#MetadataType.createREST) ⇒ Promise.<object> \| null + * [.createSOAP(metadataEntry, [overrideType], [handleOutside])](#MetadataType.createSOAP) ⇒ Promise.<object> \| null + * [.updateREST(metadataEntry, uri)](#MetadataType.updateREST) ⇒ Promise.<object> \| null + * [.updateSOAP(metadataEntry, [overrideType], [handleOutside])](#MetadataType.updateSOAP) ⇒ Promise.<object> \| null * [._handleSOAPErrors(ex, msg, [metadataEntry], [handleOutside])](#MetadataType._handleSOAPErrors) * [.retrieveSOAP(retrieveDir, buObject, [requestParams], [additionalFields])](#MetadataType.retrieveSOAP) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveREST(retrieveDir, uri, [overrideType], [templateVariables], [singleRetrieve])](#MetadataType.retrieveREST) ⇒ Promise.<{metadata: (TYPE.MetadataTypeMap\|TYPE.MetadataTypeItem), type: string}> @@ -3302,11 +3302,11 @@ MetadataType upsert, after retrieving from target and comparing to check if crea -### MetadataType.createREST(metadataEntry, uri) ⇒ Promise +### MetadataType.createREST(metadataEntry, uri) ⇒ Promise.<object> \| null Creates a single metadata entry via REST **Kind**: static method of [MetadataType](#MetadataType) -**Returns**: Promise - Promise +**Returns**: Promise.<object> \| null - Promise of API response or null in case of an error | Param | Type | Description | | --- | --- | --- | @@ -3315,11 +3315,11 @@ Creates a single metadata entry via REST -### MetadataType.createSOAP(metadataEntry, [overrideType], [handleOutside]) ⇒ Promise +### MetadataType.createSOAP(metadataEntry, [overrideType], [handleOutside]) ⇒ Promise.<object> \| null Creates a single metadata entry via fuel-soap (generic lib not wrapper) **Kind**: static method of [MetadataType](#MetadataType) -**Returns**: Promise - Promise +**Returns**: Promise.<object> \| null - Promise of API response or null in case of an error | Param | Type | Description | | --- | --- | --- | @@ -3329,11 +3329,11 @@ Creates a single metadata entry via fuel-soap (generic lib not wrapper) -### MetadataType.updateREST(metadataEntry, uri) ⇒ Promise +### MetadataType.updateREST(metadataEntry, uri) ⇒ Promise.<object> \| null Updates a single metadata entry via REST **Kind**: static method of [MetadataType](#MetadataType) -**Returns**: Promise - Promise +**Returns**: Promise.<object> \| null - Promise of API response or null in case of an error | Param | Type | Description | | --- | --- | --- | @@ -3342,11 +3342,11 @@ Updates a single metadata entry via REST -### MetadataType.updateSOAP(metadataEntry, [overrideType], [handleOutside]) ⇒ Promise +### MetadataType.updateSOAP(metadataEntry, [overrideType], [handleOutside]) ⇒ Promise.<object> \| null Updates a single metadata entry via fuel-soap (generic lib not wrapper) **Kind**: static method of [MetadataType](#MetadataType) -**Returns**: Promise - Promise +**Returns**: Promise.<object> \| null - Promise of API response or null in case of an error | Param | Type | Description | | --- | --- | --- | diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index cc1070dcb..df0d66655 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -559,7 +559,7 @@ class MetadataType { * * @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry * @param {string} uri rest endpoint for POST - * @returns {Promise} Promise + * @returns {Promise. | null} Promise of API response or null in case of an error */ static async createREST(metadataEntry, uri) { this.removeNotCreateableFields(metadataEntry); @@ -593,7 +593,7 @@ class MetadataType { * @param {TYPE.MetadataTypeItem} metadataEntry single metadata entry * @param {string} [overrideType] can be used if the API type differs from the otherwise used type identifier * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method - * @returns {Promise} Promise + * @returns {Promise. | null} Promise of API response or null in case of an error */ static async createSOAP(metadataEntry, overrideType, handleOutside) { try { @@ -615,7 +615,7 @@ class MetadataType { return response; } catch (ex) { this._handleSOAPErrors(ex, 'creating', metadataEntry, handleOutside); - return {}; + return null; } } @@ -624,7 +624,7 @@ class MetadataType { * * @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry * @param {string} uri rest endpoint for PATCH - * @returns {Promise} Promise + * @returns {Promise. | null} Promise of API response or null in case of an error */ static async updateREST(metadataEntry, uri) { this.removeNotUpdateableFields(metadataEntry); @@ -660,7 +660,7 @@ class MetadataType { * @param {TYPE.MetadataTypeItem} metadataEntry single metadata entry * @param {string} [overrideType] can be used if the API type differs from the otherwise used type identifier * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method - * @returns {Promise} Promise + * @returns {Promise. | null} Promise of API response or null in case of an error */ static async updateSOAP(metadataEntry, overrideType, handleOutside) { try { @@ -681,7 +681,7 @@ class MetadataType { return response; } catch (ex) { this._handleSOAPErrors(ex, 'updating', metadataEntry, handleOutside); - return {}; + return null; } } /** From eb2915048a1247587e68485fbf83b67c2a63d7d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sat, 21 Jan 2023 22:23:39 +0100 Subject: [PATCH 060/132] #610: add npm keywords --- package.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/package.json b/package.json index 93eb22a46..6e2c8482f 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,19 @@ "type": "corporate", "url": "https://github.com/Accenture/sfmc-devtools" }, + "keywords": [ + "sfmc", + "ide", + "devops", + "developer", + "exacttarget", + "salesforce", + "marketing cloud", + "package manager", + "fuel", + "soap", + "rest" + ], "main": "./lib/index.js", "bin": { "mcdev": "./lib/cli.js" From e8dac4de5b4f899a4d199d1395fe3a33d9ad5ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sat, 21 Jan 2023 23:11:43 +0100 Subject: [PATCH 061/132] #641: limit retrieved fields by DEs that are upserted --- lib/metadataTypes/DataExtension.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index 1645db7f0..9d1e48f0f 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -30,7 +30,25 @@ class DataExtension extends MetadataType { /** @type {TYPE.DataExtensionMap} */ const targetMetadata = cache.getCache().dataExtension || {}; // get existing de-fields to properly handle add/update/delete of fields - await this._attachFields(targetMetadata); + const fieldOptions = {}; + for (const key of Object.keys(desToDeploy)) { + fieldOptions.filter = fieldOptions.filter + ? { + leftOperand: { + leftOperand: 'DataExtension.CustomerKey', + operator: 'equals', + rightOperand: key, + }, + operator: 'OR', + rightOperand: fieldOptions.filter, + } + : { + leftOperand: 'DataExtension.CustomerKey', + operator: 'equals', + rightOperand: key, + }; + } + await this._attachFields(desToDeploy, fieldOptions); /** @type {Promise[]} */ const deCreatePromises = []; From 787e7e1bab0ba545aa26f737fe3b288e6ee841cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sat, 21 Jan 2023 23:46:48 +0100 Subject: [PATCH 062/132] #641: improve log output --- lib/metadataTypes/DataExtension.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index 9d1e48f0f..997d911a6 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -29,7 +29,7 @@ class DataExtension extends MetadataType { // get dataExtensions from target BU for add/update decision /** @type {TYPE.DataExtensionMap} */ const targetMetadata = cache.getCache().dataExtension || {}; - // get existing de-fields to properly handle add/update/delete of fields + // get existing DE-fields for DE-keys in deployment package to properly handle add/update/delete of fields const fieldOptions = {}; for (const key of Object.keys(desToDeploy)) { fieldOptions.filter = fieldOptions.filter @@ -48,6 +48,7 @@ class DataExtension extends MetadataType { rightOperand: key, }; } + Util.logger.info(` - Caching dependent Metadata: dataExtensionField`); await this._attachFields(desToDeploy, fieldOptions); /** @type {Promise[]} */ From 90a52f88dc2fbc2a1f1ee9bad61a924a18877268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sat, 21 Jan 2023 23:53:52 +0100 Subject: [PATCH 063/132] #648: show error if no deploy payload found --- lib/Deployer.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/Deployer.js b/lib/Deployer.js index 08aa90519..7d662e99f 100644 --- a/lib/Deployer.js +++ b/lib/Deployer.js @@ -238,11 +238,17 @@ class Deployer { Object.keys(this.metadata) ); } - const foundDeployTypes = Object.keys(this.metadata).map((item) => - item === 'asset' && Util.includesStartsWith(typeArr, item) - ? typeArr[Util.includesStartsWithIndex(typeArr, item)] - : item - ); + const foundDeployTypes = Object.keys(this.metadata) + .map((type) => + type === 'asset' && Util.includesStartsWith(typeArr, type) + ? typeArr[Util.includesStartsWithIndex(typeArr, type)] + : type + ) + // remove empty types + .filter((type) => Object.keys(this.metadata[type]).length); + if (!foundDeployTypes.length) { + throw new Error('No metadata found for deployment'); + } const deployOrder = Util.getMetadataHierachy(foundDeployTypes); // build cache, including all metadata types which will be deployed (Avoids retrieve later) for (const metadataType of deployOrder) { From 9b2af85e342a0a4fa9dc6b3a7bee17eaf4384f87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sun, 22 Jan 2023 00:52:30 +0100 Subject: [PATCH 064/132] #627: add test for RETRIEVE interaction --- test/interaction.test.js | 42 +++ .../9999999/dataFolder/retrieve-response.xml | 22 ++ .../9999999/eventDefinition/get-expected.json | 34 +++ .../9999999/interaction/get-expected.json | 266 ++++++++++++++++++ .../v1/EventDefinitions/get-response.json | 42 +++ 5 files changed, 406 insertions(+) create mode 100644 test/interaction.test.js create mode 100644 test/resources/9999999/eventDefinition/get-expected.json create mode 100644 test/resources/9999999/interaction/get-expected.json create mode 100644 test/resources/9999999/interaction/v1/EventDefinitions/get-response.json diff --git a/test/interaction.test.js b/test/interaction.test.js new file mode 100644 index 000000000..969374091 --- /dev/null +++ b/test/interaction.test.js @@ -0,0 +1,42 @@ +const chai = require('chai'); +const chaiFiles = require('chai-files'); +const assert = chai.assert; +chai.use(chaiFiles); +const cache = require('../lib/util/cache'); +const testUtils = require('./utils'); +const handler = require('../lib/index'); + +describe('interaction', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a interaction', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['interaction']); + // THEN + // get results from cache + const result = cache.getCache(); + assert.equal( + result.interaction ? Object.keys(result.interaction).length : 0, + 1, + 'only one interaction expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_interaction', 'interaction'), + await testUtils.getExpectedJson('9999999', 'interaction', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + ); + return; + }); + }); +}); diff --git a/test/resources/9999999/dataFolder/retrieve-response.xml b/test/resources/9999999/dataFolder/retrieve-response.xml index a48d37473..e0ba6d200 100644 --- a/test/resources/9999999/dataFolder/retrieve-response.xml +++ b/test/resources/9999999/dataFolder/retrieve-response.xml @@ -153,6 +153,28 @@ false true + + + 9999999 + + + 2017-02-16T01:59:32.323 + 2017-02-16T01:59:32.323 + 6298 + + journey_default + + + 0 + + + my journeys + The root folder for Journeys + journey + true + false + true + diff --git a/test/resources/9999999/eventDefinition/get-expected.json b/test/resources/9999999/eventDefinition/get-expected.json new file mode 100644 index 000000000..c40d583d2 --- /dev/null +++ b/test/resources/9999999/eventDefinition/get-expected.json @@ -0,0 +1,34 @@ +{ + "type": "APIEvent", + "name": "TestContact_Event", + "description": "", + "createdDate": "2018-08-03T07:55:27.38", + "createdBy": 7586085, + "modifiedDate": "2018-08-03T08:22:03.76", + "modifiedBy": 7586085, + "mode": "Production", + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "dataExtensionName": "Contact_Data", + "sourceApplicationExtensionId": "7db1f972-f8b7-49b6-91b5-fa218e13953d", + "filterDefinitionTemplate": "", + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "arguments": { + "serializedObjectType": 11, + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "dataExtensionId": "C25D5A59-5EBC-40C9-8D27-149831881D89", + "automationId": "00000000-0000-0000-0000-000000000000", + "criteria": "", + "useHighWatermark": false + }, + "metaData": { + "scheduleState": "No Schedule", + "criteriaDescription": "" + }, + "interactionCount": 1, + "isVisibleInPicker": true, + "isPlatformObject": false, + "category": "Event", + "publishedInteractionCount": 1, + "automationId": "00000000-0000-0000-0000-000000000000", + "disableDEDataLogging": false +} diff --git a/test/resources/9999999/interaction/get-expected.json b/test/resources/9999999/interaction/get-expected.json new file mode 100644 index 000000000..b85f8ab28 --- /dev/null +++ b/test/resources/9999999/interaction/get-expected.json @@ -0,0 +1,266 @@ +{ + "key": "testExisting_interaction", + "name": "testExisting_interaction", + "lastPublishedDate": "2017-04-12T08:07:48", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2017-04-12T05:38:05.837", + "modifiedDate": "2017-04-12T08:07:48.333", + "activities": [ + { + "id": "69213026-bd2c-433b-8332-5f52d3e87ca5", + "key": "WAIT-1", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "bd3dff6b-565c-4b56-b9cb-60cd5b6d080b", + "next": "DATAEXTENSIONUPDATE-1", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "546704c0-9384-4a41-b20e-97615cc6cc6a", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "5d93cda9-2015-4c07-a1db-0d5853d25bf6", + "key": "WAIT-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "e3d3258a-891b-4838-b5a6-af37f8cb769a", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "deed4c9d-f487-4371-bfd9-76fca44ec49b", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "ef4db13e-83f0-4d41-981d-4bf5810c0daa", + "key": "DATAEXTENSIONUPDATE-1", + "name": "", + "description": "", + "type": "DATAEXTENSIONUPDATE", + "outcomes": [ + { + "key": "a49ecf04-4612-4582-85fe-d7193f872fa8", + "next": "WAIT-2", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { "contactKey": "{{Contact.Key}}", "value": "{{DateTime.Now}}" }, + "configurationArguments": { + "dataExtensionId": "ace267f0-b81d-e711-80cc-1402ec7222b4", + "field": "4e875b26-0317-4525-bfa0-50c8d1b7a7b5" + }, + "metaData": { + "dataExtensionName": "test_TestData", + "cachedFieldName": "JourneyConfirmed", + "cachedDisplayValue": "" + }, + "schema": { + "arguments": { + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "value": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "test_TESTDataentry", + "description": "", + "type": "APIEvent", + "outcomes": [], + "arguments": { + "filterResult": "{{Contact.FilterId.e4ddb887-6f2d-46b1-9f64-9a020f217339}}" + }, + "configurationArguments": { + "schemaVersionId": 133, + "criteria": "", + "filterDefinitionId": "e4ddb887-6f2d-46b1-9f64-9a020f217339" + }, + "metaData": { + "scheduleState": "No Schedule", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionId": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "title": "", + "category": "Event" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "OnceAndDone", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.APIEvent-60130566-e2fe-eb29-4140-15c27093a80b.\"emailAddress\"}}"], + "properties": {} + }, + "metaData": {}, + "executionMode": "Production", + "status": "Published", + "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/interaction/v1/EventDefinitions/get-response.json b/test/resources/9999999/interaction/v1/EventDefinitions/get-response.json new file mode 100644 index 000000000..42731676e --- /dev/null +++ b/test/resources/9999999/interaction/v1/EventDefinitions/get-response.json @@ -0,0 +1,42 @@ +{ + "count": 1, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "type": "APIEvent", + "name": "TestContact_Event", + "description": "", + "createdDate": "2018-08-03T07:55:27.38", + "createdBy": 7586085, + "modifiedDate": "2018-08-03T08:22:03.76", + "modifiedBy": 7586085, + "mode": "Production", + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "dataExtensionName": "Contact_Data", + "sourceApplicationExtensionId": "7db1f972-f8b7-49b6-91b5-fa218e13953d", + "filterDefinitionTemplate": "", + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "arguments": { + "serializedObjectType": 11, + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "dataExtensionId": "C25D5A59-5EBC-40C9-8D27-149831881D89", + "automationId": "00000000-0000-0000-0000-000000000000", + "criteria": "", + "useHighWatermark": false + }, + "metaData": { + "scheduleState": "No Schedule", + "criteriaDescription": "" + }, + "interactionCount": 1, + "isVisibleInPicker": true, + "isPlatformObject": false, + "category": "Event", + "publishedInteractionCount": 1, + "automationId": "00000000-0000-0000-0000-000000000000", + "disableDEDataLogging": false + } + ] +} From 94ebae4c15e298df19204da0955c9606e759a824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sun, 22 Jan 2023 01:11:53 +0100 Subject: [PATCH 065/132] #627: add test for DEPLOY interaction --- test/interaction.test.js | 38 +++ ...Existing_interaction.interaction-meta.json | 266 +++++++++++++++++ .../testNew_interaction.interaction-meta.json | 266 +++++++++++++++++ .../9999999/interaction/get-expected.json | 4 +- .../9999999/interaction/post-expected.json | 266 +++++++++++++++++ .../9999999/interaction/put-expected.json | 266 +++++++++++++++++ .../v1/interactions/get-response.json | 4 +- .../v1/interactions/post-response.json | 280 ++++++++++++++++++ .../v1/interactions/put-response.json | 280 ++++++++++++++++++ 9 files changed, 1666 insertions(+), 4 deletions(-) create mode 100644 test/mockRoot/deploy/testInstance/testBU/interaction/testExisting_interaction.interaction-meta.json create mode 100644 test/mockRoot/deploy/testInstance/testBU/interaction/testNew_interaction.interaction-meta.json create mode 100644 test/resources/9999999/interaction/post-expected.json create mode 100644 test/resources/9999999/interaction/put-expected.json create mode 100644 test/resources/9999999/interaction/v1/interactions/post-response.json create mode 100644 test/resources/9999999/interaction/v1/interactions/put-response.json diff --git a/test/interaction.test.js b/test/interaction.test.js index 969374091..10535b389 100644 --- a/test/interaction.test.js +++ b/test/interaction.test.js @@ -39,4 +39,42 @@ describe('interaction', () => { return; }); }); + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + it('Should create & upsert a interaction', async () => { + // WHEN + await handler.deploy('testInstance/testBU', ['interaction']); + // THEN + // get results from cache + const result = cache.getCache(); + assert.equal( + result.interaction ? Object.keys(result.interaction).length : 0, + 2, + 'two interactions expected' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_interaction', 'interaction'), + await testUtils.getExpectedJson('9999999', 'interaction', 'post'), + 'returned JSON was not equal expected for insert interaction' + ); + + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_interaction', 'interaction'), + await testUtils.getExpectedJson('9999999', 'interaction', 'put'), // watch out - interaction api wants put instead of patch for updates + 'returned JSON was not equal expected for update interaction' + ); + + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 7, + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + ); + return; + }); + }); }); diff --git a/test/mockRoot/deploy/testInstance/testBU/interaction/testExisting_interaction.interaction-meta.json b/test/mockRoot/deploy/testInstance/testBU/interaction/testExisting_interaction.interaction-meta.json new file mode 100644 index 000000000..e23496e93 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/interaction/testExisting_interaction.interaction-meta.json @@ -0,0 +1,266 @@ +{ + "key": "testExisting_interaction", + "name": "testExisting_interaction", + "lastPublishedDate": "2017-04-12T08:07:48", + "description": "updated via deploy", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2017-04-12T05:38:05.837", + "modifiedDate": "2017-04-12T08:07:48.333", + "activities": [ + { + "id": "69213026-bd2c-433b-8332-5f52d3e87ca5", + "key": "WAIT-1", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "bd3dff6b-565c-4b56-b9cb-60cd5b6d080b", + "next": "DATAEXTENSIONUPDATE-1", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "546704c0-9384-4a41-b20e-97615cc6cc6a", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "5d93cda9-2015-4c07-a1db-0d5853d25bf6", + "key": "WAIT-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "e3d3258a-891b-4838-b5a6-af37f8cb769a", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "deed4c9d-f487-4371-bfd9-76fca44ec49b", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "ef4db13e-83f0-4d41-981d-4bf5810c0daa", + "key": "DATAEXTENSIONUPDATE-1", + "name": "", + "description": "", + "type": "DATAEXTENSIONUPDATE", + "outcomes": [ + { + "key": "a49ecf04-4612-4582-85fe-d7193f872fa8", + "next": "WAIT-2", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { "contactKey": "{{Contact.Key}}", "value": "{{DateTime.Now}}" }, + "configurationArguments": { + "dataExtensionId": "ace267f0-b81d-e711-80cc-1402ec7222b4", + "field": "4e875b26-0317-4525-bfa0-50c8d1b7a7b5" + }, + "metaData": { + "dataExtensionName": "test_TestData", + "cachedFieldName": "JourneyConfirmed", + "cachedDisplayValue": "" + }, + "schema": { + "arguments": { + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "value": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "test_TESTDataentry", + "description": "", + "type": "APIEvent", + "outcomes": [], + "arguments": { + "filterResult": "{{Contact.FilterId.e4ddb887-6f2d-46b1-9f64-9a020f217339}}" + }, + "configurationArguments": { + "schemaVersionId": 133, + "criteria": "", + "filterDefinitionId": "e4ddb887-6f2d-46b1-9f64-9a020f217339" + }, + "metaData": { + "scheduleState": "No Schedule", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionId": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "title": "", + "category": "Event" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "OnceAndDone", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.APIEvent-60130566-e2fe-eb29-4140-15c27093a80b.\"emailAddress\"}}"], + "properties": {} + }, + "metaData": {}, + "executionMode": "Production", + "status": "Draft", + "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/interaction/testNew_interaction.interaction-meta.json b/test/mockRoot/deploy/testInstance/testBU/interaction/testNew_interaction.interaction-meta.json new file mode 100644 index 000000000..a9a5e0f27 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/interaction/testNew_interaction.interaction-meta.json @@ -0,0 +1,266 @@ +{ + "key": "testNew_interaction", + "name": "testNew_interaction", + "lastPublishedDate": "2017-04-12T08:07:48", + "description": "created on deploy", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2017-04-12T05:38:05.837", + "modifiedDate": "2017-04-12T08:07:48.333", + "activities": [ + { + "id": "69213026-bd2c-433b-8332-5f52d3e87ca5", + "key": "WAIT-1", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "bd3dff6b-565c-4b56-b9cb-60cd5b6d080b", + "next": "DATAEXTENSIONUPDATE-1", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "546704c0-9384-4a41-b20e-97615cc6cc6a", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "5d93cda9-2015-4c07-a1db-0d5853d25bf6", + "key": "WAIT-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "e3d3258a-891b-4838-b5a6-af37f8cb769a", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "deed4c9d-f487-4371-bfd9-76fca44ec49b", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "ef4db13e-83f0-4d41-981d-4bf5810c0daa", + "key": "DATAEXTENSIONUPDATE-1", + "name": "", + "description": "", + "type": "DATAEXTENSIONUPDATE", + "outcomes": [ + { + "key": "a49ecf04-4612-4582-85fe-d7193f872fa8", + "next": "WAIT-2", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { "contactKey": "{{Contact.Key}}", "value": "{{DateTime.Now}}" }, + "configurationArguments": { + "dataExtensionId": "ace267f0-b81d-e711-80cc-1402ec7222b4", + "field": "4e875b26-0317-4525-bfa0-50c8d1b7a7b5" + }, + "metaData": { + "dataExtensionName": "test_TestData", + "cachedFieldName": "JourneyConfirmed", + "cachedDisplayValue": "" + }, + "schema": { + "arguments": { + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "value": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "test_TESTDataentry", + "description": "", + "type": "APIEvent", + "outcomes": [], + "arguments": { + "filterResult": "{{Contact.FilterId.e4ddb887-6f2d-46b1-9f64-9a020f217339}}" + }, + "configurationArguments": { + "schemaVersionId": 133, + "criteria": "", + "filterDefinitionId": "e4ddb887-6f2d-46b1-9f64-9a020f217339" + }, + "metaData": { + "scheduleState": "No Schedule", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionId": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "title": "", + "category": "Event" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "OnceAndDone", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.APIEvent-60130566-e2fe-eb29-4140-15c27093a80b.\"emailAddress\"}}"], + "properties": {} + }, + "metaData": {}, + "executionMode": "Production", + "status": "Draft", + "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/interaction/get-expected.json b/test/resources/9999999/interaction/get-expected.json index b85f8ab28..303a954eb 100644 --- a/test/resources/9999999/interaction/get-expected.json +++ b/test/resources/9999999/interaction/get-expected.json @@ -2,7 +2,7 @@ "key": "testExisting_interaction", "name": "testExisting_interaction", "lastPublishedDate": "2017-04-12T08:07:48", - "description": "", + "description": "bla bla", "version": 1, "workflowApiVersion": 1, "createdDate": "2017-04-12T05:38:05.837", @@ -259,7 +259,7 @@ }, "metaData": {}, "executionMode": "Production", - "status": "Published", + "status": "Draft", "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", "scheduledStatus": "Draft", "r__folder_Path": "my journeys" diff --git a/test/resources/9999999/interaction/post-expected.json b/test/resources/9999999/interaction/post-expected.json new file mode 100644 index 000000000..a9a5e0f27 --- /dev/null +++ b/test/resources/9999999/interaction/post-expected.json @@ -0,0 +1,266 @@ +{ + "key": "testNew_interaction", + "name": "testNew_interaction", + "lastPublishedDate": "2017-04-12T08:07:48", + "description": "created on deploy", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2017-04-12T05:38:05.837", + "modifiedDate": "2017-04-12T08:07:48.333", + "activities": [ + { + "id": "69213026-bd2c-433b-8332-5f52d3e87ca5", + "key": "WAIT-1", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "bd3dff6b-565c-4b56-b9cb-60cd5b6d080b", + "next": "DATAEXTENSIONUPDATE-1", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "546704c0-9384-4a41-b20e-97615cc6cc6a", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "5d93cda9-2015-4c07-a1db-0d5853d25bf6", + "key": "WAIT-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "e3d3258a-891b-4838-b5a6-af37f8cb769a", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "deed4c9d-f487-4371-bfd9-76fca44ec49b", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "ef4db13e-83f0-4d41-981d-4bf5810c0daa", + "key": "DATAEXTENSIONUPDATE-1", + "name": "", + "description": "", + "type": "DATAEXTENSIONUPDATE", + "outcomes": [ + { + "key": "a49ecf04-4612-4582-85fe-d7193f872fa8", + "next": "WAIT-2", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { "contactKey": "{{Contact.Key}}", "value": "{{DateTime.Now}}" }, + "configurationArguments": { + "dataExtensionId": "ace267f0-b81d-e711-80cc-1402ec7222b4", + "field": "4e875b26-0317-4525-bfa0-50c8d1b7a7b5" + }, + "metaData": { + "dataExtensionName": "test_TestData", + "cachedFieldName": "JourneyConfirmed", + "cachedDisplayValue": "" + }, + "schema": { + "arguments": { + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "value": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "test_TESTDataentry", + "description": "", + "type": "APIEvent", + "outcomes": [], + "arguments": { + "filterResult": "{{Contact.FilterId.e4ddb887-6f2d-46b1-9f64-9a020f217339}}" + }, + "configurationArguments": { + "schemaVersionId": 133, + "criteria": "", + "filterDefinitionId": "e4ddb887-6f2d-46b1-9f64-9a020f217339" + }, + "metaData": { + "scheduleState": "No Schedule", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionId": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "title": "", + "category": "Event" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "OnceAndDone", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.APIEvent-60130566-e2fe-eb29-4140-15c27093a80b.\"emailAddress\"}}"], + "properties": {} + }, + "metaData": {}, + "executionMode": "Production", + "status": "Draft", + "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/interaction/put-expected.json b/test/resources/9999999/interaction/put-expected.json new file mode 100644 index 000000000..303a954eb --- /dev/null +++ b/test/resources/9999999/interaction/put-expected.json @@ -0,0 +1,266 @@ +{ + "key": "testExisting_interaction", + "name": "testExisting_interaction", + "lastPublishedDate": "2017-04-12T08:07:48", + "description": "bla bla", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2017-04-12T05:38:05.837", + "modifiedDate": "2017-04-12T08:07:48.333", + "activities": [ + { + "id": "69213026-bd2c-433b-8332-5f52d3e87ca5", + "key": "WAIT-1", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "bd3dff6b-565c-4b56-b9cb-60cd5b6d080b", + "next": "DATAEXTENSIONUPDATE-1", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "546704c0-9384-4a41-b20e-97615cc6cc6a", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "5d93cda9-2015-4c07-a1db-0d5853d25bf6", + "key": "WAIT-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "e3d3258a-891b-4838-b5a6-af37f8cb769a", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "deed4c9d-f487-4371-bfd9-76fca44ec49b", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "ef4db13e-83f0-4d41-981d-4bf5810c0daa", + "key": "DATAEXTENSIONUPDATE-1", + "name": "", + "description": "", + "type": "DATAEXTENSIONUPDATE", + "outcomes": [ + { + "key": "a49ecf04-4612-4582-85fe-d7193f872fa8", + "next": "WAIT-2", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { "contactKey": "{{Contact.Key}}", "value": "{{DateTime.Now}}" }, + "configurationArguments": { + "dataExtensionId": "ace267f0-b81d-e711-80cc-1402ec7222b4", + "field": "4e875b26-0317-4525-bfa0-50c8d1b7a7b5" + }, + "metaData": { + "dataExtensionName": "test_TestData", + "cachedFieldName": "JourneyConfirmed", + "cachedDisplayValue": "" + }, + "schema": { + "arguments": { + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "value": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "test_TESTDataentry", + "description": "", + "type": "APIEvent", + "outcomes": [], + "arguments": { + "filterResult": "{{Contact.FilterId.e4ddb887-6f2d-46b1-9f64-9a020f217339}}" + }, + "configurationArguments": { + "schemaVersionId": 133, + "criteria": "", + "filterDefinitionId": "e4ddb887-6f2d-46b1-9f64-9a020f217339" + }, + "metaData": { + "scheduleState": "No Schedule", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionId": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "title": "", + "category": "Event" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "OnceAndDone", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.APIEvent-60130566-e2fe-eb29-4140-15c27093a80b.\"emailAddress\"}}"], + "properties": {} + }, + "metaData": {}, + "executionMode": "Production", + "status": "Draft", + "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/interaction/v1/interactions/get-response.json b/test/resources/9999999/interaction/v1/interactions/get-response.json index 1f87d37a3..9cf7432fe 100644 --- a/test/resources/9999999/interaction/v1/interactions/get-response.json +++ b/test/resources/9999999/interaction/v1/interactions/get-response.json @@ -15,7 +15,7 @@ "key": "testExisting_interaction", "name": "testExisting_interaction", "lastPublishedDate": "2017-04-12T08:07:48", - "description": "", + "description": "bla bla", "version": 1, "workflowApiVersion": 1, "createdDate": "2017-04-12T05:38:05.837", @@ -288,7 +288,7 @@ "metaData": {}, "executionMode": "Production", "categoryId": 6298, - "status": "Published", + "status": "Draft", "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", "scheduledStatus": "Draft" } diff --git a/test/resources/9999999/interaction/v1/interactions/post-response.json b/test/resources/9999999/interaction/v1/interactions/post-response.json new file mode 100644 index 000000000..a40be257c --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/post-response.json @@ -0,0 +1,280 @@ +{ + "id": "233d4413-922c-4568-85a5-e5cc77efc3be", + "key": "testNew_interaction", + "name": "testNew_interaction", + "lastPublishedDate": "2017-04-12T08:07:48", + "description": "created on deploy", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2017-04-12T05:38:05.837", + "modifiedDate": "2017-04-12T08:07:48.333", + "activities": [ + { + "id": "69213026-bd2c-433b-8332-5f52d3e87ca5", + "key": "WAIT-1", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "bd3dff6b-565c-4b56-b9cb-60cd5b6d080b", + "next": "DATAEXTENSIONUPDATE-1", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "546704c0-9384-4a41-b20e-97615cc6cc6a", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "5d93cda9-2015-4c07-a1db-0d5853d25bf6", + "key": "WAIT-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "e3d3258a-891b-4838-b5a6-af37f8cb769a", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "deed4c9d-f487-4371-bfd9-76fca44ec49b", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "ef4db13e-83f0-4d41-981d-4bf5810c0daa", + "key": "DATAEXTENSIONUPDATE-1", + "name": "", + "description": "", + "type": "DATAEXTENSIONUPDATE", + "outcomes": [ + { + "key": "a49ecf04-4612-4582-85fe-d7193f872fa8", + "next": "WAIT-2", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { "contactKey": "{{Contact.Key}}", "value": "{{DateTime.Now}}" }, + "configurationArguments": { + "dataExtensionId": "ace267f0-b81d-e711-80cc-1402ec7222b4", + "field": "4e875b26-0317-4525-bfa0-50c8d1b7a7b5" + }, + "metaData": { + "dataExtensionName": "test_TestData", + "cachedFieldName": "JourneyConfirmed", + "cachedDisplayValue": "" + }, + "schema": { + "arguments": { + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "value": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "a7f8cd93-e0a6-40a5-8557-5bd6fa76c0ea", + "key": "TRIGGER", + "name": "test_TESTDataentry", + "description": "", + "type": "APIEvent", + "outcomes": [], + "arguments": { + "filterResult": "{{Contact.FilterId.e4ddb887-6f2d-46b1-9f64-9a020f217339}}" + }, + "configurationArguments": { + "schemaVersionId": 133, + "criteria": "", + "filterDefinitionId": "e4ddb887-6f2d-46b1-9f64-9a020f217339" + }, + "metaData": { + "scheduleState": "No Schedule", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionId": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "title": "", + "category": "Event" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 5848, + "cumulativePopulation": 3019, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "healthStats": { + "currentlyInCount": 0, + "delayedContactCount": 0, + "delayedMinuteInterval": 60 + }, + "entryMode": "OnceAndDone", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.APIEvent-60130566-e2fe-eb29-4140-15c27093a80b.\"emailAddress\"}}"], + "properties": {} + }, + "metaData": {}, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/put-response.json b/test/resources/9999999/interaction/v1/interactions/put-response.json new file mode 100644 index 000000000..d29bdfb14 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/put-response.json @@ -0,0 +1,280 @@ +{ + "id": "233d4413-922c-4568-85a5-e5cc77efc3be", + "key": "testExisting_interaction", + "name": "testExisting_interaction", + "lastPublishedDate": "2017-04-12T08:07:48", + "description": "bla bla", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2017-04-12T05:38:05.837", + "modifiedDate": "2017-04-12T08:07:48.333", + "activities": [ + { + "id": "69213026-bd2c-433b-8332-5f52d3e87ca5", + "key": "WAIT-1", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "bd3dff6b-565c-4b56-b9cb-60cd5b6d080b", + "next": "DATAEXTENSIONUPDATE-1", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "546704c0-9384-4a41-b20e-97615cc6cc6a", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "5d93cda9-2015-4c07-a1db-0d5853d25bf6", + "key": "WAIT-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "e3d3258a-891b-4838-b5a6-af37f8cb769a", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "deed4c9d-f487-4371-bfd9-76fca44ec49b", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "ef4db13e-83f0-4d41-981d-4bf5810c0daa", + "key": "DATAEXTENSIONUPDATE-1", + "name": "", + "description": "", + "type": "DATAEXTENSIONUPDATE", + "outcomes": [ + { + "key": "a49ecf04-4612-4582-85fe-d7193f872fa8", + "next": "WAIT-2", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { "contactKey": "{{Contact.Key}}", "value": "{{DateTime.Now}}" }, + "configurationArguments": { + "dataExtensionId": "ace267f0-b81d-e711-80cc-1402ec7222b4", + "field": "4e875b26-0317-4525-bfa0-50c8d1b7a7b5" + }, + "metaData": { + "dataExtensionName": "test_TestData", + "cachedFieldName": "JourneyConfirmed", + "cachedDisplayValue": "" + }, + "schema": { + "arguments": { + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "value": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "a7f8cd93-e0a6-40a5-8557-5bd6fa76c0ea", + "key": "TRIGGER", + "name": "test_TESTDataentry", + "description": "", + "type": "APIEvent", + "outcomes": [], + "arguments": { + "filterResult": "{{Contact.FilterId.e4ddb887-6f2d-46b1-9f64-9a020f217339}}" + }, + "configurationArguments": { + "schemaVersionId": 133, + "criteria": "", + "filterDefinitionId": "e4ddb887-6f2d-46b1-9f64-9a020f217339" + }, + "metaData": { + "scheduleState": "No Schedule", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionId": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "title": "", + "category": "Event" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 5848, + "cumulativePopulation": 3019, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "healthStats": { + "currentlyInCount": 0, + "delayedContactCount": 0, + "delayedMinuteInterval": 60 + }, + "entryMode": "OnceAndDone", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.APIEvent-60130566-e2fe-eb29-4140-15c27093a80b.\"emailAddress\"}}"], + "properties": {} + }, + "metaData": {}, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", + "scheduledStatus": "Draft" +} From ea32519e7b0079f61b1c96c73228320eb81ff659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sun, 22 Jan 2023 01:49:41 +0100 Subject: [PATCH 066/132] #627: add test for TEMPLATE interaction required disabling escaping in Mustache and hard-wiring the use of triple curly-brackets to avoid replacemetns on the double-curly-brackets that occur in journey jsons. --- lib/metadataTypes/MetadataType.js | 15 +- lib/metadataTypes/Query.js | 11 +- test/interaction.test.js | 43 +++ .../9999999/interaction/build-expected.json | 262 ++++++++++++++++++ .../interaction/template-expected.json | 262 ++++++++++++++++++ 5 files changed, 589 insertions(+), 4 deletions(-) create mode 100644 test/resources/9999999/interaction/build-expected.json create mode 100644 test/resources/9999999/interaction/template-expected.json diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index ca46eb164..154c59bc9 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -15,6 +15,15 @@ const cache = require('../util/cache'); const deepEqual = require('deep-equal'); const pLimit = require('p-limit'); const Mustache = require('mustache'); +/** + * ensure that Mustache does not escape any characters + * + * @param {string} text - + * @returns {string} text + */ +Mustache.escape = function (text) { + return text; +}; /** * MetadataType class that gets extended by their specific metadata type class. @@ -1337,7 +1346,7 @@ class MetadataType { */ static applyTemplateValues(code, templateVariables) { // replace template variables with their values - return Mustache.render(code, templateVariables); + return Mustache.render(code, templateVariables, {}, ['{{{', '}}}']); } /** * helper for {@link buildTemplateForNested} @@ -1470,8 +1479,8 @@ class MetadataType { let metadata; try { // update all initial variables & create metadata object - metadata = JSON.parse(Mustache.render(metadataStr, variables)); - typeDirArr = typeDirArr.map((el) => Mustache.render(el, variables)); + metadata = JSON.parse(Mustache.render(metadataStr, variables, {}, ['{{{', '}}}'])); + typeDirArr = typeDirArr.map((el) => Mustache.render(el, variables, {}, ['{{{', '}}}'])); } catch { throw new Error( `${this.definition.type}:: Error applying template variables on ${ diff --git a/lib/metadataTypes/Query.js b/lib/metadataTypes/Query.js index a5f1eaba8..02eb3f489 100644 --- a/lib/metadataTypes/Query.js +++ b/lib/metadataTypes/Query.js @@ -5,6 +5,15 @@ const MetadataType = require('./MetadataType'); const File = require('../util/file'); const cache = require('../util/cache'); const Mustache = require('mustache'); +/** + * ensure that Mustache does not escape any characters + * + * @param {string} text - + * @returns {string} text + */ +Mustache.escape = function (text) { + return text; +}; /** * Query MetadataType @@ -157,7 +166,7 @@ class Query extends MetadataType { .join('}}}'); // replace template variables with their values - return Mustache.render(code, templateVariables); + return Mustache.render(code, templateVariables, {}, ['{{{', '}}}']); } /** * helper for {@link MetadataType.buildDefinition} diff --git a/test/interaction.test.js b/test/interaction.test.js index 10535b389..be4703353 100644 --- a/test/interaction.test.js +++ b/test/interaction.test.js @@ -77,4 +77,47 @@ describe('interaction', () => { return; }); }); + describe('Templating ================', () => { + it('Should create a interaction template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['interaction']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'interaction', + ['testExisting_interaction'], + 'testSourceMarket' + ); + assert.equal( + result.interaction ? Object.keys(result.interaction).length : 0, + 1, + 'only one interaction expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_interaction', 'interaction'), + await testUtils.getExpectedJson('9999999', 'interaction', 'template'), + 'returned template JSON was not equal expected' + ); + + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'interaction', + 'testExisting_interaction', + 'testTargetMarket' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testExisting_interaction', 'interaction'), + await testUtils.getExpectedJson('9999999', 'interaction', 'build'), + 'returned deployment JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + ); + return; + }); + }); }); diff --git a/test/resources/9999999/interaction/build-expected.json b/test/resources/9999999/interaction/build-expected.json new file mode 100644 index 000000000..5dbd765d4 --- /dev/null +++ b/test/resources/9999999/interaction/build-expected.json @@ -0,0 +1,262 @@ +{ + "key": "testExisting_interaction", + "name": "testExisting_interaction", + "description": "foobar", + "workflowApiVersion": 1, + "modifiedDate": "2017-04-12T08:07:48.333", + "activities": [ + { + "id": "69213026-bd2c-433b-8332-5f52d3e87ca5", + "key": "WAIT-1", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "bd3dff6b-565c-4b56-b9cb-60cd5b6d080b", + "next": "DATAEXTENSIONUPDATE-1", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "546704c0-9384-4a41-b20e-97615cc6cc6a", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "5d93cda9-2015-4c07-a1db-0d5853d25bf6", + "key": "WAIT-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "e3d3258a-891b-4838-b5a6-af37f8cb769a", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "deed4c9d-f487-4371-bfd9-76fca44ec49b", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "ef4db13e-83f0-4d41-981d-4bf5810c0daa", + "key": "DATAEXTENSIONUPDATE-1", + "name": "", + "description": "", + "type": "DATAEXTENSIONUPDATE", + "outcomes": [ + { + "key": "a49ecf04-4612-4582-85fe-d7193f872fa8", + "next": "WAIT-2", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { "contactKey": "{{Contact.Key}}", "value": "{{DateTime.Now}}" }, + "configurationArguments": { + "dataExtensionId": "ace267f0-b81d-e711-80cc-1402ec7222b4", + "field": "4e875b26-0317-4525-bfa0-50c8d1b7a7b5" + }, + "metaData": { + "dataExtensionName": "test_TestData", + "cachedFieldName": "JourneyConfirmed", + "cachedDisplayValue": "" + }, + "schema": { + "arguments": { + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "value": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "test_TESTDataentry", + "description": "", + "type": "APIEvent", + "outcomes": [], + "arguments": { + "filterResult": "{{Contact.FilterId.e4ddb887-6f2d-46b1-9f64-9a020f217339}}" + }, + "configurationArguments": { + "schemaVersionId": 133, + "criteria": "", + "filterDefinitionId": "e4ddb887-6f2d-46b1-9f64-9a020f217339" + }, + "metaData": { + "scheduleState": "No Schedule", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionId": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "title": "", + "category": "Event" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "OnceAndDone", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.APIEvent-60130566-e2fe-eb29-4140-15c27093a80b.\"emailAddress\"}}"], + "properties": {} + }, + "metaData": {}, + "executionMode": "Production", + "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/interaction/template-expected.json b/test/resources/9999999/interaction/template-expected.json new file mode 100644 index 000000000..84f25a93b --- /dev/null +++ b/test/resources/9999999/interaction/template-expected.json @@ -0,0 +1,262 @@ +{ + "key": "testExisting_interaction", + "name": "testExisting_interaction", + "description": "{{{description}}}", + "workflowApiVersion": 1, + "modifiedDate": "2017-04-12T08:07:48.333", + "activities": [ + { + "id": "69213026-bd2c-433b-8332-5f52d3e87ca5", + "key": "WAIT-1", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "bd3dff6b-565c-4b56-b9cb-60cd5b6d080b", + "next": "DATAEXTENSIONUPDATE-1", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "546704c0-9384-4a41-b20e-97615cc6cc6a", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "5d93cda9-2015-4c07-a1db-0d5853d25bf6", + "key": "WAIT-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "e3d3258a-891b-4838-b5a6-af37f8cb769a", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "deed4c9d-f487-4371-bfd9-76fca44ec49b", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "ef4db13e-83f0-4d41-981d-4bf5810c0daa", + "key": "DATAEXTENSIONUPDATE-1", + "name": "", + "description": "", + "type": "DATAEXTENSIONUPDATE", + "outcomes": [ + { + "key": "a49ecf04-4612-4582-85fe-d7193f872fa8", + "next": "WAIT-2", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { "contactKey": "{{Contact.Key}}", "value": "{{DateTime.Now}}" }, + "configurationArguments": { + "dataExtensionId": "ace267f0-b81d-e711-80cc-1402ec7222b4", + "field": "4e875b26-0317-4525-bfa0-50c8d1b7a7b5" + }, + "metaData": { + "dataExtensionName": "test_TestData", + "cachedFieldName": "JourneyConfirmed", + "cachedDisplayValue": "" + }, + "schema": { + "arguments": { + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "value": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "test_TESTDataentry", + "description": "", + "type": "APIEvent", + "outcomes": [], + "arguments": { + "filterResult": "{{Contact.FilterId.e4ddb887-6f2d-46b1-9f64-9a020f217339}}" + }, + "configurationArguments": { + "schemaVersionId": 133, + "criteria": "", + "filterDefinitionId": "e4ddb887-6f2d-46b1-9f64-9a020f217339" + }, + "metaData": { + "scheduleState": "No Schedule", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionId": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "title": "", + "category": "Event" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "OnceAndDone", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.APIEvent-60130566-e2fe-eb29-4140-15c27093a80b.\"emailAddress\"}}"], + "properties": {} + }, + "metaData": {}, + "executionMode": "Production", + "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} From 2ee301d563f11bf77a58a1459dbc6bfe406e6aa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sun, 22 Jan 2023 02:27:36 +0100 Subject: [PATCH 067/132] #635: fix warnings during test execution --- lib/metadataTypes/List.js | 9 +++++++-- .../testExisting_temail.transactionalEmail-meta.json | 3 --- .../messaging/v1/email/definitions/post-response.json | 2 +- .../9999999/transactionalEmail/post-expected.json | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/metadataTypes/List.js b/lib/metadataTypes/List.js index a13146000..2646ac17a 100644 --- a/lib/metadataTypes/List.js +++ b/lib/metadataTypes/List.js @@ -93,6 +93,7 @@ class List extends MetadataType { businessUnit: Util.parentBuName, credential: buObject.credential, }; + const clientBackup = this.client; try { this.client = auth.getSDK(buObjectParentBu); } catch (ex) { @@ -136,16 +137,20 @@ class List extends MetadataType { } } + // revert client to current default + this.client = clientBackup; + // make sure to overwrite parent bu DEs with local ones return { metadata: { ...metadataParentBu.metadata, ...results.metadata }, type: results.type, }; } else if (masterUnsubscribeBehavior === 'BUSINESS_UNIT_ONLY') { + // revert client to current default + this.client = clientBackup; + Util.logger.debug(' - BU uses own All Subscriber List'); } - // revert client to current default - this.client = auth.getSDK(this.buObject); } return results; } diff --git a/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json b/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json index 9d6c10fea..564d90cee 100644 --- a/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json +++ b/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json @@ -17,8 +17,5 @@ }, "options": { "trackLinks": true - }, - "journey": { - "interactionKey": "testExisting_interaction" } } diff --git a/test/resources/9999999/messaging/v1/email/definitions/post-response.json b/test/resources/9999999/messaging/v1/email/definitions/post-response.json index 0b2f8e238..eec361607 100644 --- a/test/resources/9999999/messaging/v1/email/definitions/post-response.json +++ b/test/resources/9999999/messaging/v1/email/definitions/post-response.json @@ -15,5 +15,5 @@ "updateSubscriber": true }, "options": { "trackLinks": true }, - "journey": { "interactionKey": "1f936b41-cf1b-4207-aa33-715b3bf9eab7" } + "journey": { "interactionKey": "testExisting_interaction" } } diff --git a/test/resources/9999999/transactionalEmail/post-expected.json b/test/resources/9999999/transactionalEmail/post-expected.json index 5f94f6127..3865215c2 100644 --- a/test/resources/9999999/transactionalEmail/post-expected.json +++ b/test/resources/9999999/transactionalEmail/post-expected.json @@ -19,6 +19,6 @@ "trackLinks": true }, "journey": { - "interactionKey": "1f936b41-cf1b-4207-aa33-715b3bf9eab7" + "interactionKey": "testExisting_interaction" } } From aaa7b97a8ea971d8561695dbea732a41ba033746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sun, 22 Jan 2023 04:02:14 +0100 Subject: [PATCH 068/132] #646: initial version of mcdev join (project) --- docs/dist/documentation.md | 40 +++++++++++++++++++++ lib/cli.js | 9 +++++ lib/index.js | 9 +++++ lib/util/init.js | 71 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 3e9331bb9..e7ef8ae4f 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -470,6 +470,7 @@ main class * [.retrieve(businessUnit, [selectedTypesArr], [keys], [changelogOnly])](#Mcdev.retrieve) ⇒ Promise.<object> * [.deploy(businessUnit, [selectedTypesArr], [keyArr], [fromRetrieve])](#Mcdev.deploy) ⇒ Promise.<Object.<string, TYPE.MultiMetadataTypeMap>> * [.initProject([credentialsName])](#Mcdev.initProject) ⇒ Promise.<void> + * [.joinProject()](#Mcdev.joinProject) ⇒ Promise.<void> * [.findBUs(credentialsName)](#Mcdev.findBUs) ⇒ Promise.<void> * [.document(businessUnit, type)](#Mcdev.document) ⇒ Promise.<void> * [.deleteByKey(businessUnit, type, customerKey)](#Mcdev.deleteByKey) ⇒ Promise.<void> @@ -576,6 +577,13 @@ Creates template file for properties.json | --- | --- | --- | | [credentialsName] | string | identifying name of the installed package / project | + + +### Mcdev.joinProject() ⇒ Promise.<void> +Clones an existing project from git repository and installs it + +**Kind**: static method of [Mcdev](#Mcdev) +**Returns**: Promise.<void> - - ### Mcdev.findBUs(credentialsName) ⇒ Promise.<void> @@ -5750,6 +5758,7 @@ CLI helper class * [._updateGitConfigUser()](#Init._updateGitConfigUser) ⇒ void * [._getGitConfigUser()](#Init._getGitConfigUser) ⇒ Promise.<{'user.name': string, 'user.email': string}> * [.initProject(properties, credentialName)](#Init.initProject) ⇒ Promise.<void> + * [.joinProject()](#Init.joinProject) ⇒ Promise.<void> * [._initMarkets()](#Init._initMarkets) * [._downloadAllBUs(bu, gitStatus)](#Init._downloadAllBUs) ⇒ Promise.<void> * [.upgradeProject(properties, [initial], [repoName])](#Init.upgradeProject) ⇒ Promise.<boolean> @@ -5873,6 +5882,13 @@ Creates template file for properties.json | properties | TYPE.Mcdevrc | config file's json | | credentialName | string | identifying name of the installed package / project | + + +### Init.joinProject() ⇒ Promise.<void> +Creates template file for properties.json + +**Kind**: static method of [Init](#Init) +**Returns**: Promise.<void> - - ### Init.\_initMarkets() @@ -5964,6 +5980,7 @@ CLI helper class * [._updateGitConfigUser()](#Init._updateGitConfigUser) ⇒ void * [._getGitConfigUser()](#Init._getGitConfigUser) ⇒ Promise.<{'user.name': string, 'user.email': string}> * [.initProject(properties, credentialName)](#Init.initProject) ⇒ Promise.<void> + * [.joinProject()](#Init.joinProject) ⇒ Promise.<void> * [._initMarkets()](#Init._initMarkets) * [._downloadAllBUs(bu, gitStatus)](#Init._downloadAllBUs) ⇒ Promise.<void> * [.upgradeProject(properties, [initial], [repoName])](#Init.upgradeProject) ⇒ Promise.<boolean> @@ -6087,6 +6104,13 @@ Creates template file for properties.json | properties | TYPE.Mcdevrc | config file's json | | credentialName | string | identifying name of the installed package / project | + + +### Init.joinProject() ⇒ Promise.<void> +Creates template file for properties.json + +**Kind**: static method of [Init](#Init) +**Returns**: Promise.<void> - - ### Init.\_initMarkets() @@ -6178,6 +6202,7 @@ CLI helper class * [._updateGitConfigUser()](#Init._updateGitConfigUser) ⇒ void * [._getGitConfigUser()](#Init._getGitConfigUser) ⇒ Promise.<{'user.name': string, 'user.email': string}> * [.initProject(properties, credentialName)](#Init.initProject) ⇒ Promise.<void> + * [.joinProject()](#Init.joinProject) ⇒ Promise.<void> * [._initMarkets()](#Init._initMarkets) * [._downloadAllBUs(bu, gitStatus)](#Init._downloadAllBUs) ⇒ Promise.<void> * [.upgradeProject(properties, [initial], [repoName])](#Init.upgradeProject) ⇒ Promise.<boolean> @@ -6301,6 +6326,13 @@ Creates template file for properties.json | properties | TYPE.Mcdevrc | config file's json | | credentialName | string | identifying name of the installed package / project | + + +### Init.joinProject() ⇒ Promise.<void> +Creates template file for properties.json + +**Kind**: static method of [Init](#Init) +**Returns**: Promise.<void> - - ### Init.\_initMarkets() @@ -6392,6 +6424,7 @@ CLI helper class * [._updateGitConfigUser()](#Init._updateGitConfigUser) ⇒ void * [._getGitConfigUser()](#Init._getGitConfigUser) ⇒ Promise.<{'user.name': string, 'user.email': string}> * [.initProject(properties, credentialName)](#Init.initProject) ⇒ Promise.<void> + * [.joinProject()](#Init.joinProject) ⇒ Promise.<void> * [._initMarkets()](#Init._initMarkets) * [._downloadAllBUs(bu, gitStatus)](#Init._downloadAllBUs) ⇒ Promise.<void> * [.upgradeProject(properties, [initial], [repoName])](#Init.upgradeProject) ⇒ Promise.<boolean> @@ -6515,6 +6548,13 @@ Creates template file for properties.json | properties | TYPE.Mcdevrc | config file's json | | credentialName | string | identifying name of the installed package / project | + + +### Init.joinProject() ⇒ Promise.<void> +Creates template file for properties.json + +**Kind**: static method of [Init](#Init) +**Returns**: Promise.<void> - - ### Init.\_initMarkets() diff --git a/lib/cli.js b/lib/cli.js index 2c6fcc474..467c1b2ea 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -84,6 +84,15 @@ yargs Mcdev.initProject(argv.credentialsName); }, }) + .command({ + command: 'join', + desc: `clones an existing project from git`, + handler: (argv) => { + Mcdev.setSkipInteraction(argv.skipInteraction); + Mcdev.setLoggingLevel(argv); + Mcdev.joinProject(); + }, + }) .command({ command: 'reloadBUs [credentialsName]', aliases: ['rb'], diff --git a/lib/index.js b/lib/index.js index ee98a608a..a2ffe25ca 100644 --- a/lib/index.js +++ b/lib/index.js @@ -293,6 +293,15 @@ class Mcdev { const properties = await config.getProperties(!!credentialsName, true); await Init.initProject(properties, credentialsName); } + /** + * Clones an existing project from git repository and installs it + * + * @returns {Promise.} - + */ + static async joinProject() { + Util.logger.info('mcdev:: Joining an existing project'); + await Init.joinProject(); + } /** * Refreshes BU names and ID's from MC instance diff --git a/lib/util/init.js b/lib/util/init.js index 43980a3ba..6b9507025 100644 --- a/lib/util/init.js +++ b/lib/util/init.js @@ -186,6 +186,77 @@ const Init = { } }, + /** + * Creates template file for properties.json + * + * @returns {Promise.} - + */ + async joinProject() { + const responses = await inquirer.prompt([ + { + type: 'confirm', + name: 'isJoin', + message: + 'Do you want to join an existing project for which you have a Git-Repository URL?', + default: true, + }, + ]); + if (responses.isJoin) { + const gitRepoQs = await inquirer.prompt([ + { + type: 'input', + name: 'gitRepoUrl', + message: 'Please enter the Git-Repository URL', + }, + { + type: 'input', + name: 'gitBranch', + message: + 'If you were asked to work on a specific branch, please enter it now (or leave empty for default)', + }, + ]); + const repoName = gitRepoQs.gitRepoUrl.split('/').pop().replace('.git', ''); + const projectFolder = await inquirer.prompt([ + { + type: 'confirm', + name: 'isCreate', + message: `Do you want to clone the repository into the subfolder ${repoName}? If you choose "no", the repository will be cloned into the current folder.`, + default: true, + }, + ]); + if (!projectFolder.isCreate) { + // we likely created a logs folder by now which would block git clone + await File.rm('./logs', { recursive: true, force: true }); + } + // clone repo into current folder + Util.execSync( + 'git', + [ + 'clone', + gitRepoQs.gitBranch ? `--branch ${gitRepoQs.gitBranch}` : null, + '--config core.longpaths=true', + '--config core.autocrlf=input', + gitRepoQs.gitRepoUrl, + projectFolder.isCreate ? null : './', + ].filter(Boolean) + ); + if (projectFolder.isCreate) { + process.chdir(repoName); + } + await InitGit._updateGitConfigUser(); + + const properties = await config.getProperties(true, true); + if (!properties) { + Util.logger.error( + 'Could not find .mcdevrc.json file in project folder. Please check your Git repository and branch.' + ); + return; + } + await this.initProject(properties); + } else { + return; + } + }, /** * helper for @initProject that optionally creates markets and market lists for all BUs */ From 6a4f264b798f9641e22dc9a3467078d632705879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sun, 22 Jan 2023 04:05:19 +0100 Subject: [PATCH 069/132] #646: remove option to clone to current folder broke due to auto-created logs folder --- lib/util/init.js | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/lib/util/init.js b/lib/util/init.js index 6b9507025..e095e0006 100644 --- a/lib/util/init.js +++ b/lib/util/init.js @@ -216,18 +216,6 @@ const Init = { }, ]); const repoName = gitRepoQs.gitRepoUrl.split('/').pop().replace('.git', ''); - const projectFolder = await inquirer.prompt([ - { - type: 'confirm', - name: 'isCreate', - message: `Do you want to clone the repository into the subfolder ${repoName}? If you choose "no", the repository will be cloned into the current folder.`, - default: true, - }, - ]); - if (!projectFolder.isCreate) { - // we likely created a logs folder by now which would block git clone - await File.rm('./logs', { recursive: true, force: true }); - } // clone repo into current folder Util.execSync( 'git', @@ -237,14 +225,15 @@ const Init = { '--config core.longpaths=true', '--config core.autocrlf=input', gitRepoQs.gitRepoUrl, - projectFolder.isCreate ? null : './', ].filter(Boolean) ); - if (projectFolder.isCreate) { - process.chdir(repoName); - } + // make sure we switch to the new subfolder or else the rest will fail + process.chdir(repoName); + + // get name and email that's to be used for git commits await InitGit._updateGitConfigUser(); + // ask the user to enter the server credentials const properties = await config.getProperties(true, true); if (!properties) { Util.logger.error( From 9a0f75a3d870ed00029d0941d854513491c3202c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sun, 22 Jan 2023 04:12:00 +0100 Subject: [PATCH 070/132] #646: check for config before asking for more input --- lib/util/init.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/util/init.js b/lib/util/init.js index e095e0006..22aa7b966 100644 --- a/lib/util/init.js +++ b/lib/util/init.js @@ -230,10 +230,7 @@ const Init = { // make sure we switch to the new subfolder or else the rest will fail process.chdir(repoName); - // get name and email that's to be used for git commits - await InitGit._updateGitConfigUser(); - - // ask the user to enter the server credentials + // check if the branch looks good const properties = await config.getProperties(true, true); if (!properties) { Util.logger.error( @@ -241,6 +238,11 @@ const Init = { ); return; } + + // get name and email that's to be used for git commits + await InitGit._updateGitConfigUser(); + + // ask the user to enter the server credentials await this.initProject(properties); } else { return; From 39a96b1919f22ce6c79cfbcabad85f40cb7762cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 23 Jan 2023 10:28:39 +0100 Subject: [PATCH 071/132] #627: promoted to retrieve-by-default --- lib/metadataTypes/definitions/EventDefinition.definition.js | 2 +- lib/metadataTypes/definitions/Interaction.definition.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/metadataTypes/definitions/EventDefinition.definition.js b/lib/metadataTypes/definitions/EventDefinition.definition.js index faa5b804e..8af115fc0 100644 --- a/lib/metadataTypes/definitions/EventDefinition.definition.js +++ b/lib/metadataTypes/definitions/EventDefinition.definition.js @@ -12,7 +12,7 @@ module.exports = { restPagination: true, type: 'eventDefinition', typeDescription: 'Used in Journeys (Interactions) to define Entry Events.', - typeRetrieveByDefault: false, + typeRetrieveByDefault: true, typeName: 'Journey: Entry Event Definition', fields: { 'arguments.automationId': { diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index 7371dd3fe..b99d0aa97 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -16,8 +16,8 @@ module.exports = { lastmodNameField: null, restPagination: true, type: 'interaction', - typeDescription: 'Journey from Builder (internally called "Interaction").', - typeRetrieveByDefault: false, + typeDescription: 'Journey (internally called "Interaction").', + typeRetrieveByDefault: true, typeName: 'Journey', fields: { activities: { From e57857a9ca0a5a6f4a1e8b99e53cb1817e7477f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 23 Jan 2023 12:52:52 +0100 Subject: [PATCH 072/132] #627: auto-trim leading %23 / # from ID --- lib/metadataTypes/Interaction.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 9e0e13bcf..1848ca1d5 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -29,9 +29,13 @@ class Interaction extends MetadataType { /* eslint-disable unicorn/prefer-ternary */ if (key.startsWith('id:')) { // ! allow selecting journeys by ID because that's what users see in the URL - singleKey = '/' + key.slice(3); + singleKey = key.slice(3); + if (singleKey.startsWith('%23')) { + // in the journey URL the Id is prefixed with an HTML-encoded "#" which could accidentally be copied by users + singleKey = singleKey.slice(3); + } } else { - singleKey = '/key:' + encodeURIComponent(key); + singleKey = 'key:' + encodeURIComponent(key); } /* eslint-enable unicorn/prefer-ternary */ } @@ -40,7 +44,7 @@ class Interaction extends MetadataType { return super.retrieveREST( retrieveDir, - `/interaction/v1/interactions${singleKey}?extras=${extras}`, + `/interaction/v1/interactions/${singleKey}?extras=${extras}`, null, null, key @@ -65,6 +69,10 @@ class Interaction extends MetadataType { if (key.startsWith('id:')) { // ! allow selecting journeys by ID because that's what users see in the URL singleKey = key.slice(3); + if (singleKey.startsWith('%23')) { + // in the journey URL the Id is prefixed with an HTML-encoded "#" which could accidentally be copied by users + singleKey = singleKey.slice(3); + } } else { // delete by key with specified version does not work, therefore we need to get the ID first const response = await this.client.rest.get( From 0d4d49623a0a6ff8281ac7141578dbf7f9c32311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 23 Jan 2023 13:06:53 +0100 Subject: [PATCH 073/132] #627: clarify the limitation to journeys --- lib/metadataTypes/MetadataType.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 154c59bc9..828a7cfb8 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -867,6 +867,7 @@ class MetadataType { } } else if (singleRetrieve) { // some types will return a single item intead of an array if the key is supported by their api + // ! currently, the id: prefix is only supported by journey (interaction) if (singleRetrieve.startsWith('id:')) { singleRetrieve = body[keyField]; } From 2b86ff886973033ec90b5ef53ac1dd2c30804e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 23 Jan 2023 13:16:11 +0100 Subject: [PATCH 074/132] #627: auto-trim appended version for retrieve-by-id --- lib/metadataTypes/Interaction.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 1848ca1d5..e1b417b60 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -34,6 +34,10 @@ class Interaction extends MetadataType { // in the journey URL the Id is prefixed with an HTML-encoded "#" which could accidentally be copied by users singleKey = singleKey.slice(3); } + if (singleKey.includes('/')) { + // in the journey URL the version is appended after the ID, separated by a forward-slash. Needs to be removed from the ID for the retrieve + singleKey = singleKey.split('/')[0]; + } } else { singleKey = 'key:' + encodeURIComponent(key); } From 780d03a0ff171fa6b76b02ee2a9ac52ba8a9811c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 23 Jan 2023 16:29:56 +0100 Subject: [PATCH 075/132] #627: removed definitionId - it's basically the ID of the journey's version. --- docs/dist/documentation.md | 15 ++++++++++++--- .../definitions/Interaction.definition.js | 6 +++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index f6fa20cc9..d5f443ca3 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -74,7 +74,11 @@ as this is a configuration in the EID

ImportFile MetadataType

InteractionMetadataType
-

Script MetadataType

+

Interaction MetadataType +! BETA RELEASE of journey support (v4.3.0); it so far only resolves a limited amount of dependencies and will likely break during cross-BU deployments! +id: A unique id of the journey assigned by the journey’s API during its creation +key: A unique id of the journey within the MID. Can be generated by the developer +definitionId: A unique UUID provided by Salesforce Marketing Cloud. Each version of a journey has a unique DefinitionID while the Id and Key remain the same. Version 1 will have id == definitionId

ListMetadataType

List MetadataType

@@ -2914,7 +2918,11 @@ parses retrieved Metadata before saving ## Interaction ⇐ [MetadataType](#MetadataType) -Script MetadataType +Interaction MetadataType +! BETA RELEASE of journey support (v4.3.0); it so far only resolves a limited amount of dependencies and will likely break during cross-BU deployments! +id: A unique id of the journey assigned by the journey’s API during its creation +key: A unique id of the journey within the MID. Can be generated by the developer +definitionId: A unique UUID provided by Salesforce Marketing Cloud. Each version of a journey has a unique DefinitionID while the Id and Key remain the same. Version 1 will have id == definitionId **Kind**: global class **Extends**: [MetadataType](#MetadataType) @@ -2932,7 +2940,6 @@ Script MetadataType ### Interaction.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of Interaction -Endpoint /interaction/v1/interactions?extras=all&pageSize=50000 return 50000 Scripts with all details. **Kind**: static method of [Interaction](#Interaction) **Returns**: Promise.<TYPE.MetadataTypeMapObj> - Promise @@ -2987,6 +2994,7 @@ Creates a single item ### Interaction.postRetrieveTasks(metadata) ⇒ TYPE.MetadataTypeItem manages post retrieve steps +! BETA RELEASE of journey support (v4.3.0); it so far only resolves a limited amount of dependencies and will likely break during cross-BU deployments! **Kind**: static method of [Interaction](#Interaction) **Returns**: TYPE.MetadataTypeItem - Array with one metadata object and one query string @@ -2999,6 +3007,7 @@ manages post retrieve steps ### Interaction.preDeployTasks(metadata) ⇒ TYPE.MetadataTypeItem prepares a TSD for deployment +! BETA RELEASE of journey support (v4.3.0); it so far only resolves a limited amount of dependencies and will likely break during cross-BU deployments! **Kind**: static method of [Interaction](#Interaction) **Returns**: TYPE.MetadataTypeItem - metadata object diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index b99d0aa97..f4734dae1 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -67,9 +67,9 @@ module.exports = { }, definitionId: { isCreateable: false, - isUpdateable: true, - retrieving: true, - template: true, + isUpdateable: false, + retrieving: false, + template: false, }, definitionType: { isCreateable: true, From 2ff750803b3a27753acad6f18eef80de0938bba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 23 Jan 2023 16:58:11 +0100 Subject: [PATCH 076/132] #627: show "Downloaded (0)" if key/id and don't stop on these API-errors --- lib/metadataTypes/Interaction.js | 42 ++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index e1b417b60..e3b3cded3 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -7,14 +7,17 @@ const cache = require('../util/cache'); const File = require('../util/file'); /** - * Script MetadataType + * Interaction MetadataType + * ! BETA RELEASE of journey support (v4.3.0); it so far only resolves a limited amount of dependencies and will likely break during cross-BU deployments! + * id: A unique id of the journey assigned by the journey’s API during its creation + * key: A unique id of the journey within the MID. Can be generated by the developer + * definitionId: A unique UUID provided by Salesforce Marketing Cloud. Each version of a journey has a unique DefinitionID while the Id and Key remain the same. Version 1 will have id == definitionId * * @augments MetadataType */ class Interaction extends MetadataType { /** * Retrieves Metadata of Interaction - * Endpoint /interaction/v1/interactions?extras=all&pageSize=50000 return 50000 Scripts with all details. * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter @@ -23,8 +26,9 @@ class Interaction extends MetadataType { * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise */ - static retrieve(retrieveDir, _, __, ___, key) { + static async retrieve(retrieveDir, _, __, ___, key) { let singleKey = ''; + let mode = 'key'; if (key) { /* eslint-disable unicorn/prefer-ternary */ if (key.startsWith('id:')) { @@ -38,6 +42,7 @@ class Interaction extends MetadataType { // in the journey URL the version is appended after the ID, separated by a forward-slash. Needs to be removed from the ID for the retrieve singleKey = singleKey.split('/')[0]; } + mode = 'id'; } else { singleKey = 'key:' + encodeURIComponent(key); } @@ -46,13 +51,30 @@ class Interaction extends MetadataType { // full details for retrieve, only base data for caching; reduces caching time from minutes to seconds const extras = retrieveDir ? 'all' : ''; - return super.retrieveREST( - retrieveDir, - `/interaction/v1/interactions/${singleKey}?extras=${extras}`, - null, - null, - key - ); + try { + return await super.retrieveREST( + retrieveDir, + `/interaction/v1/interactions/${singleKey}?extras=${extras}`, + null, + null, + key + ); + } catch (ex) { + if ( + [ + 'Interaction matching key not found.', + 'Must provide a valid ID or Key parameter', + ].includes(ex.message) + ) { + Util.logger.info( + `Downloaded: ${this.definition.type} (0) (${ + mode === 'key' ? `Key: ${key}` : `ID: ${singleKey}` + })` + ); + } else { + throw ex; + } + } } /** * Delete a metadata item from the specified business unit From 5131aa92c3709d54eadabf0a27a73ed29e158c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 23 Jan 2023 17:12:38 +0100 Subject: [PATCH 077/132] #627: advanced interaction-dependency resolution --- lib/metadataTypes/Interaction.js | 427 ++++++++++++++++++++++++++----- 1 file changed, 366 insertions(+), 61 deletions(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index e3b3cded3..2c257399f 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -141,6 +141,7 @@ class Interaction extends MetadataType { /** * manages post retrieve steps + * ! BETA RELEASE of journey support (v4.3.0); it so far only resolves a limited amount of dependencies and will likely break during cross-BU deployments! * * @param {TYPE.MetadataTypeItem} metadata a single query * @returns {TYPE.MetadataTypeItem} Array with one metadata object and one query string @@ -149,53 +150,224 @@ class Interaction extends MetadataType { // folder super.setFolderPath(metadata); - // eventDefinition - if (metadata.triggers?.length > 0 && metadata.triggers[0].metaData?.eventDefinitionKey) { - // trigger found; there can only be one entry in this array - try { - cache.searchForField( - 'eventDefinition', - metadata.triggers[0].metaData?.eventDefinitionKey, - 'eventDefinitionKey', - 'eventDefinitionKey' - ); - } catch (ex) { + switch (metadata.definitionType) { + case 'Multistep': { + // Multi-Step Journey + // ~~~ TRIGGERS ~~~~ + // eventDefinition / definitionType==='Multistep' && channel==='' && triggers[].type === 'EmailAudience'|'APIEvent' + if ( + metadata.triggers?.length > 0 && + metadata.triggers[0].metaData?.eventDefinitionKey + ) { + // trigger found; there can only be one entry in this array + try { + const edId = cache.searchForField( + 'eventDefinition', + metadata.triggers[0].metaData.eventDefinitionKey, + 'eventDefinitionKey', + 'id' + ); + if (metadata.triggers[0].metaData.eventDefinitionId !== edId) { + throw new Error( + ` - ${this.definition.type} ${ + metadata[this.definition.nameField] + } (${ + metadata[this.definition.keyField] + }): eventDefinitionId not matching Id found on eventDefinition with key in eventDefinitionKey` + ); + } + delete metadata.triggers[0].metaData.eventDefinitionId; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + } + + // ~~~ ACTIVITIES ~~~~ + + // triggeredSend + email+asset / activities[].type === 'EMAILV2' + // TODO email / asset + for (const item of metadata.activities) { + // check if all triggeredSends are there + try { + if (item.configurationArguments?.triggeredSendKey) { + // triggeredSendKey is not always set but triggeredSendId is + cache.searchForField( + 'triggeredSendDefinition', + item.configurationArguments.triggeredSendKey, + 'CustomerKey', + 'CustomerKey' + ); + delete item.configurationArguments.triggeredSendId; + } else if (item.configurationArguments?.triggeredSendId) { + // triggeredSendKey is not always set but triggeredSendId is + item.configurationArguments.triggeredSendKey = cache.searchForField( + 'triggeredSendDefinition', + item.configurationArguments.triggeredSendId, + 'ObjectID', + 'CustomerKey' + ); + delete item.configurationArguments.triggeredSendId; + } + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }): Could not find triggeredSendDefinition (${ex.message})` + ); + } + } + + // TODO: Filters / activities[].type === 'MULTICRITERIADECISION' + // - activities[].arguments.filterResult + // - activities[].arguments.configurationArguments.criteria + + // TODO: wait activity / activities[].type === 'WAIT' + + // TODO: journey template id? / metaData.templateId + break; + } + case 'Quicksend': { + // Single Send Journey Util.logger.warn( ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ metadata[this.definition.keyField] - }): ${ex.message}.` + }): definitionType Quicksend is not fully supported yet.` ); - } - } + // ~~~ TRIGGERS ~~~~ + // eventDefinition && triggers[].type === 'ContactAudience' + if ( + metadata.triggers?.length > 0 && + metadata.triggers[0].metaData?.eventDefinitionKey + ) { + // trigger found; there can only be one entry in this array + try { + const edId = cache.searchForField( + 'eventDefinition', + metadata.triggers[0].metaData.eventDefinitionKey, + 'eventDefinitionKey', + 'id' + ); + if (metadata.triggers[0].metaData.eventDefinitionId !== edId) { + throw new Error( + ` - ${this.definition.type} ${ + metadata[this.definition.nameField] + } (${ + metadata[this.definition.keyField] + }): eventDefinitionId not matching Id found on eventDefinition with key in eventDefinitionKey` + ); + } + delete metadata.triggers[0].metaData.eventDefinitionId; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + } - // triggeredSend - for (const item of metadata.activities) { - // check if all triggeredSends are there - try { - if (item.configurationArguments?.triggeredSendKey) { - // triggeredSendKey is not always set but triggeredSendId is - cache.searchForField( - 'triggeredSendDefinition', - item.configurationArguments.triggeredSendKey, - 'CustomerKey', - 'CustomerKey' - ); - delete item.configurationArguments.triggeredSendId; - } else if (item.configurationArguments?.triggeredSendId) { - // triggeredSendKey is not always set but triggeredSendId is - item.configurationArguments.triggeredSendKey = cache.searchForField( - 'triggeredSendDefinition', - item.configurationArguments.triggeredSendId, - 'ObjectID', - 'CustomerKey' + // ~~~ ACTIVITIES ~~~~ + try { + // TODO channel=='email' + // TODO channel=='sms' + // TODO channel=='push' / activities[].type === 'PUSHNOTIFICATIONACTIVITY' + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` ); - delete item.configurationArguments.triggeredSendId; } - } catch (ex) { + break; + } + case 'Transactional': { + // Transactional Send Journey + // ~~~ TRIGGERS ~~~~ + // ! journeys so far only supports transactional EMAIL messages. SMS and Push do not create their own journey. + // ! transactional (email) journeys only have a dummy trigger without real content. + // transactionalEmail / definitionType==='Transactional' && channel==='email' && triggers[].type === 'transactional-api' + // --> nothing to do here + + // ~~~ ACTIVITIES ~~~~ + // ! transactional (email) journeys only have one activity (type=EMAILV2) which links back to the transactionalEmail () + switch (metadata.channel) { + case 'email': { + if ( + metadata.activities?.length > 0 && + metadata.activities[0].configurationArguments?.triggeredSendKey + ) { + // trigger found; there can only be one entry in this array + try { + const tEmailId = cache.searchForField( + 'transactionalEmail', + metadata.activities[0].configurationArguments?.triggeredSendKey, + 'definitionKey', + 'definitionId' + ); + if ( + tEmailId != + metadata.activities[0].configurationArguments?.triggeredSendId + ) { + throw new Error( + ` - ${this.definition.type} ${ + metadata[this.definition.nameField] + } (${ + metadata[this.definition.keyField] + }): transactionalEmailId not matching Id found on transactionalEmail with key in transactionalEmailKey` + ); + } + if ( + metadata.activities[0].metaData?.highThroughput + ?.definitionKey && + metadata.activities[0].metaData?.highThroughput + ?.definitionKey != + metadata.activities[0].configurationArguments + ?.triggeredSendKey + ) { + throw new Error( + ` - ${this.definition.type} ${ + metadata[this.definition.nameField] + } (${ + metadata[this.definition.keyField] + }): metaData.highThroughput.definitionKey not matching key in configurationArguments.transactionalEmailKey` + ); + } + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${ + metadata[this.definition.nameField] + } (${metadata[this.definition.keyField]}): ${ex.message}.` + ); + } + } + + break; + } + default: { + // it is expected that we'll see 'sms' and 'push' here in the future + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): channel ${ + metadata.channel + } is not supported yet. Please open a ticket at https://github.com/Accenture/sfmc-devtools/issues/new/choose to request it` + ); + } + } + + break; + } + default: { Util.logger.warn( - ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ metadata[this.definition.keyField] - }): Could not find triggeredSendDefinition (${ex.message})` + }): definitionType ${ + metadata.definitionType + } is not supported yet. Please open a ticket at https://github.com/Accenture/sfmc-devtools/issues/new/choose to request it` ); } } @@ -204,6 +376,7 @@ class Interaction extends MetadataType { } /** * prepares a TSD for deployment + * ! BETA RELEASE of journey support (v4.3.0); it so far only resolves a limited amount of dependencies and will likely break during cross-BU deployments! * * @param {TYPE.MetadataTypeItem} metadata of a single TSD * @returns {TYPE.MetadataTypeItem} metadata object @@ -216,32 +389,164 @@ class Interaction extends MetadataType { // folder super.setFolderId(metadata); - // eventDefinition - if (metadata.triggers?.length > 0 && metadata.triggers[0].metaData?.eventDefinitionKey) { - // trigger found; there can only be one entry in this array - cache.searchForField( - 'eventDefinition', - metadata.triggers[0].metaData?.eventDefinitionKey, - 'eventDefinitionKey', - 'eventDefinitionKey' - ); - } + switch (metadata.definitionType) { + case 'Multistep': { + // Multi-Step Journey + // ~~~ TRIGGERS ~~~~ - // triggeredSend - for (const item of metadata.activities) { - // check if all triggeredSends are there - if (!item.configurationArguments?.triggeredSendKey) { - continue; + // eventDefinition / definitionType==='Multistep' && channel==='' && triggers[].type === 'EmailAudience'|'APIEvent' + if ( + metadata.triggers?.length > 0 && + metadata.triggers[0].metaData?.eventDefinitionKey + ) { + // trigger found; there can only be one entry in this array + metadata.triggers[0].metaData.eventDefinitionId = cache.searchForField( + 'eventDefinition', + metadata.triggers[0].metaData.eventDefinitionKey, + 'eventDefinitionKey', + 'id' + ); + } + + // transactionalEmail / definitionType==='Transactional' && channel==='email' && triggers[].type === 'transactional-api' + + // ~~~ ACTIVITIES ~~~~ + + // triggeredSend + email+asset / activities[].type === 'EMAILV2' + // TODO email / asset + for (const item of metadata.activities) { + // check if all triggeredSends are there + if (!item.configurationArguments?.triggeredSendKey) { + continue; + } + // triggeredSendKey is not always set but triggeredSendId is + item.configurationArguments.triggeredSendId = cache.searchForField( + 'triggeredSendDefinition', + item.configurationArguments.triggeredSendKey, + 'CustomerKey', + 'ObjectID' + ); + } + + // TODO: Filters / activities[].type === 'MULTICRITERIADECISION' + // - activities[].arguments.filterResult + // - activities[].arguments.configurationArguments.criteria + + // TODO: wait activity / activities[].type === 'WAIT' + + // TODO: journey template id? / metaData.templateId + break; } - // triggeredSendKey is not always set but triggeredSendId is - item.configurationArguments.triggeredSendId = cache.searchForField( - 'triggeredSendDefinition', - item.configurationArguments.triggeredSendKey, - 'CustomerKey', - 'ObjectID' - ); - } + case 'Quicksend': { + // Single Send Journey + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): definitionType Quicksend is not supported yet and might fail to deploy.` + ); + // ~~~ TRIGGERS ~~~~ + // eventDefinition && triggers[].type === 'ContactAudience' + if ( + metadata.triggers?.length > 0 && + metadata.triggers[0].metaData?.eventDefinitionKey + ) { + // trigger found; there can only be one entry in this array + try { + metadata.triggers[0].metaData.eventDefinitionId = cache.searchForField( + 'eventDefinition', + metadata.triggers[0].metaData?.eventDefinitionKey, + 'eventDefinitionKey', + 'id' + ); + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + } + + // ~~~ ACTIVITIES ~~~~ + try { + // TODO channel=='email' + // TODO channel=='sms' + // TODO channel=='push' / activities[].type === 'PUSHNOTIFICATIONACTIVITY' + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + break; + } + case 'Transactional': { + // Transactional Send Journey + // ~~~ TRIGGERS ~~~~ + // ! journeys so far transactional EMAIL messages. SMS and Push do not create their own journey. + // ! transactional (email) journeys only have a dummy trigger without real content. + + // transactionalEmail / definitionType==='Transactional' && channel==='email' && triggers[].type === 'transactional-api' + // --> nothing to do here + + // ~~~ ACTIVITIES ~~~~ + // ! transactional (email) journeys only have one activity (type=EMAILV2) which links back to the transactionalEmail () + switch (metadata.channel) { + case 'email': { + if ( + metadata.activities?.length > 0 && + metadata.activities[0].configurationArguments?.triggeredSendKey + ) { + // trigger found; there can only be one entry in this array + metadata.activities[0].configurationArguments.triggeredSendId = + cache.searchForField( + 'transactionalEmail', + metadata.activities[0].configurationArguments?.triggeredSendKey, + 'definitionKey', + 'definitionId' + ); + if ( + metadata.activities[0].metaData?.highThroughput?.definitionKey && + metadata.activities[0].metaData?.highThroughput?.definitionKey != + metadata.activities[0].configurationArguments?.triggeredSendKey + ) { + throw new Error( + ` - ${this.definition.type} ${ + metadata[this.definition.nameField] + } (${ + metadata[this.definition.keyField] + }): metaData.highThroughput.definitionKey not matching key in configurationArguments.transactionalEmailKey` + ); + } + } + + break; + } + default: { + // it is expected that we'll see 'sms' and 'push' here in the future + throw new Error( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): channel ${ + metadata.channel + } is not supported yet. Please open a ticket at https://github.com/Accenture/sfmc-devtools/issues/new/choose to request it` + ); + } + } + break; + } + default: { + throw new Error( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): definitionType ${ + metadata.definitionType + } is not supported yet. Please open a ticket at https://github.com/Accenture/sfmc-devtools/issues/new/choose to request it` + ); + } + } return metadata; } From ecbc5c92be8570b8b7c976f4270ca06fe11af9e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 23 Jan 2023 17:25:14 +0100 Subject: [PATCH 078/132] #627: adjust tests to changes in retrieved fields --- test/resources/9999999/interaction/build-expected.json | 2 -- test/resources/9999999/interaction/get-expected.json | 2 -- test/resources/9999999/interaction/post-expected.json | 2 -- test/resources/9999999/interaction/put-expected.json | 2 -- test/resources/9999999/interaction/template-expected.json | 2 -- .../9999999/interaction/v1/EventDefinitions/get-response.json | 1 + 6 files changed, 1 insertion(+), 10 deletions(-) diff --git a/test/resources/9999999/interaction/build-expected.json b/test/resources/9999999/interaction/build-expected.json index 5dbd765d4..3abfb93b1 100644 --- a/test/resources/9999999/interaction/build-expected.json +++ b/test/resources/9999999/interaction/build-expected.json @@ -234,7 +234,6 @@ "metaData": { "scheduleState": "No Schedule", "sourceInteractionId": "00000000-0000-0000-0000-000000000000", - "eventDefinitionId": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", "chainType": "None", "configurationRequired": false, @@ -256,7 +255,6 @@ }, "metaData": {}, "executionMode": "Production", - "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", "scheduledStatus": "Draft", "r__folder_Path": "my journeys" } diff --git a/test/resources/9999999/interaction/get-expected.json b/test/resources/9999999/interaction/get-expected.json index 303a954eb..e716802f2 100644 --- a/test/resources/9999999/interaction/get-expected.json +++ b/test/resources/9999999/interaction/get-expected.json @@ -237,7 +237,6 @@ "metaData": { "scheduleState": "No Schedule", "sourceInteractionId": "00000000-0000-0000-0000-000000000000", - "eventDefinitionId": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", "chainType": "None", "configurationRequired": false, @@ -260,7 +259,6 @@ "metaData": {}, "executionMode": "Production", "status": "Draft", - "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", "scheduledStatus": "Draft", "r__folder_Path": "my journeys" } diff --git a/test/resources/9999999/interaction/post-expected.json b/test/resources/9999999/interaction/post-expected.json index a9a5e0f27..6b14381b9 100644 --- a/test/resources/9999999/interaction/post-expected.json +++ b/test/resources/9999999/interaction/post-expected.json @@ -237,7 +237,6 @@ "metaData": { "scheduleState": "No Schedule", "sourceInteractionId": "00000000-0000-0000-0000-000000000000", - "eventDefinitionId": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", "chainType": "None", "configurationRequired": false, @@ -260,7 +259,6 @@ "metaData": {}, "executionMode": "Production", "status": "Draft", - "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", "scheduledStatus": "Draft", "r__folder_Path": "my journeys" } diff --git a/test/resources/9999999/interaction/put-expected.json b/test/resources/9999999/interaction/put-expected.json index 303a954eb..e716802f2 100644 --- a/test/resources/9999999/interaction/put-expected.json +++ b/test/resources/9999999/interaction/put-expected.json @@ -237,7 +237,6 @@ "metaData": { "scheduleState": "No Schedule", "sourceInteractionId": "00000000-0000-0000-0000-000000000000", - "eventDefinitionId": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", "chainType": "None", "configurationRequired": false, @@ -260,7 +259,6 @@ "metaData": {}, "executionMode": "Production", "status": "Draft", - "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", "scheduledStatus": "Draft", "r__folder_Path": "my journeys" } diff --git a/test/resources/9999999/interaction/template-expected.json b/test/resources/9999999/interaction/template-expected.json index 84f25a93b..8688d0d92 100644 --- a/test/resources/9999999/interaction/template-expected.json +++ b/test/resources/9999999/interaction/template-expected.json @@ -234,7 +234,6 @@ "metaData": { "scheduleState": "No Schedule", "sourceInteractionId": "00000000-0000-0000-0000-000000000000", - "eventDefinitionId": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", "chainType": "None", "configurationRequired": false, @@ -256,7 +255,6 @@ }, "metaData": {}, "executionMode": "Production", - "definitionId": "233d4413-922c-4568-85a5-e5cc77efc3be", "scheduledStatus": "Draft", "r__folder_Path": "my journeys" } diff --git a/test/resources/9999999/interaction/v1/EventDefinitions/get-response.json b/test/resources/9999999/interaction/v1/EventDefinitions/get-response.json index 42731676e..4cecd2da9 100644 --- a/test/resources/9999999/interaction/v1/EventDefinitions/get-response.json +++ b/test/resources/9999999/interaction/v1/EventDefinitions/get-response.json @@ -5,6 +5,7 @@ "links": {}, "items": [ { + "id": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", "type": "APIEvent", "name": "TestContact_Event", "description": "", From 4e5c565ca11f044bfbecb724e1c5f8099ba585df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 23 Jan 2023 17:56:07 +0100 Subject: [PATCH 079/132] #627: move journey-version-param into key/id field as a req suffix --- docs/dist/documentation.md | 10 ++++------ lib/cli.js | 8 ++------ lib/index.js | 5 ++--- lib/metadataTypes/Interaction.js | 30 +++++++++++++++++++++++------- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index d5f443ca3..ce6c10ef9 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -476,7 +476,7 @@ main class * [.initProject([credentialsName])](#Mcdev.initProject) ⇒ Promise.<void> * [.findBUs(credentialsName)](#Mcdev.findBUs) ⇒ Promise.<void> * [.document(businessUnit, type)](#Mcdev.document) ⇒ Promise.<void> - * [.deleteByKey(businessUnit, type, customerKey, [version])](#Mcdev.deleteByKey) ⇒ Promise.<void> + * [.deleteByKey(businessUnit, type, customerKey)](#Mcdev.deleteByKey) ⇒ Promise.<void> * [.badKeys(businessUnit)](#Mcdev.badKeys) ⇒ Promise.<void> * [.retrieveAsTemplate(businessUnit, selectedType, name, market)](#Mcdev.retrieveAsTemplate) ⇒ Promise.<TYPE.MultiMetadataTypeList> * [.buildTemplate(businessUnit, selectedType, keyArr, market)](#Mcdev.buildTemplate) ⇒ Promise.<TYPE.MultiMetadataTypeList> @@ -607,7 +607,7 @@ Creates docs for supported metadata types in Markdown and/or HTML format -### Mcdev.deleteByKey(businessUnit, type, customerKey, [version]) ⇒ Promise.<void> +### Mcdev.deleteByKey(businessUnit, type, customerKey) ⇒ Promise.<void> Creates docs for supported metadata types in Markdown and/or HTML format **Kind**: static method of [Mcdev](#Mcdev) @@ -618,7 +618,6 @@ Creates docs for supported metadata types in Markdown and/or HTML format | businessUnit | string | references credentials from properties.json | | type | string | supported metadata type | | customerKey | string | Identifier of metadata | -| [version] | number | optional version of metadata | @@ -2929,7 +2928,7 @@ definitionId: A unique UUID provided by Salesforce Marketing Cloud. Each version * [Interaction](#Interaction) ⇐ [MetadataType](#MetadataType) * [.retrieve(retrieveDir, [_], [__], [___], [key])](#Interaction.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [.deleteByKey(buObject, key, version)](#Interaction.deleteByKey) ⇒ Promise.<boolean> + * [.deleteByKey(buObject, key)](#Interaction.deleteByKey) ⇒ Promise.<boolean> * [.update(metadata)](#Interaction.update) ⇒ Promise * [.create(metadata)](#Interaction.create) ⇒ Promise * [.postRetrieveTasks(metadata)](#Interaction.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem @@ -2954,7 +2953,7 @@ Retrieves Metadata of Interaction -### Interaction.deleteByKey(buObject, key, version) ⇒ Promise.<boolean> +### Interaction.deleteByKey(buObject, key) ⇒ Promise.<boolean> Delete a metadata item from the specified business unit **Kind**: static method of [Interaction](#Interaction) @@ -2964,7 +2963,6 @@ Delete a metadata item from the specified business unit | --- | --- | --- | | buObject | TYPE.BuObject | references credentials | | key | string | Identifier of item | -| version | number | required version of metadata | diff --git a/lib/cli.js b/lib/cli.js index b9ffff3d0..2c6fcc474 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -139,7 +139,7 @@ yargs }, }) .command({ - command: 'delete [VERSION]', + command: 'delete ', aliases: ['del'], desc: 'deletes metadata of selected type and external key', builder: (yargs) => { @@ -156,16 +156,12 @@ yargs .positional('EXTERNALKEY', { type: 'string', describe: 'the key to delete', - }) - .positional('VERSION', { - type: 'string', - describe: 'some types have versions (e.g. interaction)', }); }, handler: (argv) => { Mcdev.setSkipInteraction(argv.skipInteraction); Mcdev.setLoggingLevel(argv); - Mcdev.deleteByKey(argv.BU, argv.TYPE, argv.EXTERNALKEY, argv.VERSION); + Mcdev.deleteByKey(argv.BU, argv.TYPE, argv.EXTERNALKEY); }, }) .command({ diff --git a/lib/index.js b/lib/index.js index 2c7f5b6c0..a6698d57c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -355,10 +355,9 @@ class Mcdev { * @param {string} businessUnit references credentials from properties.json * @param {string} type supported metadata type * @param {string} customerKey Identifier of metadata - * @param {number} [version] optional version of metadata * @returns {Promise.} - */ - static async deleteByKey(businessUnit, type, customerKey, version) { + static async deleteByKey(businessUnit, type, customerKey) { Util.logger.info('mcdev:: delete'); const properties = await config.getProperties(); if (!(await config.checkProperties(properties))) { @@ -378,7 +377,7 @@ class Mcdev { } try { MetadataTypeInfo[type].properties = properties; - await MetadataTypeInfo[type].deleteByKey(buObject, customerKey, version); + await MetadataTypeInfo[type].deleteByKey(buObject, customerKey); } catch (ex) { Util.logger.errorStack(ex, ` - Deleting ${type} failed`); } diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 2c257399f..0413dd850 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -31,6 +31,11 @@ class Interaction extends MetadataType { let mode = 'key'; if (key) { /* eslint-disable unicorn/prefer-ternary */ + if (key.startsWith('%23')) { + // in the journey URL the Id is prefixed with an HTML-encoded "#" which could accidentally be copied by users + + singleKey = singleKey.slice(3); + } if (key.startsWith('id:')) { // ! allow selecting journeys by ID because that's what users see in the URL singleKey = key.slice(3); @@ -81,15 +86,10 @@ class Interaction extends MetadataType { * * @param {TYPE.BuObject} buObject references credentials * @param {string} key Identifier of item - * @param {number} version required version of metadata * @returns {Promise.} deletion success status */ - static async deleteByKey(buObject, key, version) { - if (Number.isNaN(version)) { - throw new TypeError( - 'Version is required for deleting interactions to avoid accidental deletion of the wrong item.' - ); - } + static async deleteByKey(buObject, key) { + let version; let singleKey = ''; /* eslint-disable unicorn/prefer-ternary */ if (key.startsWith('id:')) { @@ -99,7 +99,16 @@ class Interaction extends MetadataType { // in the journey URL the Id is prefixed with an HTML-encoded "#" which could accidentally be copied by users singleKey = singleKey.slice(3); } + if (singleKey.includes('/')) { + // in the journey URL the version is appended after the ID, separated by a forward-slash. + [singleKey, version] = singleKey.split('/'); + } } else { + if (key.includes('/')) { + // in the journey URL the version is appended after the ID, separated by a forward-slash. + [singleKey, version] = key.split('/'); + } + // delete by key with specified version does not work, therefore we need to get the ID first const response = await this.client.rest.get( `/interaction/v1/interactions/key:${key}?extras=` @@ -108,6 +117,13 @@ class Interaction extends MetadataType { singleKey = results[key].id; Util.logger.debug(`Deleting interaction ${key} via its ID ${singleKey}`); } + if (!/^\d+$/.test(version)) { + throw new TypeError( + 'Version is required for deleting interactions to avoid accidental deletion of the wrong item. Please append it at the end of the key or id, separated by forward-slash. Example for deleting version 4: ' + + key + + '/4' + ); + } Util.logger.warn( `Deleting Interactions via this command breaks following retrieve-by-key/id requests until you've deployed/created a new draft version! You can get still get the latest available version of your journey by retrieving all interactions on this BU.` ); From dfb864012b4d51792ed4d274f3f8dc4193c0d651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 23 Jan 2023 18:07:18 +0100 Subject: [PATCH 080/132] #627: auto-recognition of key vs id --- lib/metadataTypes/Interaction.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 0413dd850..4283bc39f 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -31,24 +31,25 @@ class Interaction extends MetadataType { let mode = 'key'; if (key) { /* eslint-disable unicorn/prefer-ternary */ - if (key.startsWith('%23')) { - // in the journey URL the Id is prefixed with an HTML-encoded "#" which could accidentally be copied by users - singleKey = singleKey.slice(3); - } - if (key.startsWith('id:')) { + if (key.startsWith('id:') || key.startsWith('%23')) { // ! allow selecting journeys by ID because that's what users see in the URL + // if the key started with %23 assume an ID was copied from the URL but the user forgot to prefix it with id: + + // remove id: or %23 singleKey = key.slice(3); if (singleKey.startsWith('%23')) { // in the journey URL the Id is prefixed with an HTML-encoded "#" which could accidentally be copied by users + // despite the slicing above, this still needs testing here because users might have prefixed the ID with id: but did not know to remove the #23 singleKey = singleKey.slice(3); } if (singleKey.includes('/')) { - // in the journey URL the version is appended after the ID, separated by a forward-slash. Needs to be removed from the ID for the retrieve + // in the journey URL the version is appended after the ID, separated by a forward-slash. Needs to be removed from the ID for the retrieve as we always aim to retrieve the latest version only singleKey = singleKey.split('/')[0]; } mode = 'id'; } else { + // assume actual key was provided singleKey = 'key:' + encodeURIComponent(key); } /* eslint-enable unicorn/prefer-ternary */ @@ -92,11 +93,15 @@ class Interaction extends MetadataType { let version; let singleKey = ''; /* eslint-disable unicorn/prefer-ternary */ - if (key.startsWith('id:')) { + if (key.startsWith('id:') || key.startsWith('%23')) { // ! allow selecting journeys by ID because that's what users see in the URL + // if the key started with %23 assume an ID was copied from the URL but the user forgot to prefix it with id: + + // remove id: or %23 singleKey = key.slice(3); if (singleKey.startsWith('%23')) { // in the journey URL the Id is prefixed with an HTML-encoded "#" which could accidentally be copied by users + // despite the slicing above, this still needs testing here because users might have prefixed the ID with id: but did not know to remove the #23 singleKey = singleKey.slice(3); } if (singleKey.includes('/')) { @@ -106,12 +111,12 @@ class Interaction extends MetadataType { } else { if (key.includes('/')) { // in the journey URL the version is appended after the ID, separated by a forward-slash. - [singleKey, version] = key.split('/'); + [key, version] = key.split('/'); } // delete by key with specified version does not work, therefore we need to get the ID first const response = await this.client.rest.get( - `/interaction/v1/interactions/key:${key}?extras=` + `/interaction/v1/interactions/key:${encodeURIComponent(key)}?extras=` ); const results = this.parseResponseBody(response, key); singleKey = results[key].id; From bb488b04bc8ea241599edab458a02bf1ec281bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 23 Jan 2023 18:16:15 +0100 Subject: [PATCH 081/132] #627: move journey-version-param into key/id field as a req suffix --- docs/dist/documentation.md | 5 ++--- lib/metadataTypes/MetadataType.js | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index ce6c10ef9..46e26004d 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -3179,7 +3179,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.buildDefinition(templateDir, targetDir, templateName, variables)](#MetadataType.buildDefinition) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.checkForErrors(ex)](#MetadataType.checkForErrors) ⇒ Array.<string> * [.document([buObject], [metadata], [isDeploy])](#MetadataType.document) ⇒ void - * [.deleteByKey(buObject, customerKey, [version])](#MetadataType.deleteByKey) ⇒ boolean + * [.deleteByKey(buObject, customerKey)](#MetadataType.deleteByKey) ⇒ boolean * [.postDeleteTasks(buObject, customerKey)](#MetadataType.postDeleteTasks) ⇒ void * [.deleteByKeySOAP(buObject, customerKey, [handleOutside])](#MetadataType.deleteByKeySOAP) ⇒ boolean * [.deleteByKeyREST(buObject, url, key, [handleOutside])](#MetadataType.deleteByKeyREST) ⇒ boolean @@ -3807,7 +3807,7 @@ Gets metadata cache with limited fields and does not store value to disk -### MetadataType.deleteByKey(buObject, customerKey, [version]) ⇒ boolean +### MetadataType.deleteByKey(buObject, customerKey) ⇒ boolean Delete a metadata item from the specified business unit **Kind**: static method of [MetadataType](#MetadataType) @@ -3817,7 +3817,6 @@ Delete a metadata item from the specified business unit | --- | --- | --- | | buObject | TYPE.BuObject | references credentials | | customerKey | string | Identifier of data extension | -| [version] | number | optional version of metadata | diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 828a7cfb8..fa697f397 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -1580,10 +1580,9 @@ class MetadataType { * * @param {TYPE.BuObject} buObject references credentials * @param {string} customerKey Identifier of data extension - * @param {number} [version] optional version of metadata * @returns {boolean} deletion success status */ - static deleteByKey(buObject, customerKey, version) { + static deleteByKey(buObject, customerKey) { Util.logger.error(`Deletion is not yet supported for ${this.definition.typeName}!`); return false; } From c8b3fcbdb61360d4d478f88e7c290302d61293cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 23 Jan 2023 19:41:35 +0100 Subject: [PATCH 082/132] #636: code review fixes --- lib/Deployer.js | 3 +-- lib/Retriever.js | 10 ++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/Deployer.js b/lib/Deployer.js index 71c2c4930..e0d8b3931 100644 --- a/lib/Deployer.js +++ b/lib/Deployer.js @@ -271,8 +271,7 @@ class Deployer { const multiMetadataTypeMap = {}; // deploy metadata files, extending cache once deploys for (const metadataType in deployOrder) { - // TODO rewrite to allow deploying only a specific sub-type - // const [type, subType] = metadataType.split('-'); + // TODO rewrite to allow deploying only a specific sub-type; currently, subtypes are ignored when executing deploy const type = metadataType; if (this.metadata[type]) { Util.logger.info('Deploying: ' + metadataType); diff --git a/lib/Retriever.js b/lib/Retriever.js index f0de8d41b..13532f57d 100644 --- a/lib/Retriever.js +++ b/lib/Retriever.js @@ -89,14 +89,20 @@ class Retriever { } else if (templateVariables) { // type is in list of types to retrieve and we have template variables Util.logger.info(`Retrieving as Template: ${metadataType}`); - + if (subTypeArr?.length > 1) { + Util.logger.warn( + `retrieveAsTemplate only works with one subtype, ignoring all but first subtype from your list: ${subTypeArr.join( + ', ' + )}` + ); + } result = await Promise.all( typeKeyMap[metadataType].map((name) => MetadataTypeInfo[type].retrieveAsTemplate( this.templateDir, name, templateVariables, - subTypeArr?.[0] // this might cause issues if one were to try to use the method with multiple subtypes + subTypeArr?.[0] ) ) ); From 8ae61eefc90f34aa26179139431eaf81f1563538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 23 Jan 2023 19:47:17 +0100 Subject: [PATCH 083/132] #636: fix jsdoc/require-returns-check warnings --- docs/dist/documentation.md | 30 +++++++++++++++--------------- lib/metadataTypes/Automation.js | 2 +- lib/metadataTypes/Query.js | 2 +- lib/util/file.js | 6 +++--- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 1de708b5e..54faf1872 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -1292,7 +1292,7 @@ Automation MetadataType * [.postDeployTasks(metadata, originalMetadata)](#Automation.postDeployTasks) ⇒ Promise.<void> * [.setFolderPath(metadata)](#Automation.setFolderPath) * [.setFolderId(metadata)](#Automation.setFolderId) - * [.parseMetadata(metadata)](#Automation.parseMetadata) ⇒ TYPE.AutomationItem + * [.parseMetadata(metadata)](#Automation.parseMetadata) ⇒ TYPE.AutomationItem \| void * [._buildSchedule(scheduleObject)](#Automation._buildSchedule) ⇒ TYPE.AutomationScheduleSoap * [._calcTime(offsetServer, dateInput, [offsetInput])](#Automation._calcTime) ⇒ string * [.document(buObject, [metadata])](#Automation.document) ⇒ Promise.<void> @@ -1455,11 +1455,11 @@ automation-specific script that retrieves the folder ID from cache and updates t -### Automation.parseMetadata(metadata) ⇒ TYPE.AutomationItem +### Automation.parseMetadata(metadata) ⇒ TYPE.AutomationItem \| void parses retrieved Metadata before saving **Kind**: static method of [Automation](#Automation) -**Returns**: TYPE.AutomationItem - parsed item +**Returns**: TYPE.AutomationItem \| void - parsed item | Param | Type | Description | | --- | --- | --- | @@ -4045,7 +4045,7 @@ Query MetadataType * [.buildTemplateForNested(templateDir, targetDir, metadata, templateVariables, templateName)](#Query.buildTemplateForNested) ⇒ Promise.<Array.<Array.<string>>> * [.parseMetadata(metadata)](#Query.parseMetadata) ⇒ TYPE.CodeExtractItem * [.getFilesToCommit(keyArr)](#Query.getFilesToCommit) ⇒ Array.<string> - * [.checkForErrors(ex)](#Query.checkForErrors) ⇒ Array.<string> + * [.checkForErrors(ex)](#Query.checkForErrors) ⇒ Array.<string> \| void @@ -4212,11 +4212,11 @@ additionally, the documentation for dataExtension and automation should be retur -### Query.checkForErrors(ex) ⇒ Array.<string> +### Query.checkForErrors(ex) ⇒ Array.<string> \| void Standardizes a check for multiple messages but adds query specific filters to error texts **Kind**: static method of [Query](#Query) -**Returns**: Array.<string> - formatted Error Message +**Returns**: Array.<string> \| void - formatted Error Message | Param | Type | Description | | --- | --- | --- | @@ -5747,10 +5747,10 @@ File extends fs-extra. It adds logger and util methods for file handling * [.writePrettyToFile(directory, filename, filetype, content, [templateVariables])](#File.writePrettyToFile) ⇒ Promise.<boolean> * [._beautify_prettier(directory, filename, filetype, content)](#File._beautify_prettier) ⇒ string * [.writeToFile(directory, filename, filetype, content, [encoding])](#File.writeToFile) ⇒ Promise.<boolean> - * [.readJSONFile(directory, filename, sync, cleanPath)](#File.readJSONFile) ⇒ Promise \| object - * [.readFilteredFilename(directory, filename, filetype, [encoding])](#File.readFilteredFilename) ⇒ Promise.<string> + * [.readJSONFile(directory, filename, sync, cleanPath)](#File.readJSONFile) ⇒ Promise.<object> \| object \| void + * [.readFilteredFilename(directory, filename, filetype, [encoding])](#File.readFilteredFilename) ⇒ Promise.<string> \| void * [.readDirectories(directory, depth, [includeStem], [_stemLength])](#File.readDirectories) ⇒ Promise.<Array.<string>> - * [.readDirectoriesSync(directory, [depth], [includeStem], [_stemLength])](#File.readDirectoriesSync) ⇒ Array.<string> + * [.readDirectoriesSync(directory, [depth], [includeStem], [_stemLength])](#File.readDirectoriesSync) ⇒ Array.<string> \| void * [.saveConfigFile(properties)](#File.saveConfigFile) ⇒ Promise.<void> * [.initPrettier([filetype])](#File.initPrettier) ⇒ Promise.<boolean> @@ -5880,11 +5880,11 @@ Saves text content to a file in the local file system. Will create the parent di -### File.readJSONFile(directory, filename, sync, cleanPath) ⇒ Promise \| object +### File.readJSONFile(directory, filename, sync, cleanPath) ⇒ Promise.<object> \| object \| void Saves json content to a file in the local file system. Will create the parent directory if it does not exist **Kind**: static method of [File](#File) -**Returns**: Promise \| object - Promise or JSON object depending on if async or not +**Returns**: Promise.<object> \| object \| void - Promise or JSON object depending on if async or not; void on error | Param | Type | Description | | --- | --- | --- | @@ -5895,11 +5895,11 @@ Saves json content to a file in the local file system. Will create the parent di -### File.readFilteredFilename(directory, filename, filetype, [encoding]) ⇒ Promise.<string> +### File.readFilteredFilename(directory, filename, filetype, [encoding]) ⇒ Promise.<string> \| void reads file from local file system. **Kind**: static method of [File](#File) -**Returns**: Promise.<string> - file contents +**Returns**: Promise.<string> \| void - file contents; void on error | Param | Type | Default | Description | | --- | --- | --- | --- | @@ -5930,13 +5930,13 @@ of file paths to be iterated over ``` -### File.readDirectoriesSync(directory, [depth], [includeStem], [_stemLength]) ⇒ Array.<string> +### File.readDirectoriesSync(directory, [depth], [includeStem], [_stemLength]) ⇒ Array.<string> \| void reads directories to a specific depth returning an array of file paths to be iterated over using sync api (required in constructors) TODO - merge with readDirectories. so far the logic is really different **Kind**: static method of [File](#File) -**Returns**: Array.<string> - array of fully defined file paths +**Returns**: Array.<string> \| void - array of fully defined file paths; void on error | Param | Type | Description | | --- | --- | --- | diff --git a/lib/metadataTypes/Automation.js b/lib/metadataTypes/Automation.js index 7835217a5..921e5649f 100644 --- a/lib/metadataTypes/Automation.js +++ b/lib/metadataTypes/Automation.js @@ -509,7 +509,7 @@ class Automation extends MetadataType { * parses retrieved Metadata before saving * * @param {TYPE.AutomationItem} metadata a single automation definition - * @returns {TYPE.AutomationItem} parsed item + * @returns {TYPE.AutomationItem | void} parsed item */ static parseMetadata(metadata) { // folder diff --git a/lib/metadataTypes/Query.js b/lib/metadataTypes/Query.js index 02eb3f489..7f5a4e0c0 100644 --- a/lib/metadataTypes/Query.js +++ b/lib/metadataTypes/Query.js @@ -337,7 +337,7 @@ class Query extends MetadataType { * Standardizes a check for multiple messages but adds query specific filters to error texts * * @param {object} ex response payload from REST API - * @returns {string[]} formatted Error Message + * @returns {string[] | void} formatted Error Message */ static checkForErrors(ex) { const errors = super.checkForErrors(ex); diff --git a/lib/util/file.js b/lib/util/file.js index 58d29df89..c95c12b72 100644 --- a/lib/util/file.js +++ b/lib/util/file.js @@ -300,7 +300,7 @@ const File = { * @param {string} filename name of the file without '.json' ending * @param {boolean} sync should execute sync (default is async) * @param {boolean} cleanPath should execute sync (default is true) - * @returns {Promise | object} Promise or JSON object depending on if async or not + * @returns {Promise. | object | void} Promise or JSON object depending on if async or not; void on error */ readJSONFile: function (directory, filename, sync, cleanPath) { try { @@ -336,7 +336,7 @@ const File = { * @param {string} filename name of the file without '.json' ending * @param {string} filetype filetype suffix * @param {string} [encoding='utf8'] read file with encoding (defaults to utf-8) - * @returns {Promise.} file contents + * @returns {Promise. | void} file contents; void on error */ readFilteredFilename: function (directory, filename, filetype, encoding) { try { @@ -411,7 +411,7 @@ const File = { * @param {number} [depth] how many levels to check (1 base) * @param {boolean} [includeStem] include the parent directory in the response * @param {number} [_stemLength] set recursively for subfolders. do not set manually! - * @returns {string[]} array of fully defined file paths + * @returns {string[] | void} array of fully defined file paths; void on error */ readDirectoriesSync: function (directory, depth, includeStem, _stemLength) { try { From d018e90c0704699b9e9e6cb0d31fb7bbb906ff7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Jan 2023 20:06:26 +0000 Subject: [PATCH 084/132] Bump husky from 8.0.1 to 8.0.3 Bumps [husky](https://github.com/typicode/husky) from 8.0.1 to 8.0.3. - [Release notes](https://github.com/typicode/husky/releases) - [Commits](https://github.com/typicode/husky/compare/v8.0.1...v8.0.3) --- updated-dependencies: - dependency-name: husky dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1dfb7974c..fb09e459b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45,7 +45,7 @@ "eslint-plugin-mocha": "10.1.0", "eslint-plugin-prettier": "4.2.1", "eslint-plugin-unicorn": "45.0.2", - "husky": "8.0.1", + "husky": "8.0.3", "jsdoc-to-markdown": "8.0.0", "lint-staged": "13.1.0", "mocha": "10.2.0", @@ -4578,9 +4578,9 @@ } }, "node_modules/husky": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz", - "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", "dev": true, "bin": { "husky": "lib/bin.js" @@ -13246,9 +13246,9 @@ "dev": true }, "husky": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz", - "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", "dev": true }, "iconv-lite": { diff --git a/package.json b/package.json index 6e2c8482f..20fcd14cd 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "eslint-plugin-mocha": "10.1.0", "eslint-plugin-prettier": "4.2.1", "eslint-plugin-unicorn": "45.0.2", - "husky": "8.0.1", + "husky": "8.0.3", "jsdoc-to-markdown": "8.0.0", "lint-staged": "13.1.0", "mocha": "10.2.0", From 5f176ca1d6be3bef9575bb577560f1a67ef60f91 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Jan 2023 22:10:34 +0000 Subject: [PATCH 085/132] Bump simple-git from 3.15.1 to 3.16.0 Bumps [simple-git](https://github.com/steveukx/git-js/tree/HEAD/simple-git) from 3.15.1 to 3.16.0. - [Release notes](https://github.com/steveukx/git-js/releases) - [Changelog](https://github.com/steveukx/git-js/blob/main/simple-git/CHANGELOG.md) - [Commits](https://github.com/steveukx/git-js/commits/simple-git@3.16.0/simple-git) --- updated-dependencies: - dependency-name: simple-git dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index fb09e459b..56847b108 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "prettier-plugin-sql": "0.12.1", "semver": "7.3.8", "sfmc-sdk": "0.6.2", - "simple-git": "3.15.1", + "simple-git": "3.16.0", "toposort": "2.0.2", "update-notifier": "5.1.0", "winston": "3.8.2", @@ -8675,9 +8675,9 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/simple-git": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.15.1.tgz", - "integrity": "sha512-73MVa5984t/JP4JcQt0oZlKGr42ROYWC3BcUZfuHtT3IHKPspIvL0cZBnvPXF7LL3S/qVeVHVdYYmJ3LOTw4Rg==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.16.0.tgz", + "integrity": "sha512-zuWYsOLEhbJRWVxpjdiXl6eyAyGo/KzVW+KFhhw9MqEEJttcq+32jTWSGyxTdf9e/YCohxRE+9xpWFj9FdiJNw==", "dependencies": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", @@ -16284,9 +16284,9 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "simple-git": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.15.1.tgz", - "integrity": "sha512-73MVa5984t/JP4JcQt0oZlKGr42ROYWC3BcUZfuHtT3IHKPspIvL0cZBnvPXF7LL3S/qVeVHVdYYmJ3LOTw4Rg==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.16.0.tgz", + "integrity": "sha512-zuWYsOLEhbJRWVxpjdiXl6eyAyGo/KzVW+KFhhw9MqEEJttcq+32jTWSGyxTdf9e/YCohxRE+9xpWFj9FdiJNw==", "requires": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", diff --git a/package.json b/package.json index 20fcd14cd..c889e4b9f 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "prettier-plugin-sql": "0.12.1", "semver": "7.3.8", "sfmc-sdk": "0.6.2", - "simple-git": "3.15.1", + "simple-git": "3.16.0", "toposort": "2.0.2", "update-notifier": "5.1.0", "winston": "3.8.2", From 9b8030258d52b606e739fa5ead8808e028393116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Tue, 24 Jan 2023 16:59:22 +0100 Subject: [PATCH 086/132] #663: add sleep timer to avoid race conditions on SFMC's server --- docs/dist/documentation.md | 26 ++++++++++++++++++++ lib/metadataTypes/TriggeredSendDefinition.js | 8 ++++++ lib/util/util.js | 11 +++++++++ 3 files changed, 45 insertions(+) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 1552eb108..7463c4be2 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -5135,6 +5135,7 @@ CLI entry for SFMC DevTools * [.setLoggingLevel(argv)](#Util.setLoggingLevel) ⇒ void * [.logSubtypes(subTypeArr)](#Util.logSubtypes) ⇒ void * [.getKeysString(keyArr, [isId])](#Util.getKeysString) ⇒ string + * [.sleep(ms)](#Util.sleep) ⇒ Promise.<void> @@ -5394,6 +5395,18 @@ helper to print the subtypes we filtered by | keyArr | Array.<string> \| string | list of subtypes to be printed | | [isId] | boolean | optional flag to indicate if key is an id | + + +### Util.sleep(ms) ⇒ Promise.<void> +pause execution of code; useful when multiple server calls are dependent on each other and might not be executed right away + +**Kind**: static method of [Util](#Util) +**Returns**: Promise.<void> - - promise to wait for + +| Param | Type | Description | +| --- | --- | --- | +| ms | number | time in miliseconds to wait | + ## MetadataTypeDefinitions @@ -6899,6 +6912,7 @@ Util that contains logger and simple util methods * [.setLoggingLevel(argv)](#Util.setLoggingLevel) ⇒ void * [.logSubtypes(subTypeArr)](#Util.logSubtypes) ⇒ void * [.getKeysString(keyArr, [isId])](#Util.getKeysString) ⇒ string + * [.sleep(ms)](#Util.sleep) ⇒ Promise.<void> @@ -7158,6 +7172,18 @@ helper to print the subtypes we filtered by | keyArr | Array.<string> \| string | list of subtypes to be printed | | [isId] | boolean | optional flag to indicate if key is an id | + + +### Util.sleep(ms) ⇒ Promise.<void> +pause execution of code; useful when multiple server calls are dependent on each other and might not be executed right away + +**Kind**: static method of [Util](#Util) +**Returns**: Promise.<void> - - promise to wait for + +| Param | Type | Description | +| --- | --- | --- | +| ms | number | time in miliseconds to wait | + ## csvToArray(csv) ⇒ Array.<string> diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index 088e236a9..17a90b9e6 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -250,6 +250,7 @@ class TriggeredSendDefinition extends MetadataType { * @returns {Promise.} - */ static async refresh(keyArr) { + console.time('Time'); // eslint-disable-line no-console let checkKey = true; if (!keyArr) { keyArr = await this._findRefreshableItems(); @@ -264,6 +265,7 @@ class TriggeredSendDefinition extends MetadataType { } const successCounter = (await Promise.all(refreshList)).filter(Boolean).length; Util.logger.info(`Refreshed ${successCounter} of ${keyArr.length}`); + console.timeEnd('Time'); // eslint-disable-line no-console } /** @@ -382,6 +384,9 @@ class TriggeredSendDefinition extends MetadataType { return false; } + // wait for pause to finish on the server's internal queue + await Util.sleep(3000); + // publish try { item.RefreshContent = 'true'; @@ -399,6 +404,9 @@ class TriggeredSendDefinition extends MetadataType { return false; } + // wait for publish to finish on the server's internal queue + await Util.sleep(3000); + // start try { item.TriggeredSendStatus = 'Active'; diff --git a/lib/util/util.js b/lib/util/util.js index ab2e2fc6f..a60e94e60 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -494,6 +494,17 @@ const Util = { } return ''; }, + /** + * pause execution of code; useful when multiple server calls are dependent on each other and might not be executed right away + * + * @param {number} ms time in miliseconds to wait + * @returns {Promise.} - promise to wait for + */ + async sleep(ms) { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }, }; /** * wrapper around our standard winston logging to console and logfile From 723293e96bd60c1e8dda9c03944540a1a2aff383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Tue, 24 Jan 2023 17:13:32 +0100 Subject: [PATCH 087/132] #665: fix bad calls to retrieveByCache --- lib/metadataTypes/MetadataType.js | 2 +- lib/metadataTypes/TriggeredSendDefinition.js | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 2c0bfd88a..8b9890b19 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -217,7 +217,7 @@ class MetadataType { * @returns {Promise.} metadata */ static retrieveChangelog(buObject, additionalFields, subTypeArr) { - return this.retrieveForCache(buObject, subTypeArr); + return this.retrieveForCache(buObject, additionalFields, subTypeArr); } /** diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index 088e236a9..383794adc 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -291,11 +291,16 @@ class TriggeredSendDefinition extends MetadataType { for (const [type, subTypeArr] of Object.entries(requiredCache)) { if (!cache.getCache()?.[type]) { Util.logger.info(` - Caching dependent Metadata: ${type}`); + Util.logSubtypes(subTypeArr); cacheTypes[type].client = this.client; cacheTypes[type].buObject = this.buObject; cacheTypes[type].properties = this.properties; - const result = await cacheTypes[type].retrieveForCache(this.buObject, subTypeArr); + const result = await cacheTypes[type].retrieveForCache( + this.buObject, + null, + subTypeArr + ); cache.setMetadata(type, result.metadata); } } From 145aaf70aa7f364f033157aeed8e6c45cd66a771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Tue, 24 Jan 2023 17:23:17 +0100 Subject: [PATCH 088/132] #665: fix bad subtype reference (needs to be an array) --- lib/metadataTypes/TriggeredSendDefinition.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index 383794adc..978ddb919 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -285,7 +285,7 @@ class TriggeredSendDefinition extends MetadataType { 'triggered_send', 'triggered_send_journeybuilder', ], - asset: 'message', + asset: ['message'], list: null, }; for (const [type, subTypeArr] of Object.entries(requiredCache)) { From 0b7da408501d2d486dc89ad0522f873777c2327b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Tue, 24 Jan 2023 17:26:57 +0100 Subject: [PATCH 089/132] #653: added/updated field counter now logged as info --- lib/metadataTypes/DataExtensionField.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/metadataTypes/DataExtensionField.js b/lib/metadataTypes/DataExtensionField.js index fb96596ac..e203c27ff 100644 --- a/lib/metadataTypes/DataExtensionField.js +++ b/lib/metadataTypes/DataExtensionField.js @@ -242,8 +242,8 @@ class DataExtensionField extends MetadataType { } } - Util.logger.debug( - `${deployColumns.length} Fields added/updated for [${deKey}]${ + Util.logger.info( + ` - Found ${deployColumns.length} added/updated Fields for ${deKey}${ deployColumns.length ? ': ' : '' }` + deployColumns.map((item) => item.Name).join(', ') ); From 403c8fd3d4a45d0c05e6b74f1816ee71d3bcd80f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 25 Jan 2023 11:21:04 +0100 Subject: [PATCH 090/132] #667: increase REST pageSize from 50 to 500 to boost performance --- docs/dist/documentation.md | 24 ++++++++++++++++++++++++ lib/metadataTypes/MetadataType.js | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 1552eb108..60e61b9d3 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -5133,6 +5133,7 @@ CLI entry for SFMC DevTools * [.execSync(cmd, [args], [hideOutput])](#Util.execSync) ⇒ string * [.templateSearchResult(results, keyToSearch, searchValue)](#Util.templateSearchResult) ⇒ TYPE.MetadataTypeItem * [.setLoggingLevel(argv)](#Util.setLoggingLevel) ⇒ void + * [.logBeta(type)](#Util.logBeta) * [.logSubtypes(subTypeArr)](#Util.logSubtypes) ⇒ void * [.getKeysString(keyArr, [isId])](#Util.getKeysString) ⇒ string @@ -5370,6 +5371,17 @@ configures what is displayed in the console | [argv.verbose] | boolean | chatty user CLI output | | [argv.debug] | boolean | enables developer output & features | + + +### Util.logBeta(type) +outputs a warning that the given type is still in beta + +**Kind**: static method of [Util](#Util) + +| Param | Type | Description | +| --- | --- | --- | +| type | string | api name of the type thats in beta | + ### Util.logSubtypes(subTypeArr) ⇒ void @@ -6897,6 +6909,7 @@ Util that contains logger and simple util methods * [.execSync(cmd, [args], [hideOutput])](#Util.execSync) ⇒ string * [.templateSearchResult(results, keyToSearch, searchValue)](#Util.templateSearchResult) ⇒ TYPE.MetadataTypeItem * [.setLoggingLevel(argv)](#Util.setLoggingLevel) ⇒ void + * [.logBeta(type)](#Util.logBeta) * [.logSubtypes(subTypeArr)](#Util.logSubtypes) ⇒ void * [.getKeysString(keyArr, [isId])](#Util.getKeysString) ⇒ string @@ -7134,6 +7147,17 @@ configures what is displayed in the console | [argv.verbose] | boolean | chatty user CLI output | | [argv.debug] | boolean | enables developer output & features | + + +### Util.logBeta(type) +outputs a warning that the given type is still in beta + +**Kind**: static method of [Util](#Util) + +| Param | Type | Description | +| --- | --- | --- | +| type | string | api name of the type thats in beta | + ### Util.logSubtypes(subTypeArr) ⇒ void diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 8b9890b19..d962a676c 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -821,7 +821,7 @@ class MetadataType { static async retrieveREST(retrieveDir, uri, overrideType, templateVariables, singleRetrieve) { const response = this.definition.restPagination && !singleRetrieve - ? await this.client.rest.getBulk(uri) + ? await this.client.rest.getBulk(uri, 500) : await this.client.rest.get(uri); const results = this.parseResponseBody(response, singleRetrieve); // get extended metadata if applicable From 0ee2b5f25408b726bbd369d1fb9b79757a2f37e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 25 Jan 2023 11:27:00 +0100 Subject: [PATCH 091/132] #660: warn users about beta status of eventDefinition and interaction --- lib/metadataTypes/EventDefinition.js | 5 +++++ lib/metadataTypes/Interaction.js | 4 ++++ lib/util/util.js | 10 ++++++++++ 3 files changed, 19 insertions(+) diff --git a/lib/metadataTypes/EventDefinition.js b/lib/metadataTypes/EventDefinition.js index da37f3c2a..b9f48b6c5 100644 --- a/lib/metadataTypes/EventDefinition.js +++ b/lib/metadataTypes/EventDefinition.js @@ -25,6 +25,7 @@ class EventDefinition extends MetadataType { * @returns {Promise.} Promise of metadata */ static retrieve(retrieveDir, _, __, ___, key) { + Util.logBeta(this.definition.type); return super.retrieveREST( retrieveDir, `/interaction/v1/EventDefinitions${ @@ -54,6 +55,7 @@ class EventDefinition extends MetadataType { * @returns {Promise.} Promise of metadata */ static async retrieveAsTemplate(templateDir, name, templateVariables) { + Util.logBeta(this.definition.type); const res = await this.client.rest.get( '/interaction/v1/EventDefinitions?name=' + encodeURIComponent(name) ); @@ -123,6 +125,7 @@ class EventDefinition extends MetadataType { * @returns {Promise.} deletion success status */ static deleteByKey(key) { + Util.logBeta(this.definition.type); return super.deleteByKeyREST( '/interaction/v1/eventDefinitions/key:' + encodeURIComponent(key), key, @@ -137,6 +140,7 @@ class EventDefinition extends MetadataType { * @returns {Promise} Promise */ static create(EventDefinition) { + Util.logBeta(this.definition.type); return super.createREST(EventDefinition, '/interaction/v1/EventDefinitions/'); } @@ -147,6 +151,7 @@ class EventDefinition extends MetadataType { * @returns {Promise} Promise */ static async update(metadataEntry) { + Util.logBeta(this.definition.type); if (metadataEntry === null || metadataEntry === undefined) { return null; } diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 4fe10340f..fa7b20de7 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -27,6 +27,7 @@ class Interaction extends MetadataType { * @returns {Promise.} Promise */ static async retrieve(retrieveDir, _, __, ___, key) { + Util.logBeta(this.definition.type); let singleKey = ''; let mode = 'key'; if (key) { @@ -66,6 +67,7 @@ class Interaction extends MetadataType { key ); } catch (ex) { + // if the interaction does not exist, the API returns an error code which would otherwise bring execution to a hold if ( [ 'Interaction matching key not found.', @@ -146,6 +148,7 @@ class Interaction extends MetadataType { * @returns {Promise} Promise */ static update(metadata) { + Util.logBeta(this.definition.type); return super.updateREST(metadata, '/interaction/v1/interactions/', true); } @@ -156,6 +159,7 @@ class Interaction extends MetadataType { * @returns {Promise} Promise */ static create(metadata) { + Util.logBeta(this.definition.type); return super.createREST(metadata, '/interaction/v1/interactions/'); } diff --git a/lib/util/util.js b/lib/util/util.js index ab2e2fc6f..4d01a3bf4 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -452,6 +452,16 @@ const Util = { Util.logger.debug('CLI logger set to: debug'); } }, + /** + * outputs a warning that the given type is still in beta + * + * @param {string} type api name of the type thats in beta + */ + logBeta(type) { + Util.logger.warn( + `${type} support is currently still in beta. Please report any issues here: https://github.com/Accenture/sfmc-devtools/issues/new/choose` + ); + }, // defined colors for logging things in different colors color: { reset: '\x1B[0m', From 66109af49e7f25e165dee2ea0d8a116d191f8227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 25 Jan 2023 12:00:40 +0100 Subject: [PATCH 092/132] #662: fix SQL test cases not loading prettier correctly for auto-formatting --- lib/util/file.js | 4 ++++ test/resources/9999999/query/post-expected.sql | 2 +- test/utils.js | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/util/file.js b/lib/util/file.js index c95c12b72..3d04bc7fd 100644 --- a/lib/util/file.js +++ b/lib/util/file.js @@ -246,6 +246,10 @@ const File = { filename + '.' + filetype, ])}`; Util.logger.debug(warnMsg); + if (Util.logger.level === 'debug') { + // useful when running test cases in which we cannot see .error files + Util.logger.debug(ex.message); + } // save prettier errror into log file // Note: we have to filter color codes from prettier's error message before saving it to file diff --git a/test/resources/9999999/query/post-expected.sql b/test/resources/9999999/query/post-expected.sql index 9eb673f71..8020314ea 100644 --- a/test/resources/9999999/query/post-expected.sql +++ b/test/resources/9999999/query/post-expected.sql @@ -1,4 +1,4 @@ SELECT SubscriberKey as testField FROM - _Subscribers \ No newline at end of file + _Subscribers diff --git a/test/utils.js b/test/utils.js index 86b2c73e3..d2e1b3309 100644 --- a/test/utils.js +++ b/test/utils.js @@ -114,12 +114,29 @@ exports.mockSetup = (isDeploy) => { .reply((config) => resourceFactory.handleRESTRequest(config)); const fsMockConf = { '.prettierrc': fsmock.load(path.resolve(__dirname, '../boilerplate/files/.prettierrc')), + '.eslintrc': fsmock.load(path.resolve(__dirname, '../boilerplate/files/.eslintrc')), + '.eslintignore': fsmock.load(path.resolve(__dirname, '../boilerplate/files/.eslintignore')), '.mcdevrc.json': fsmock.load(path.resolve(__dirname, 'mockRoot/.mcdevrc.json')), '.mcdev-auth.json': fsmock.load(path.resolve(__dirname, 'mockRoot/.mcdev-auth.json')), 'boilerplate/config.json': fsmock.load( path.resolve(__dirname, '../boilerplate/config.json') ), test: fsmock.load(path.resolve(__dirname)), + // the following node_modules are required for prettier's SQL parser to work + 'node_modules/prettier': fsmock.load(path.resolve(__dirname, '../node_modules/prettier')), + 'node_modules/prettier-plugin-sql': fsmock.load( + path.resolve(__dirname, '../node_modules/prettier-plugin-sql') + ), + 'node_modules/node-sql-parser': fsmock.load( + path.resolve(__dirname, '../node_modules/node-sql-parser') + ), + 'node_modules/big-integer': fsmock.load( + path.resolve(__dirname, '../node_modules/big-integer') + ), + 'node_modules/sql-formatter': fsmock.load( + path.resolve(__dirname, '../node_modules/sql-formatter') + ), + 'node_modules/nearley': fsmock.load(path.resolve(__dirname, '../node_modules/nearley')), }; if (isDeploy) { // load files we manually prepared for a direct test of `deploy` command From af7066e548f72f9355444d1f65ce080d3716a1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 25 Jan 2023 12:10:44 +0100 Subject: [PATCH 093/132] #660: improve beta warnings --- docs/dist/documentation.md | 32 ++++++++++++++++++++++++++++ lib/metadataTypes/EventDefinition.js | 15 +++++++++++-- lib/metadataTypes/Interaction.js | 21 +++++++++++++++--- lib/util/util.js | 2 +- 4 files changed, 64 insertions(+), 6 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 60e61b9d3..6e18fa829 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -2368,6 +2368,7 @@ EventDefinition MetadataType * [.retrieveAsTemplate(templateDir, name, templateVariables)](#EventDefinition.retrieveAsTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.postRetrieveTasks(eventDef)](#EventDefinition.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.deleteByKey(key)](#EventDefinition.deleteByKey) ⇒ Promise.<boolean> + * [.deploy(metadata, deployDir, retrieveDir, buObject)](#EventDefinition.deploy) ⇒ Promise.<TYPE.MetadataTypeMap> * [.create(EventDefinition)](#EventDefinition.create) ⇒ Promise * [.update(metadataEntry)](#EventDefinition.update) ⇒ Promise * [.preDeployTasks(metadata)](#EventDefinition.preDeployTasks) ⇒ TYPE.MetadataTypeItem @@ -2436,6 +2437,21 @@ Delete a metadata item from the specified business unit | --- | --- | --- | | key | string | Identifier of item | + + +### EventDefinition.deploy(metadata, deployDir, retrieveDir, buObject) ⇒ Promise.<TYPE.MetadataTypeMap> +Deploys metadata - merely kept here to be able to print [logBeta](#Util.logBeta) once per deploy + +**Kind**: static method of [EventDefinition](#EventDefinition) +**Returns**: Promise.<TYPE.MetadataTypeMap> - Promise of keyField => metadata map + +| Param | Type | Description | +| --- | --- | --- | +| metadata | TYPE.MetadataTypeMap | metadata mapped by their keyField | +| deployDir | string | directory where deploy metadata are saved | +| retrieveDir | string | directory where metadata after deploy should be saved | +| buObject | TYPE.BuObject | properties for auth | + ### EventDefinition.create(EventDefinition) ⇒ Promise @@ -2947,6 +2963,7 @@ definitionId: A unique UUID provided by Salesforce Marketing Cloud. Each version * [Interaction](#Interaction) ⇐ [MetadataType](#MetadataType) * [.retrieve(retrieveDir, [_], [__], [___], [key])](#Interaction.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.deleteByKey(key)](#Interaction.deleteByKey) ⇒ Promise.<boolean> + * [.deploy(metadata, deployDir, retrieveDir, buObject)](#Interaction.deploy) ⇒ Promise.<TYPE.MetadataTypeMap> * [.update(metadata)](#Interaction.update) ⇒ Promise * [.create(metadata)](#Interaction.create) ⇒ Promise * [.postRetrieveTasks(metadata)](#Interaction.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem @@ -2981,6 +2998,21 @@ Delete a metadata item from the specified business unit | --- | --- | --- | | key | string | Identifier of item | + + +### Interaction.deploy(metadata, deployDir, retrieveDir, buObject) ⇒ Promise.<TYPE.MetadataTypeMap> +Deploys metadata - merely kept here to be able to print [logBeta](#Util.logBeta) once per deploy + +**Kind**: static method of [Interaction](#Interaction) +**Returns**: Promise.<TYPE.MetadataTypeMap> - Promise of keyField => metadata map + +| Param | Type | Description | +| --- | --- | --- | +| metadata | TYPE.MetadataTypeMap | metadata mapped by their keyField | +| deployDir | string | directory where deploy metadata are saved | +| retrieveDir | string | directory where metadata after deploy should be saved | +| buObject | TYPE.BuObject | properties for auth | + ### Interaction.update(metadata) ⇒ Promise diff --git a/lib/metadataTypes/EventDefinition.js b/lib/metadataTypes/EventDefinition.js index b9f48b6c5..9a6899cb7 100644 --- a/lib/metadataTypes/EventDefinition.js +++ b/lib/metadataTypes/EventDefinition.js @@ -132,6 +132,19 @@ class EventDefinition extends MetadataType { false ); } + /** + * Deploys metadata - merely kept here to be able to print {@link Util.logBeta} once per deploy + * + * @param {TYPE.MetadataTypeMap} metadata metadata mapped by their keyField + * @param {string} deployDir directory where deploy metadata are saved + * @param {string} retrieveDir directory where metadata after deploy should be saved + * @param {TYPE.BuObject} buObject properties for auth + * @returns {Promise.} Promise of keyField => metadata map + */ + static async deploy(metadata, deployDir, retrieveDir, buObject) { + Util.logBeta(this.definition.type); + return super.deploy(metadata, deployDir, retrieveDir, buObject); + } /** * Creates a single Event Definition @@ -140,7 +153,6 @@ class EventDefinition extends MetadataType { * @returns {Promise} Promise */ static create(EventDefinition) { - Util.logBeta(this.definition.type); return super.createREST(EventDefinition, '/interaction/v1/EventDefinitions/'); } @@ -151,7 +163,6 @@ class EventDefinition extends MetadataType { * @returns {Promise} Promise */ static async update(metadataEntry) { - Util.logBeta(this.definition.type); if (metadataEntry === null || metadataEntry === undefined) { return null; } diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index fa7b20de7..b8a1f2188 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -27,7 +27,10 @@ class Interaction extends MetadataType { * @returns {Promise.} Promise */ static async retrieve(retrieveDir, _, __, ___, key) { - Util.logBeta(this.definition.type); + if (retrieveDir) { + // only print this during retrieve, not during retrieveForCache + Util.logBeta(this.definition.type); + } let singleKey = ''; let mode = 'key'; if (key) { @@ -141,6 +144,20 @@ class Interaction extends MetadataType { false ); } + /** + * Deploys metadata - merely kept here to be able to print {@link Util.logBeta} once per deploy + * + * @param {TYPE.MetadataTypeMap} metadata metadata mapped by their keyField + * @param {string} deployDir directory where deploy metadata are saved + * @param {string} retrieveDir directory where metadata after deploy should be saved + * @param {TYPE.BuObject} buObject properties for auth + * @returns {Promise.} Promise of keyField => metadata map + */ + static async deploy(metadata, deployDir, retrieveDir, buObject) { + Util.logBeta(this.definition.type); + return super.deploy(metadata, deployDir, retrieveDir, buObject); + } + /** * Updates a single item * @@ -148,7 +165,6 @@ class Interaction extends MetadataType { * @returns {Promise} Promise */ static update(metadata) { - Util.logBeta(this.definition.type); return super.updateREST(metadata, '/interaction/v1/interactions/', true); } @@ -159,7 +175,6 @@ class Interaction extends MetadataType { * @returns {Promise} Promise */ static create(metadata) { - Util.logBeta(this.definition.type); return super.createREST(metadata, '/interaction/v1/interactions/'); } diff --git a/lib/util/util.js b/lib/util/util.js index 4d01a3bf4..85af6a619 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -459,7 +459,7 @@ const Util = { */ logBeta(type) { Util.logger.warn( - `${type} support is currently still in beta. Please report any issues here: https://github.com/Accenture/sfmc-devtools/issues/new/choose` + ` - ${type} support is currently still in beta. Please report any issues here: https://github.com/Accenture/sfmc-devtools/issues/new/choose` ); }, // defined colors for logging things in different colors From 4ba622025de178540e0d2dd0ebc97918a8cfb8ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 25 Jan 2023 15:01:19 +0100 Subject: [PATCH 094/132] #654: fix failing rowcount call for dataExtensions --- .../rowset/get-response.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 test/resources/9999999/data/v1/customobjectdata/key/childBU_dataextension_test/rowset/get-response.json diff --git a/test/resources/9999999/data/v1/customobjectdata/key/childBU_dataextension_test/rowset/get-response.json b/test/resources/9999999/data/v1/customobjectdata/key/childBU_dataextension_test/rowset/get-response.json new file mode 100644 index 000000000..7719b9cda --- /dev/null +++ b/test/resources/9999999/data/v1/customobjectdata/key/childBU_dataextension_test/rowset/get-response.json @@ -0,0 +1,13 @@ +{ + "links": { + "self": "/v1/customobjectdata/token/ea0a44dc-b679-4d7d-8b77-e5d3f106e854/rowset?$page=1" + }, + "requestToken": "ea0a44dc-b679-4d7d-8b77-e5d3f106e854", + "tokenExpireDateUtc": "2023-01-26T13:54:59.883", + "customObjectId": "30400c03-0ec4-ec11-b83c-48df37d1de8b", + "customObjectKey": "childBU_dataextension_test", + "pageSize": 1, + "page": 1, + "count": 0, + "top": 0 +} From 89aa717ddb91e984da4e133b911b1785017164d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 25 Jan 2023 15:05:46 +0100 Subject: [PATCH 095/132] #668: log missing RESPONSE files for soap/rest --- test/resourceFactory.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/test/resourceFactory.js b/test/resourceFactory.js index cb0854775..14bbc7940 100644 --- a/test/resourceFactory.js +++ b/test/resourceFactory.js @@ -20,13 +20,16 @@ exports.loadSOAPRecords = async (mcdevAction, type, mid) => { type, mcdevAction + '-response.xml' ); - return (await fs.pathExists(testPath)) - ? fs.readFile(testPath, { - encoding: 'utf8', - }) - : fs.readFile(path.join('test', 'resources', mcdevAction + '-response.xml'), { - encoding: 'utf8', - }); + if (await fs.pathExists(testPath)) { + return fs.readFile(testPath, { + encoding: 'utf8', + }); + } + console.log(`error: Please create file ${testPath}`); // eslint-disable-line no-console + + return fs.readFile(path.join('test', 'resources', mcdevAction + '-response.xml'), { + encoding: 'utf8', + }); }; /** * based on request, respond with different soap data @@ -123,6 +126,8 @@ exports.handleRESTRequest = async (config) => { ]; } } else { + console.log(`error: Please create file ${testPath}`); // eslint-disable-line no-console + return [ 404, fs.readFile(path.join('test', 'resources', 'rest404-response.json'), { From bbc76f7aed64b855a59e91f7be18e6353bafbcd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 25 Jan 2023 15:10:48 +0100 Subject: [PATCH 096/132] #668: add missing dataExtension response for caching shared DEs --- .../dataExtension/retrieve-response.xml | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 test/resources/1111111/dataExtension/retrieve-response.xml diff --git a/test/resources/1111111/dataExtension/retrieve-response.xml b/test/resources/1111111/dataExtension/retrieve-response.xml new file mode 100644 index 000000000..68ea2dd11 --- /dev/null +++ b/test/resources/1111111/dataExtension/retrieve-response.xml @@ -0,0 +1,26 @@ + + + + RetrieveResponse + urn:uuid:c198cc12-c34c-4d1d-90b0-5b785a342efc + urn:uuid:a0506b59-1847-4405-8231-6a15e26bbcc9 + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + + 2022-04-21T19:21:50Z + 2022-04-21T19:26:50Z + + + + + + OK + d175de6e-c8e4-4f5d-9c1d-ad64426ff4b7 + + + \ No newline at end of file From 542d130986cc933b55520719223cdb0c72e6a758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 25 Jan 2023 16:29:55 +0100 Subject: [PATCH 097/132] #669: add missing folder-subtype "hidden" --- .../definitions/TriggeredSendDefinition.definition.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js b/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js index 58c5e9908..f27b6bdf3 100644 --- a/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js +++ b/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js @@ -1,6 +1,7 @@ module.exports = { bodyIteratorField: 'Results', dependencies: [ + 'folder-hidden', 'folder-triggered_send', 'folder-triggered_send_journeybuilder', 'email', From f4d40b48fbeab15aaaf5ed933b31d5ead8bebced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 25 Jan 2023 16:56:13 +0100 Subject: [PATCH 098/132] #669: add missing folder-subtype "hidden" for type email --- lib/metadataTypes/definitions/Email.definition.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metadataTypes/definitions/Email.definition.js b/lib/metadataTypes/definitions/Email.definition.js index 249a6fa0a..92c47638d 100644 --- a/lib/metadataTypes/definitions/Email.definition.js +++ b/lib/metadataTypes/definitions/Email.definition.js @@ -1,6 +1,6 @@ module.exports = { bodyIteratorField: 'Results', - dependencies: ['folder-email', 'folder-shared_email_default'], + dependencies: ['folder-hidden', 'folder-email', 'folder-shared_email_default'], hasExtended: false, idField: 'ID', keepId: true, From ffe94b63d72e3c99d14e144498779cba5a6ad26d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Wed, 25 Jan 2023 17:31:09 +0100 Subject: [PATCH 099/132] #669: need hidden folder to resolve SystemHiddenDataExtensions --- lib/metadataTypes/DataExtension.js | 10 +++------- .../definitions/DataExtension.definition.js | 1 + 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index ec270d2db..d747f9cb3 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -376,13 +376,9 @@ class DataExtension extends MetadataType { const metadataParentBu = await this._retrieveAll(additionalFields); // get shared folders to match our shared / synched Data Extensions - const subTypeArr = [ - 'shared_data', - 'synchronizeddataextension', - 'salesforcedataextension', - 'shared_dataextension', - 'dataextension', - ]; + const subTypeArr = this.definition.dependencies + .filter((item) => item.startsWith('folder-')) + .map((item) => item.slice(7)); Util.logger.info(' - Caching dependent Metadata: folder (shared via _ParentBU_)'); Util.logSubtypes(subTypeArr); Folder.client = this.client; diff --git a/lib/metadataTypes/definitions/DataExtension.definition.js b/lib/metadataTypes/definitions/DataExtension.definition.js index c47574bd8..ca22f8f21 100644 --- a/lib/metadataTypes/definitions/DataExtension.definition.js +++ b/lib/metadataTypes/definitions/DataExtension.definition.js @@ -1,6 +1,7 @@ module.exports = { bodyIteratorField: 'Results', dependencies: [ + 'folder-hidden', 'folder-dataextension', 'folder-salesforcedataextension', 'folder-shared_data', From 1b53a8e81455c936353cdc69b3e83809a82fbb79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Thu, 26 Jan 2023 10:11:03 +0100 Subject: [PATCH 100/132] #669: ease debugging of missing folders by keeping the id --- lib/metadataTypes/definitions/Folder.definition.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/metadataTypes/definitions/Folder.definition.js b/lib/metadataTypes/definitions/Folder.definition.js index 97e01b2e4..c1c48bec7 100644 --- a/lib/metadataTypes/definitions/Folder.definition.js +++ b/lib/metadataTypes/definitions/Folder.definition.js @@ -71,6 +71,7 @@ module.exports = { ], hasExtended: false, idField: 'ID', + keepId: true, keyField: 'CustomerKey', nameField: 'Name', restPagination: false, From 158c57d7414e3525c675d3963a29e1dcd70b295c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Thu, 26 Jan 2023 11:41:17 +0100 Subject: [PATCH 101/132] #670: fix folder filter origin message --- lib/metadataTypes/MetadataType.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index d962a676c..bfce20a92 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -1124,7 +1124,7 @@ class MetadataType { metadataEntry.r__folder_Path ); if (excludeByDefinition) { - Util.logger.debug(errorMsg + ' (project config)'); + Util.logger.debug(errorMsg + ' (Accenture SFMC DevTools default)'); return true; } @@ -1133,7 +1133,7 @@ class MetadataType { metadataEntry.r__folder_Path ); if (excludeByConfig) { - Util.logger.debug(errorMsg + ' (Accenture SFMC DevTools default)'); + Util.logger.debug(errorMsg + ' (project config)'); return true; } } From 3a68614f4eeed7b55b6470efc3679131ecf0546f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Thu, 26 Jan 2023 12:41:05 +0100 Subject: [PATCH 102/132] #671: handle download errors for automations gracefully --- docs/dist/documentation.md | 26 ++++++++++++++++++++++++++ lib/metadataTypes/Automation.js | 30 ++++++++++++++++++++++++++---- lib/util/auth.js | 2 +- lib/util/util.js | 23 ++++++++++++++++------- 4 files changed, 69 insertions(+), 12 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 6e18fa829..3aacaac94 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -5166,6 +5166,7 @@ CLI entry for SFMC DevTools * [.templateSearchResult(results, keyToSearch, searchValue)](#Util.templateSearchResult) ⇒ TYPE.MetadataTypeItem * [.setLoggingLevel(argv)](#Util.setLoggingLevel) ⇒ void * [.logBeta(type)](#Util.logBeta) + * [.getGrayMsg(msg)](#Util.getGrayMsg) ⇒ string * [.logSubtypes(subTypeArr)](#Util.logSubtypes) ⇒ void * [.getKeysString(keyArr, [isId])](#Util.getKeysString) ⇒ string @@ -5414,6 +5415,18 @@ outputs a warning that the given type is still in beta | --- | --- | --- | | type | string | api name of the type thats in beta | + + +### Util.getGrayMsg(msg) ⇒ string +helper that wraps a message in the correct color codes to have them printed gray + +**Kind**: static method of [Util](#Util) +**Returns**: string - gray msg + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | log message that should be wrapped with color codes | + ### Util.logSubtypes(subTypeArr) ⇒ void @@ -6942,6 +6955,7 @@ Util that contains logger and simple util methods * [.templateSearchResult(results, keyToSearch, searchValue)](#Util.templateSearchResult) ⇒ TYPE.MetadataTypeItem * [.setLoggingLevel(argv)](#Util.setLoggingLevel) ⇒ void * [.logBeta(type)](#Util.logBeta) + * [.getGrayMsg(msg)](#Util.getGrayMsg) ⇒ string * [.logSubtypes(subTypeArr)](#Util.logSubtypes) ⇒ void * [.getKeysString(keyArr, [isId])](#Util.getKeysString) ⇒ string @@ -7190,6 +7204,18 @@ outputs a warning that the given type is still in beta | --- | --- | --- | | type | string | api name of the type thats in beta | + + +### Util.getGrayMsg(msg) ⇒ string +helper that wraps a message in the correct color codes to have them printed gray + +**Kind**: static method of [Util](#Util) +**Returns**: string - gray msg + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | log message that should be wrapped with color codes | + ### Util.logSubtypes(subTypeArr) ⇒ void diff --git a/lib/metadataTypes/Automation.js b/lib/metadataTypes/Automation.js index 921e5649f..cc966f428 100644 --- a/lib/metadataTypes/Automation.js +++ b/lib/metadataTypes/Automation.js @@ -36,12 +36,34 @@ class Automation extends MetadataType { }; } const results = await this.client.soap.retrieveBulk('Program', ['ObjectID'], requestParams); - + Util.logger.info( + Util.getGrayMsg(` - ${results.Results.length} Automations found. Retrieving details...`) + ); const details = results.Results ? await Promise.all( - results.Results.map((a) => - this.client.rest.get('/automation/v1/automations/' + a.ObjectID) - ) + results.Results.map(async (a) => { + try { + return await this.client.rest.get( + '/automation/v1/automations/' + a.ObjectID + ); + } catch (ex) { + try { + if (ex.message == 'socket hang up') { + // one more retry; it's a rare case but retrying again should solve the issue gracefully + return await this.client.rest.get( + '/automation/v1/automations/' + a.ObjectID + ); + } + } catch { + // no extra action needed, handled below + } + // if we do get here, we should log the error and continue instead of failing to download all automations + Util.logger.error( + ` - skipping retrieving Automation ${a.ObjectID}: ${ex.message} ${ex.code}` + ); + return null; + } + }) ) : []; const parsed = this.parseResponseBody({ items: details }); diff --git a/lib/util/auth.js b/lib/util/auth.js index 720f7b0f1..6d1298aeb 100644 --- a/lib/util/auth.js +++ b/lib/util/auth.js @@ -106,7 +106,7 @@ function setupSDK(sessionKey, authObject) { Util.logger.warn( ` - Connection problem (Code: ${ex.code}). Retrying ${remainingAttempts} time${ remainingAttempts > 1 ? 's' : '' - }` + }${ex.endpoint ? Util.getGrayMsg(' - ' + ex.endpoint) : ''}` ); Util.logger.errorStack(ex); }, diff --git a/lib/util/util.js b/lib/util/util.js index 85af6a619..a11aedeae 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -467,6 +467,15 @@ const Util = { reset: '\x1B[0m', dim: '\x1B[2m', }, + /** + * helper that wraps a message in the correct color codes to have them printed gray + * + * @param {string} msg log message that should be wrapped with color codes + * @returns {string} gray msg + */ + getGrayMsg(msg) { + return `${Util.color.dim}${msg}${Util.color.reset}`; + }, /** * helper to print the subtypes we filtered by * @@ -476,9 +485,9 @@ const Util = { logSubtypes(subTypeArr) { if (subTypeArr && subTypeArr.length > 0) { Util.logger.info( - `${Util.color.dim} - Subtype${subTypeArr.length > 1 ? 's' : ''}: ${subTypeArr.join( - ', ' - )}${Util.color.reset}` + Util.getGrayMsg( + ` - Subtype${subTypeArr.length > 1 ? 's' : ''}: ${subTypeArr.join(', ')}` + ) ); } }, @@ -498,9 +507,9 @@ const Util = { keyArr = [keyArr]; } if (keyArr.length > 0) { - return `${Util.color.dim} - ${isId ? 'ID' : 'Key'}${ - keyArr.length > 1 ? 's' : '' - }: ${keyArr.join(', ')}${Util.color.reset}`; + return Util.getGrayMsg( + ` - ${isId ? 'ID' : 'Key'}${keyArr.length > 1 ? 's' : ''}: ${keyArr.join(', ')}` + ); } return ''; }, @@ -583,7 +592,7 @@ function startLogger() { // ! this method only sets exitCode=1 if message-param was set // if not, then this method purely outputs debug information and should not change the exitCode winstonError(message + ':'); - winstonError(' ' + ex.message); + winstonError(` ${ex.message} (${ex.code})`); if (ex.endpoint) { // ex.endpoint is only available if 'ex' is of type RestError winstonError(' endpoint: ' + ex.endpoint); From c3a1d40e6180e46cb837a0108ba9c57ba4bd1c50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Thu, 26 Jan 2023 12:48:40 +0100 Subject: [PATCH 103/132] #667: allow types to override restPageSize --- lib/metadataTypes/MetadataType.js | 2 +- lib/metadataTypes/definitions/Interaction.definition.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index bfce20a92..4f4b74657 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -821,7 +821,7 @@ class MetadataType { static async retrieveREST(retrieveDir, uri, overrideType, templateVariables, singleRetrieve) { const response = this.definition.restPagination && !singleRetrieve - ? await this.client.rest.getBulk(uri, 500) + ? await this.client.rest.getBulk(uri, this.definition.restPageSize || 500) : await this.client.rest.get(uri); const results = this.parseResponseBody(response, singleRetrieve); // get extended metadata if applicable diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index d6e18c596..518d55367 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -15,6 +15,7 @@ module.exports = { lastmodDateField: 'modifiedDate', lastmodNameField: null, restPagination: true, + restPageSize: 250, type: 'interaction', typeDescription: 'Journey (internally called "Interaction").', typeRetrieveByDefault: true, From 6cad588770672027573c26e87daa60ced59a0205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Thu, 26 Jan 2023 17:32:03 +0100 Subject: [PATCH 104/132] #671: only print endpoint path but not domain for connection problems --- lib/util/auth.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/util/auth.js b/lib/util/auth.js index 6d1298aeb..2541241c9 100644 --- a/lib/util/auth.js +++ b/lib/util/auth.js @@ -106,7 +106,13 @@ function setupSDK(sessionKey, authObject) { Util.logger.warn( ` - Connection problem (Code: ${ex.code}). Retrying ${remainingAttempts} time${ remainingAttempts > 1 ? 's' : '' - }${ex.endpoint ? Util.getGrayMsg(' - ' + ex.endpoint) : ''}` + }${ + ex.endpoint + ? Util.getGrayMsg( + ' - ' + ex.endpoint.split('rest.marketingcloudapis.com')[1] + ) + : '' + }` ); Util.logger.errorStack(ex); }, From f2cfc28ecc61c96fd9c0b3cbcd0a55115019798e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Thu, 26 Jan 2023 18:08:29 +0100 Subject: [PATCH 105/132] #672: switch to generic retrieveREST wrapper + filter deleted items on the server + fix missing definitionId for interactions --- lib/metadataTypes/TransactionalMessage.js | 45 ++++++++++++----------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/lib/metadataTypes/TransactionalMessage.js b/lib/metadataTypes/TransactionalMessage.js index 60bef3612..f2f1440aa 100644 --- a/lib/metadataTypes/TransactionalMessage.js +++ b/lib/metadataTypes/TransactionalMessage.js @@ -31,20 +31,16 @@ class TransactionalMessage extends MetadataType { keyList = [key]; } else { // Retrieve all - const response = this.definition.restPagination - ? await this.client.rest.getBulk(baseUri) - : await this.client.rest.get(baseUri); - const parsed = this.parseResponseBody(response); - keyList = Object.keys(parsed).filter((item) => parsed[item].status !== 'Deleted'); - const filteredCount = Object.keys(parsed).length - keyList.length; - if (filteredCount) { - Util.logger.info( - ` - Filtered ${this.definition.type} with status 'deleted': ${filteredCount} (downloaded but not saved to disk)` - ); - } + // * keep deleted items for caching (and to decide on update vs create) + const parsed = ( + await this.retrieveREST( + null, + baseUri + (retrieveDir ? '?$filter=status%20neq%20deleted' : '') + ) + ).metadata; + keyList = Object.keys(parsed); } - - // get all sms with additional details not given by the list endpoint + // get all transactionalX items with additional details not given by the list endpoint const details = ( await Promise.all( keyList.map(async (key) => { @@ -57,15 +53,17 @@ class TransactionalMessage extends MetadataType { ) ).filter(Boolean); const parsed = this.parseResponseBody({ definitions: details }); + let savedMetadata; + if (retrieveDir) { + // * retrieveDir is mandatory in this method as it is not used for caching (there is a seperate method for that) + savedMetadata = await this.saveResults(parsed, retrieveDir, null, null); + Util.logger.info( + `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + + Util.getKeysString(key) + ); + } - // * retrieveDir is mandatory in this method as it is not used for caching (there is a seperate method for that) - const savedMetadata = await this.saveResults(parsed, retrieveDir, null, null); - Util.logger.info( - `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + - Util.getKeysString(key) - ); - - return { metadata: savedMetadata, type: this.definition.type }; + return { metadata: savedMetadata || parsed, type: this.definition.type }; } /** @@ -74,7 +72,10 @@ class TransactionalMessage extends MetadataType { * @returns {Promise.} Promise of metadata */ static retrieveForCache() { - return super.retrieveREST(null, '/messaging/v1/' + this.subType + '/definitions/'); + // the call to /messaging/v1/email/definitions/ does not return definitionId + // definitionId is required for resolving dependencies on interactions. + // we should therefore use the already defined retrieve method + return this.retrieve(); } /** * Updates a single item From da10a3dbd654055dd381582591ba776c924eb2a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Thu, 26 Jan 2023 18:15:32 +0100 Subject: [PATCH 106/132] #672: enabled pagination and set pageSize to this API's max of 100 --- lib/metadataTypes/definitions/TransactionalEmail.definition.js | 3 ++- lib/metadataTypes/definitions/TransactionalPush.definition.js | 3 ++- lib/metadataTypes/definitions/TransactionalSMS.definition.js | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/metadataTypes/definitions/TransactionalEmail.definition.js b/lib/metadataTypes/definitions/TransactionalEmail.definition.js index 8b8cd08e6..3eafcbc97 100644 --- a/lib/metadataTypes/definitions/TransactionalEmail.definition.js +++ b/lib/metadataTypes/definitions/TransactionalEmail.definition.js @@ -9,7 +9,8 @@ module.exports = { createdNameField: null, lastmodDateField: 'modifiedDate', lastmodNameField: null, - restPagination: false, + restPagination: true, + restPageSize: 100, type: 'transactionalEmail', typeDescription: 'Lets you send immediate Email messages via API events', typeRetrieveByDefault: true, diff --git a/lib/metadataTypes/definitions/TransactionalPush.definition.js b/lib/metadataTypes/definitions/TransactionalPush.definition.js index 21caee96e..9102abcbe 100644 --- a/lib/metadataTypes/definitions/TransactionalPush.definition.js +++ b/lib/metadataTypes/definitions/TransactionalPush.definition.js @@ -9,7 +9,8 @@ module.exports = { createdNameField: null, lastmodDateField: 'modifiedDate', lastmodNameField: null, - restPagination: false, + restPagination: true, + restPageSize: 100, type: 'transactionalPush', typeDescription: 'Lets you send immediate Push messages via API events', typeRetrieveByDefault: true, diff --git a/lib/metadataTypes/definitions/TransactionalSMS.definition.js b/lib/metadataTypes/definitions/TransactionalSMS.definition.js index ff9e49d5d..d018f1ec9 100644 --- a/lib/metadataTypes/definitions/TransactionalSMS.definition.js +++ b/lib/metadataTypes/definitions/TransactionalSMS.definition.js @@ -9,7 +9,8 @@ module.exports = { createdNameField: null, lastmodDateField: 'modifiedDate', lastmodNameField: null, - restPagination: false, + restPagination: true, + restPageSize: 100, type: 'transactionalSMS', typeDescription: 'Lets you send immediate SMS messages via API events', typeRetrieveByDefault: true, From 1a5fd5e350846ccd8949ea2313a3db963f13909c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Thu, 26 Jan 2023 18:35:45 +0100 Subject: [PATCH 107/132] #672: adjust api calls counter in tests --- test/transactionalEmail.test.js | 2 +- test/transactionalPush.test.js | 2 +- test/transactionalSMS.test.js | 8 ++++---- test/utils.js | 11 ++++++++++- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/test/transactionalEmail.test.js b/test/transactionalEmail.test.js index 0598a4067..7cce96512 100644 --- a/test/transactionalEmail.test.js +++ b/test/transactionalEmail.test.js @@ -69,7 +69,7 @@ describe('transactionalEmail', () => { // check number of API calls assert.equal( testUtils.getAPIHistoryLength(), - 13, + 14, 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; diff --git a/test/transactionalPush.test.js b/test/transactionalPush.test.js index 49d008a09..7029fdfb2 100644 --- a/test/transactionalPush.test.js +++ b/test/transactionalPush.test.js @@ -69,7 +69,7 @@ describe('transactionalPush', () => { // check number of API calls assert.equal( testUtils.getAPIHistoryLength(), - 4, + 5, 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests', testUtils.getAPIHistoryDebug() ); diff --git a/test/transactionalSMS.test.js b/test/transactionalSMS.test.js index 7c6c48847..c8a319f48 100644 --- a/test/transactionalSMS.test.js +++ b/test/transactionalSMS.test.js @@ -41,7 +41,7 @@ describe('transactionalSMS', () => { assert.equal( testUtils.getAPIHistoryLength(), 4, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); @@ -86,8 +86,8 @@ describe('transactionalSMS', () => { // check number of API calls assert.equal( testUtils.getAPIHistoryLength(), - 5, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 6, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); @@ -141,7 +141,7 @@ describe('transactionalSMS', () => { assert.equal( testUtils.getAPIHistoryLength(), 4, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); diff --git a/test/utils.js b/test/utils.js index d2e1b3309..7b467b9b2 100644 --- a/test/utils.js +++ b/test/utils.js @@ -179,11 +179,20 @@ exports.getAPIHistory = () => apimock.history; * * @returns {object} of API history */ -exports.getAPIHistoryDebug = () => { +function getAPIHistoryDebug() { const historyArr = Object.values(apimock.history) .flat() .map((item) => ({ url: item.url, data: item.data })); return historyArr; +} +exports.getAPIHistoryDebug = getAPIHistoryDebug; +/** + * helper to return most important fields for each api call + * + * @returns {void} of API history + */ +exports.logAPIHistoryDebug = () => { + console.log(getAPIHistoryDebug()); // eslint-disable-line no-console }; /** From 4df0a5eebc7c62c454794128de498a90c0167288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Thu, 26 Jan 2023 19:15:48 +0100 Subject: [PATCH 108/132] #661: manually cache transactionalEmail in interaction to break circular dependency --- lib/metadataTypes/Interaction.js | 11 +++++++++++ .../definitions/Interaction.definition.js | 2 +- test/interaction.test.js | 12 ++++++------ test/transactionalEmail.test.js | 6 +++--- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index b8a1f2188..f93ac88e6 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -2,6 +2,7 @@ const TYPE = require('../../types/mcdev.d'); const MetadataType = require('./MetadataType'); +const TransactionalEmail = require('./TransactionalEmail'); const Util = require('../util/util'); const cache = require('../util/cache'); const File = require('../util/file'); @@ -31,6 +32,16 @@ class Interaction extends MetadataType { // only print this during retrieve, not during retrieveForCache Util.logBeta(this.definition.type); } + if (!cache.getCache()?.transactionalEmail) { + // ! interaction and transactionalEmail both link to each other. caching transactionalEmail here "manually", assuming that it's quicker than the other way round + Util.logger.info(' - Caching dependent Metadata: transactionalEmail'); + TransactionalEmail.buObject = this.buObject; + TransactionalEmail.client = this.client; + TransactionalEmail.properties = this.properties; + const result = await TransactionalEmail.retrieveForCache(); + cache.setMetadata('transactionalEmail', result.metadata); + } + let singleKey = ''; let mode = 'key'; if (key) { diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js index 518d55367..574da5c32 100644 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ b/lib/metadataTypes/definitions/Interaction.definition.js @@ -4,7 +4,7 @@ // update: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/putUpdateInteraction.html module.exports = { bodyIteratorField: 'items', - dependencies: ['folder-journey', 'triggeredSendDefinition', 'eventDefinition'], + dependencies: ['folder-journey', 'triggeredSendDefinition', 'eventDefinition'], // ! interaction and transactionalEmail both link to each other. caching transactionalEmail here "manually" instead of via dependencies array, assuming that it is quicker than the other way round folderIdField: 'categoryId', hasExtended: false, idField: 'id', diff --git a/test/interaction.test.js b/test/interaction.test.js index be4703353..d5834fef6 100644 --- a/test/interaction.test.js +++ b/test/interaction.test.js @@ -33,8 +33,8 @@ describe('interaction', () => { ); assert.equal( testUtils.getAPIHistoryLength(), - 5, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 7, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); @@ -71,8 +71,8 @@ describe('interaction', () => { // check number of API calls assert.equal( testUtils.getAPIHistoryLength(), - 7, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 9, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); @@ -114,8 +114,8 @@ describe('interaction', () => { assert.equal( testUtils.getAPIHistoryLength(), - 5, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 7, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); diff --git a/test/transactionalEmail.test.js b/test/transactionalEmail.test.js index 7cce96512..e56899c00 100644 --- a/test/transactionalEmail.test.js +++ b/test/transactionalEmail.test.js @@ -33,7 +33,7 @@ describe('transactionalEmail', () => { ); assert.equal( testUtils.getAPIHistoryLength(), - 12, + 14, 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; @@ -69,7 +69,7 @@ describe('transactionalEmail', () => { // check number of API calls assert.equal( testUtils.getAPIHistoryLength(), - 14, + 16, 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; @@ -111,7 +111,7 @@ describe('transactionalEmail', () => { ); assert.equal( testUtils.getAPIHistoryLength(), - 12, + 14, 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' ); return; From 438b83366dc84d234063e87bec35c0b36beef8b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Thu, 26 Jan 2023 19:17:15 +0100 Subject: [PATCH 109/132] #661: minor corrections --- lib/metadataTypes/Interaction.js | 6 +-- .../definitions/EventDefinition.definition.js | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index f93ac88e6..a896ecad0 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -219,11 +219,7 @@ class Interaction extends MetadataType { ); if (metadata.triggers[0].metaData.eventDefinitionId !== edId) { throw new Error( - ` - ${this.definition.type} ${ - metadata[this.definition.nameField] - } (${ - metadata[this.definition.keyField] - }): eventDefinitionId not matching Id found on eventDefinition with key in eventDefinitionKey` + `eventDefinitionId not matching Id found on eventDefinition with key in eventDefinitionKey` ); } delete metadata.triggers[0].metaData.eventDefinitionId; diff --git a/lib/metadataTypes/definitions/EventDefinition.definition.js b/lib/metadataTypes/definitions/EventDefinition.definition.js index 8af115fc0..5a522e47d 100644 --- a/lib/metadataTypes/definitions/EventDefinition.definition.js +++ b/lib/metadataTypes/definitions/EventDefinition.definition.js @@ -15,12 +15,45 @@ module.exports = { typeRetrieveByDefault: true, typeName: 'Journey: Entry Event Definition', fields: { + 'arguments.audienceCount': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'arguments.audienceDefinitionID': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'arguments.audienceDescription': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'arguments.audienceSource': { + skipValidation: true, + }, + 'arguments.audienceName': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, 'arguments.automationId': { isCreateable: true, isUpdateable: true, retrieving: true, template: true, }, + 'arguments.buildAudienceDefinitionID': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, 'arguments.contactAttributeGroup': { isCreateable: true, isUpdateable: true, @@ -832,6 +865,12 @@ module.exports = { retrieving: true, template: false, }, + 'schema.isPlatformObject': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, 'schema.fields': { isCreateable: true, isUpdateable: true, From dcc565b5a3a604acc9cfa0f88ef364bcfefee520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Thu, 26 Jan 2023 19:21:26 +0100 Subject: [PATCH 110/132] #672: adjust to breaking change in sfmc-sdk --- lib/util/auth.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/util/auth.js b/lib/util/auth.js index 2541241c9..90ef50b35 100644 --- a/lib/util/auth.js +++ b/lib/util/auth.js @@ -91,11 +91,9 @@ const Auth = { function setupSDK(sessionKey, authObject) { return new SDK(authObject, { eventHandlers: { - onLoop: (type, req) => { + onLoop: (type, accumulator) => { Util.logger.info( - ` - Requesting next batch (currently ${ - req.Results?.length || req.items?.length - } records)` + ` - Requesting next batch (currently ${accumulator?.length} records)` ); }, onRefresh: (authObject) => { From d2b7be5ec9d5124f030f796367f8e233f3abf102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Fri, 27 Jan 2023 16:54:43 +0100 Subject: [PATCH 111/132] #663: ensure RefreshContent is actually sent to allow updating the email --- lib/metadataTypes/TriggeredSendDefinition.js | 6 ------ .../definitions/TriggeredSendDefinition.definition.js | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index bfd6bdce4..59856fcd4 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -389,9 +389,6 @@ class TriggeredSendDefinition extends MetadataType { return false; } - // wait for pause to finish on the server's internal queue - await Util.sleep(3000); - // publish try { item.RefreshContent = 'true'; @@ -409,9 +406,6 @@ class TriggeredSendDefinition extends MetadataType { return false; } - // wait for publish to finish on the server's internal queue - await Util.sleep(3000); - // start try { item.TriggeredSendStatus = 'Active'; diff --git a/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js b/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js index f27b6bdf3..fe63729fc 100644 --- a/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js +++ b/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js @@ -387,7 +387,7 @@ module.exports = { }, RefreshContent: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: false, templating: false, }, From 3177ef29a0a145ab111c292230cc28c741877a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sun, 29 Jan 2023 13:38:15 +0100 Subject: [PATCH 112/132] #672: bump sfmc-sdk from 0.6.2 to 0.6.3 --- package-lock.json | 30 +++++++++++++++--------------- package.json | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 56847b108..54b9a6cd1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "prettier": "2.8.3", "prettier-plugin-sql": "0.12.1", "semver": "7.3.8", - "sfmc-sdk": "0.6.2", + "sfmc-sdk": "0.6.3", "simple-git": "3.16.0", "toposort": "2.0.2", "update-notifier": "5.1.0", @@ -3563,9 +3563,9 @@ "dev": true }, "node_modules/fast-xml-parser": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.13.tgz", - "integrity": "sha512-g+OboAw8ol1FgTHhKLR7ZHcItNudceiY04BBrvqa0JBWoPhi/+e5r4H5AeW+EsQCroJLJwsuOP3dD3c6cc5uOg==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.15.tgz", + "integrity": "sha512-bF4/E33/K/EZDHV23IJpSK2SU7rZTaSkDH5G85nXX8SKlQ9qBpWQhyPpm2nlTBewDJgtpd6+1x4TNpKmocmthQ==", "dependencies": { "strnum": "^1.0.5" }, @@ -8616,12 +8616,12 @@ "dev": true }, "node_modules/sfmc-sdk": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/sfmc-sdk/-/sfmc-sdk-0.6.2.tgz", - "integrity": "sha512-9UhnufDFka1rzYr2Ii8zTSiwgozZ0YhoEUTafAzDoz3PXZoRA8qLXlNj2voI/A4Sg44qEpg/1OCk6t7hu30IXA==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/sfmc-sdk/-/sfmc-sdk-0.6.3.tgz", + "integrity": "sha512-rnT3b4o0lnqVv347P6rUXzxxhp0TpftENdADO8fdka1Cap8Tf5Tfrnc8dBLsvnutuS00fLMAITkFbfyBEnRysQ==", "dependencies": { "axios": "^0.27.2", - "fast-xml-parser": "4.0.13", + "fast-xml-parser": "4.0.15", "p-limit": "3.1.0" }, "engines": { @@ -12509,9 +12509,9 @@ "dev": true }, "fast-xml-parser": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.13.tgz", - "integrity": "sha512-g+OboAw8ol1FgTHhKLR7ZHcItNudceiY04BBrvqa0JBWoPhi/+e5r4H5AeW+EsQCroJLJwsuOP3dD3c6cc5uOg==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.15.tgz", + "integrity": "sha512-bF4/E33/K/EZDHV23IJpSK2SU7rZTaSkDH5G85nXX8SKlQ9qBpWQhyPpm2nlTBewDJgtpd6+1x4TNpKmocmthQ==", "requires": { "strnum": "^1.0.5" } @@ -16238,12 +16238,12 @@ "dev": true }, "sfmc-sdk": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/sfmc-sdk/-/sfmc-sdk-0.6.2.tgz", - "integrity": "sha512-9UhnufDFka1rzYr2Ii8zTSiwgozZ0YhoEUTafAzDoz3PXZoRA8qLXlNj2voI/A4Sg44qEpg/1OCk6t7hu30IXA==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/sfmc-sdk/-/sfmc-sdk-0.6.3.tgz", + "integrity": "sha512-rnT3b4o0lnqVv347P6rUXzxxhp0TpftENdADO8fdka1Cap8Tf5Tfrnc8dBLsvnutuS00fLMAITkFbfyBEnRysQ==", "requires": { "axios": "^0.27.2", - "fast-xml-parser": "4.0.13", + "fast-xml-parser": "4.0.15", "p-limit": "3.1.0" } }, diff --git a/package.json b/package.json index c889e4b9f..ae54c5337 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "prettier": "2.8.3", "prettier-plugin-sql": "0.12.1", "semver": "7.3.8", - "sfmc-sdk": "0.6.2", + "sfmc-sdk": "0.6.3", "simple-git": "3.16.0", "toposort": "2.0.2", "update-notifier": "5.1.0", From db028e6fceb9073e6b22042a3bd4ad7ed0cfd416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sun, 29 Jan 2023 16:01:02 +0100 Subject: [PATCH 113/132] #661: only execute extra caching if interactions returned by API --- docs/dist/documentation.md | 24 ++ lib/metadataTypes/Interaction.js | 33 ++- lib/metadataTypes/MetadataType.js | 11 + test/dataExtension.test.js | 8 +- test/interaction.test.js | 10 +- test/query.test.js | 8 +- .../v1/interactions/get-response.json | 221 +++++++++++++++++- test/transactionalEmail.test.js | 12 +- test/transactionalPush.test.js | 8 +- 9 files changed, 301 insertions(+), 34 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 3aacaac94..726ddd99b 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -2966,6 +2966,7 @@ definitionId: A unique UUID provided by Salesforce Marketing Cloud. Each version * [.deploy(metadata, deployDir, retrieveDir, buObject)](#Interaction.deploy) ⇒ Promise.<TYPE.MetadataTypeMap> * [.update(metadata)](#Interaction.update) ⇒ Promise * [.create(metadata)](#Interaction.create) ⇒ Promise + * [.postRetrieveTasksBulk(metadataMap)](#Interaction.postRetrieveTasksBulk) * [.postRetrieveTasks(metadata)](#Interaction.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.preDeployTasks(metadata)](#Interaction.preDeployTasks) ⇒ TYPE.MetadataTypeItem * [.createOrUpdate(metadata, metadataKey, hasError, metadataToUpdate, metadataToCreate)](#Interaction.createOrUpdate) @@ -3037,6 +3038,17 @@ Creates a single item | --- | --- | --- | | metadata | TYPE.MetadataTypeItem | a single item | + + +### Interaction.postRetrieveTasksBulk(metadataMap) +Gets executed after retreive of metadata type and + +**Kind**: static method of [Interaction](#Interaction) + +| Param | Type | Description | +| --- | --- | --- | +| metadataMap | TYPE.MetadataTypeMap | key=customer key, value=metadata | + ### Interaction.postRetrieveTasks(metadata) ⇒ TYPE.MetadataTypeItem @@ -3187,6 +3199,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.getFieldNamesToRetrieve([additionalFields])](#MetadataType.getFieldNamesToRetrieve) ⇒ Array.<string> * [.deploy(metadata, deployDir, retrieveDir, buObject)](#MetadataType.deploy) ⇒ Promise.<TYPE.MetadataTypeMap> * [.postDeployTasks(metadata, originalMetadata)](#MetadataType.postDeployTasks) ⇒ void + * [.postRetrieveTasksBulk(metadataMap)](#MetadataType.postRetrieveTasksBulk) * [.postRetrieveTasks(metadata, targetDir, [isTemplating])](#MetadataType.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.setFolderPath(metadata)](#MetadataType.setFolderPath) * [.setFolderId(metadata)](#MetadataType.setFolderId) @@ -3304,6 +3317,17 @@ Gets executed after deployment of metadata type | metadata | TYPE.MetadataTypeMap | metadata mapped by their keyField | | originalMetadata | TYPE.MetadataTypeMap | metadata to be updated (contains additioanl fields) | + + +### MetadataType.postRetrieveTasksBulk(metadataMap) +Gets executed after retreive of metadata type and + +**Kind**: static method of [MetadataType](#MetadataType) + +| Param | Type | Description | +| --- | --- | --- | +| metadataMap | TYPE.MetadataTypeMap | key=customer key, value=metadata | + ### MetadataType.postRetrieveTasks(metadata, targetDir, [isTemplating]) ⇒ TYPE.MetadataTypeItem diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index a896ecad0..50632161c 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -32,15 +32,6 @@ class Interaction extends MetadataType { // only print this during retrieve, not during retrieveForCache Util.logBeta(this.definition.type); } - if (!cache.getCache()?.transactionalEmail) { - // ! interaction and transactionalEmail both link to each other. caching transactionalEmail here "manually", assuming that it's quicker than the other way round - Util.logger.info(' - Caching dependent Metadata: transactionalEmail'); - TransactionalEmail.buObject = this.buObject; - TransactionalEmail.client = this.client; - TransactionalEmail.properties = this.properties; - const result = await TransactionalEmail.retrieveForCache(); - cache.setMetadata('transactionalEmail', result.metadata); - } let singleKey = ''; let mode = 'key'; @@ -189,6 +180,30 @@ class Interaction extends MetadataType { return super.createREST(metadata, '/interaction/v1/interactions/'); } + /** + * Gets executed after retreive of metadata type and + * + * @param {TYPE.MetadataTypeMap} metadataMap key=customer key, value=metadata + */ + static async postRetrieveTasksBulk(metadataMap) { + let needTransactionalEmail = false; + for (const key in metadataMap) { + if (metadataMap[key].definitionType == 'Transactional') { + needTransactionalEmail = true; + break; + } + } + if (needTransactionalEmail && !cache.getCache()?.transactionalEmail) { + // ! interaction and transactionalEmail both link to each other. caching transactionalEmail here "manually", assuming that it's quicker than the other way round + Util.logger.info(' - Caching dependent Metadata: transactionalEmail'); + TransactionalEmail.buObject = this.buObject; + TransactionalEmail.client = this.client; + TransactionalEmail.properties = this.properties; + const result = await TransactionalEmail.retrieveForCache(); + cache.setMetadata('transactionalEmail', result.metadata); + } + } + /** * manages post retrieve steps * ! BETA RELEASE of journey support (v4.3.0); it so far only resolves a limited amount of dependencies and will likely break during cross-BU deployments! diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 4f4b74657..982c1d062 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -139,6 +139,14 @@ class MetadataType { */ static postDeployTasks(metadata, originalMetadata) {} + /** + * Gets executed after retreive of metadata type and + * + * @param {TYPE.MetadataTypeMap} metadataMap key=customer key, value=metadata + */ + static async postRetrieveTasksBulk(metadataMap) { + // placeholder + } /** * Gets executed after retreive of metadata type * @@ -1215,6 +1223,9 @@ class MetadataType { const savedResults = {}; let filterCounter = 0; let subtypeExtension; + if (Object.keys(results).length) { + await this.postRetrieveTasksBulk(results); + } for (const originalKey in results) { if (this.definition.type === 'asset') { overrideType = diff --git a/test/dataExtension.test.js b/test/dataExtension.test.js index 6900de377..eedf6de05 100644 --- a/test/dataExtension.test.js +++ b/test/dataExtension.test.js @@ -31,7 +31,7 @@ describe('dataExtension', () => { assert.equal( testUtils.getAPIHistoryLength(), 5, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); @@ -67,7 +67,7 @@ describe('dataExtension', () => { assert.equal( testUtils.getAPIHistoryLength(), 11, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); @@ -114,7 +114,7 @@ describe('dataExtension', () => { assert.equal( testUtils.getAPIHistoryLength(), 5, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); @@ -161,7 +161,7 @@ describe('dataExtension', () => { assert.equal( testUtils.getAPIHistoryLength(), 5, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); diff --git a/test/interaction.test.js b/test/interaction.test.js index d5834fef6..9e26c2f8f 100644 --- a/test/interaction.test.js +++ b/test/interaction.test.js @@ -23,8 +23,8 @@ describe('interaction', () => { const result = cache.getCache(); assert.equal( result.interaction ? Object.keys(result.interaction).length : 0, - 1, - 'only one interaction expected' + 2, + 'only 2 interactions expected' ); assert.deepEqual( await testUtils.getActualJson('testExisting_interaction', 'interaction'), @@ -51,8 +51,8 @@ describe('interaction', () => { const result = cache.getCache(); assert.equal( result.interaction ? Object.keys(result.interaction).length : 0, - 2, - 'two interactions expected' + 3, + '3 interactions expected' ); // confirm created item assert.deepEqual( @@ -71,7 +71,7 @@ describe('interaction', () => { // check number of API calls assert.equal( testUtils.getAPIHistoryLength(), - 9, + 7, 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; diff --git a/test/query.test.js b/test/query.test.js index 9b35ae11b..b470fe53f 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -40,7 +40,7 @@ describe('query', () => { assert.equal( testUtils.getAPIHistoryLength(), 6, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); @@ -82,7 +82,7 @@ describe('query', () => { assert.equal( testUtils.getAPIHistoryLength(), 8, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); @@ -128,7 +128,7 @@ describe('query', () => { assert.equal( testUtils.getAPIHistoryLength(), 6, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); @@ -175,7 +175,7 @@ describe('query', () => { assert.equal( testUtils.getAPIHistoryLength(), 6, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); diff --git a/test/resources/9999999/interaction/v1/interactions/get-response.json b/test/resources/9999999/interaction/v1/interactions/get-response.json index 9cf7432fe..e0425d8c8 100644 --- a/test/resources/9999999/interaction/v1/interactions/get-response.json +++ b/test/resources/9999999/interaction/v1/interactions/get-response.json @@ -1,5 +1,5 @@ { - "count": 1, + "count": 2, "page": 1, "pageSize": 50, "links": {}, @@ -10,6 +10,225 @@ "cumulativePopulation": 961860 }, "items": [ + { + "id": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "key": "0b76dccf-594c-b6dc-1acf-10c4493dcb84", + "name": "testExisting_temail", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2022-03-24T02:20:32.74", + "modifiedDate": "2022-03-24T02:20:40.45", + "activities": [ + { + "id": "9606bcb0-9246-4610-9800-963bc77fc20a", + "key": "EMAILV2-4", + "name": "testExisting_temail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "1f44021a-74ac-49be-a07c-67862228214d", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "test email", + "emailId": 25923, + "emailSubject": "test email", + "exclusionFilter": "", + "isSalesforceTracking": true, + "isMultipart": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "modified": {}, + "preHeader": "", + "priority": 4, + "sendClassificationId": "1284e9b2-a7b8-e711-80cf-1402ec721c9d", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "1084e9b2-a7b8-e711-80cf-1402ec721c9d", + "senderProfileId": "0f84e9b2-a7b8-e711-80cf-1402ec721c9d", + "isTrackingClicks": true, + "publicationListId": 15 + }, + "triggeredSendId": "0a650d90-755e-ed11-b852-48df37d1df5b", + "triggeredSendKey": "testExisting_temail" + }, + "metaData": { + "highThroughput": { + "definitionKey": "testExisting_temail", + "dataExtensionId": "21711373-72c1-ec11-b83b-48df37d1deb7" + }, + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "transactional-api", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "chainType": "none", + "configurationRequired": false, + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event", + "category": "Transactional", + "entrySourceGroupConfigUrl": "null" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": { + "analyticsTracking": { + "enabled": false, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": {}, + "executionMode": "Production", + "categoryId": 6298, + "status": "Published", + "scheduledStatus": "Draft", + "definitionId": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be" + }, { "id": "233d4413-922c-4568-85a5-e5cc77efc3be", "key": "testExisting_interaction", diff --git a/test/transactionalEmail.test.js b/test/transactionalEmail.test.js index e56899c00..71694dfdb 100644 --- a/test/transactionalEmail.test.js +++ b/test/transactionalEmail.test.js @@ -33,8 +33,8 @@ describe('transactionalEmail', () => { ); assert.equal( testUtils.getAPIHistoryLength(), - 14, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 12, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); @@ -69,8 +69,8 @@ describe('transactionalEmail', () => { // check number of API calls assert.equal( testUtils.getAPIHistoryLength(), - 16, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 14, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); @@ -111,8 +111,8 @@ describe('transactionalEmail', () => { ); assert.equal( testUtils.getAPIHistoryLength(), - 14, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 12, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); diff --git a/test/transactionalPush.test.js b/test/transactionalPush.test.js index 7029fdfb2..6dfbaa3c3 100644 --- a/test/transactionalPush.test.js +++ b/test/transactionalPush.test.js @@ -34,7 +34,7 @@ describe('transactionalPush', () => { assert.equal( testUtils.getAPIHistoryLength(), 3, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests' + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); @@ -70,8 +70,7 @@ describe('transactionalPush', () => { assert.equal( testUtils.getAPIHistoryLength(), 5, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests', - testUtils.getAPIHistoryDebug() + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); @@ -113,8 +112,7 @@ describe('transactionalPush', () => { assert.equal( testUtils.getAPIHistoryLength(), 3, - 'Unexpected number of requests made. Run testUtils.getAPIHistoryDebug() to see the requests', - testUtils.getAPIHistoryDebug() + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' ); return; }); From 4ddd95861bc4f800e7a38e6161a18a0e02581375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sun, 29 Jan 2023 16:45:02 +0100 Subject: [PATCH 114/132] #661: turned postRetrieveTasksBulk into a helper used by interaction only --- docs/dist/documentation.md | 36 +++++++++++++++++-------------- lib/metadataTypes/Interaction.js | 19 ++++++++++++++-- lib/metadataTypes/MetadataType.js | 11 ---------- 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 726ddd99b..a961ee592 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -2966,7 +2966,8 @@ definitionId: A unique UUID provided by Salesforce Marketing Cloud. Each version * [.deploy(metadata, deployDir, retrieveDir, buObject)](#Interaction.deploy) ⇒ Promise.<TYPE.MetadataTypeMap> * [.update(metadata)](#Interaction.update) ⇒ Promise * [.create(metadata)](#Interaction.create) ⇒ Promise - * [.postRetrieveTasksBulk(metadataMap)](#Interaction.postRetrieveTasksBulk) + * [.saveResults(results, retrieveDir, [overrideType], [templateVariables])](#Interaction.saveResults) ⇒ Promise.<TYPE.MetadataTypeMap> + * [._postRetrieveTasksBulk(metadataMap)](#Interaction._postRetrieveTasksBulk) * [.postRetrieveTasks(metadata)](#Interaction.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.preDeployTasks(metadata)](#Interaction.preDeployTasks) ⇒ TYPE.MetadataTypeItem * [.createOrUpdate(metadata, metadataKey, hasError, metadataToUpdate, metadataToCreate)](#Interaction.createOrUpdate) @@ -3038,10 +3039,25 @@ Creates a single item | --- | --- | --- | | metadata | TYPE.MetadataTypeItem | a single item | - + -### Interaction.postRetrieveTasksBulk(metadataMap) -Gets executed after retreive of metadata type and +### Interaction.saveResults(results, retrieveDir, [overrideType], [templateVariables]) ⇒ Promise.<TYPE.MetadataTypeMap> +Helper for writing Metadata to disk, used for Retrieve and deploy + +**Kind**: static method of [Interaction](#Interaction) +**Returns**: Promise.<TYPE.MetadataTypeMap> - Promise of saved metadata + +| Param | Type | Description | +| --- | --- | --- | +| results | TYPE.MetadataTypeMap | metadata results from deploy | +| retrieveDir | string | directory where metadata should be stored after deploy/retrieve | +| [overrideType] | string | for use when there is a subtype (such as folder-queries) | +| [templateVariables] | TYPE.TemplateMap | variables to be replaced in the metadata | + + + +### Interaction.\_postRetrieveTasksBulk(metadataMap) +helper for Interaction's [saveResults](saveResults). Gets executed after retreive of metadata type and **Kind**: static method of [Interaction](#Interaction) @@ -3199,7 +3215,6 @@ Provides default functionality that can be overwritten by child metadata type cl * [.getFieldNamesToRetrieve([additionalFields])](#MetadataType.getFieldNamesToRetrieve) ⇒ Array.<string> * [.deploy(metadata, deployDir, retrieveDir, buObject)](#MetadataType.deploy) ⇒ Promise.<TYPE.MetadataTypeMap> * [.postDeployTasks(metadata, originalMetadata)](#MetadataType.postDeployTasks) ⇒ void - * [.postRetrieveTasksBulk(metadataMap)](#MetadataType.postRetrieveTasksBulk) * [.postRetrieveTasks(metadata, targetDir, [isTemplating])](#MetadataType.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.setFolderPath(metadata)](#MetadataType.setFolderPath) * [.setFolderId(metadata)](#MetadataType.setFolderId) @@ -3317,17 +3332,6 @@ Gets executed after deployment of metadata type | metadata | TYPE.MetadataTypeMap | metadata mapped by their keyField | | originalMetadata | TYPE.MetadataTypeMap | metadata to be updated (contains additioanl fields) | - - -### MetadataType.postRetrieveTasksBulk(metadataMap) -Gets executed after retreive of metadata type and - -**Kind**: static method of [MetadataType](#MetadataType) - -| Param | Type | Description | -| --- | --- | --- | -| metadataMap | TYPE.MetadataTypeMap | key=customer key, value=metadata | - ### MetadataType.postRetrieveTasks(metadata, targetDir, [isTemplating]) ⇒ TYPE.MetadataTypeItem diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 50632161c..e0388e4ed 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -179,13 +179,28 @@ class Interaction extends MetadataType { static create(metadata) { return super.createREST(metadata, '/interaction/v1/interactions/'); } + /** + * Helper for writing Metadata to disk, used for Retrieve and deploy + * + * @param {TYPE.MetadataTypeMap} results metadata results from deploy + * @param {string} retrieveDir directory where metadata should be stored after deploy/retrieve + * @param {string} [overrideType] for use when there is a subtype (such as folder-queries) + * @param {TYPE.TemplateMap} [templateVariables] variables to be replaced in the metadata + * @returns {Promise.} Promise of saved metadata + */ + static async saveResults(results, retrieveDir, overrideType, templateVariables) { + if (Object.keys(results).length) { + await this._postRetrieveTasksBulk(results); + } + return super.saveResults(results, retrieveDir, overrideType, templateVariables); + } /** - * Gets executed after retreive of metadata type and + * helper for Interaction's {@link saveResults}. Gets executed after retreive of metadata type and * * @param {TYPE.MetadataTypeMap} metadataMap key=customer key, value=metadata */ - static async postRetrieveTasksBulk(metadataMap) { + static async _postRetrieveTasksBulk(metadataMap) { let needTransactionalEmail = false; for (const key in metadataMap) { if (metadataMap[key].definitionType == 'Transactional') { diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 982c1d062..4f4b74657 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -139,14 +139,6 @@ class MetadataType { */ static postDeployTasks(metadata, originalMetadata) {} - /** - * Gets executed after retreive of metadata type and - * - * @param {TYPE.MetadataTypeMap} metadataMap key=customer key, value=metadata - */ - static async postRetrieveTasksBulk(metadataMap) { - // placeholder - } /** * Gets executed after retreive of metadata type * @@ -1223,9 +1215,6 @@ class MetadataType { const savedResults = {}; let filterCounter = 0; let subtypeExtension; - if (Object.keys(results).length) { - await this.postRetrieveTasksBulk(results); - } for (const originalKey in results) { if (this.definition.type === 'asset') { overrideType = From 9056ce381ec617c07e267e0187b43ed9d1a6b783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Sun, 29 Jan 2023 17:30:26 +0100 Subject: [PATCH 115/132] #593: remove buObject param from document() switching to type-class attribute --- docs/dist/documentation.md | 31 ++++++++++++------------------ lib/index.js | 3 ++- lib/metadataTypes/AccountUser.js | 21 +++++++++----------- lib/metadataTypes/Automation.js | 13 ++++++------- lib/metadataTypes/DataExtension.js | 13 ++++++------- lib/metadataTypes/MetadataType.js | 7 +++---- lib/metadataTypes/Role.js | 13 ++++++------- 7 files changed, 44 insertions(+), 57 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index be458df09..4af1a2b2f 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -737,8 +737,8 @@ MessageSendActivity MetadataType * [.retrieve(retrieveDir, _, buObject, [___], [key])](#AccountUser.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveChangelog(buObject)](#AccountUser.retrieveChangelog) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.timeSinceDate(date)](#AccountUser.timeSinceDate) ⇒ number - * [.getBuName(buObject, id)](#AccountUser.getBuName) ⇒ string - * [.document(buObject, [metadata])](#AccountUser.document) ⇒ Promise.<void> + * [.getBuName(id)](#AccountUser.getBuName) ⇒ string + * [.document([metadata])](#AccountUser.document) ⇒ Promise.<void> * [._generateDocMd(users, type, columnsToPrint)](#AccountUser._generateDocMd) ⇒ string * [.postRetrieveTasks(metadata)](#AccountUser.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.parseMetadata(metadata)](#AccountUser.parseMetadata) ⇒ TYPE.MetadataTypeItem @@ -783,7 +783,7 @@ Retrieves SOAP based metadata of metadata type into local filesystem. executes c -### AccountUser.getBuName(buObject, id) ⇒ string +### AccountUser.getBuName(id) ⇒ string helper to print bu names **Kind**: static method of [AccountUser](#AccountUser) @@ -791,13 +791,11 @@ helper to print bu names | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | needed for eid | -| buObject.eid | string | needed to check for parent bu | | id | number | bu id | -### AccountUser.document(buObject, [metadata]) ⇒ Promise.<void> +### AccountUser.document([metadata]) ⇒ Promise.<void> Creates markdown documentation of all roles **Kind**: static method of [AccountUser](#AccountUser) @@ -805,7 +803,6 @@ Creates markdown documentation of all roles | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | properties for auth | | [metadata] | TYPE.MetadataTypeMap | user list | @@ -1303,7 +1300,7 @@ Automation MetadataType * [.parseMetadata(metadata)](#Automation.parseMetadata) ⇒ TYPE.AutomationItem \| void * [._buildSchedule(scheduleObject)](#Automation._buildSchedule) ⇒ TYPE.AutomationScheduleSoap * [._calcTime(offsetServer, dateInput, [offsetInput])](#Automation._calcTime) ⇒ string - * [.document(buObject, [metadata])](#Automation.document) ⇒ Promise.<void> + * [.document([metadata])](#Automation.document) ⇒ Promise.<void> * [.getFilesToCommit(keyArr)](#Automation.getFilesToCommit) ⇒ Array.<string> @@ -1502,7 +1499,7 @@ used to convert dates to the system timezone required for startDate -### Automation.document(buObject, [metadata]) ⇒ Promise.<void> +### Automation.document([metadata]) ⇒ Promise.<void> Parses metadata into a readable Markdown/HTML format then saves it **Kind**: static method of [Automation](#Automation) @@ -1510,7 +1507,6 @@ Parses metadata into a readable Markdown/HTML format then saves it | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | properties for auth | | [metadata] | TYPE.AutomationMap | a list of dataExtension definitions | @@ -1651,7 +1647,7 @@ DataExtension MetadataType * [.retrieveChangelog([buObject], [additionalFields])](#DataExtension.retrieveChangelog) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> * [.postRetrieveTasks(metadata)](#DataExtension.postRetrieveTasks) ⇒ TYPE.DataExtensionItem * [.preDeployTasks(metadata)](#DataExtension.preDeployTasks) ⇒ Promise.<TYPE.DataExtensionItem> - * [.document(buObject, [metadata])](#DataExtension.document) ⇒ Promise.<void> + * [.document([metadata])](#DataExtension.document) ⇒ Promise.<void> * [.deleteByKey(customerKey)](#DataExtension.deleteByKey) ⇒ Promise.<boolean> * [.postDeleteTasks(customerKey)](#DataExtension.postDeleteTasks) ⇒ void * [.retrieveForCache(buObject)](#DataExtension.retrieveForCache) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> @@ -1777,7 +1773,7 @@ prepares a DataExtension for deployment -### DataExtension.document(buObject, [metadata]) ⇒ Promise.<void> +### DataExtension.document([metadata]) ⇒ Promise.<void> Parses metadata into a readable Markdown/HTML format then saves it **Kind**: static method of [DataExtension](#DataExtension) @@ -1785,7 +1781,6 @@ Parses metadata into a readable Markdown/HTML format then saves it | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | properties for auth | | [metadata] | TYPE.DataExtensionMap | a list of dataExtension definitions | @@ -3256,7 +3251,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.readSecondaryFolder(templateDir, typeDirArr, templateName, fileName, ex)](#MetadataType.readSecondaryFolder) ⇒ object * [.buildDefinition(templateDir, targetDir, templateName, variables)](#MetadataType.buildDefinition) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.checkForErrors(ex)](#MetadataType.checkForErrors) ⇒ Array.<string> \| void - * [.document([buObject], [metadata], [isDeploy])](#MetadataType.document) ⇒ void + * [.document([metadata], [isDeploy])](#MetadataType.document) ⇒ void * [.deleteByKey(customerKey)](#MetadataType.deleteByKey) ⇒ boolean * [.postDeleteTasks(customerKey)](#MetadataType.postDeleteTasks) ⇒ void * [.deleteByKeySOAP(customerKey, [handleOutside])](#MetadataType.deleteByKeySOAP) ⇒ boolean @@ -3891,14 +3886,13 @@ Standardizes a check for multiple messages -### MetadataType.document([buObject], [metadata], [isDeploy]) ⇒ void +### MetadataType.document([metadata], [isDeploy]) ⇒ void Gets metadata cache with limited fields and does not store value to disk **Kind**: static method of [MetadataType](#MetadataType) | Param | Type | Description | | --- | --- | --- | -| [buObject] | TYPE.BuObject | properties for auth | | [metadata] | TYPE.MetadataTypeMap | a list of type definitions | | [isDeploy] | boolean | used to skip non-supported message during deploy | @@ -4303,7 +4297,7 @@ ImportFile MetadataType * [.preDeployTasks(metadata)](#Role.preDeployTasks) ⇒ TYPE.MetadataTypeItem * [.create(metadata)](#Role.create) ⇒ Promise * [.update(metadata)](#Role.update) ⇒ Promise - * [.document(buObject, [metadata])](#Role.document) ⇒ Promise.<void> + * [.document([metadata])](#Role.document) ⇒ Promise.<void> * [._traverseRoles(role, element, [permission], [isAllowed])](#Role._traverseRoles) ⇒ void @@ -4360,7 +4354,7 @@ Updates a single Role. -### Role.document(buObject, [metadata]) ⇒ Promise.<void> +### Role.document([metadata]) ⇒ Promise.<void> Creates markdown documentation of all roles **Kind**: static method of [Role](#Role) @@ -4368,7 +4362,6 @@ Creates markdown documentation of all roles | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | properties for auth | | [metadata] | TYPE.MetadataTypeMap | role definitions | diff --git a/lib/index.js b/lib/index.js index 88edffeb9..9bae8032f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -347,7 +347,8 @@ class Mcdev { ); if (buObject !== null) { MetadataTypeInfo[type].properties = properties; - MetadataTypeInfo[type].document(buObject); + MetadataTypeInfo[type].buObject = buObject; + MetadataTypeInfo[type].document(); } } catch (ex) { Util.logger.error('mcdev.document ' + ex.message); diff --git a/lib/metadataTypes/AccountUser.js b/lib/metadataTypes/AccountUser.js index b8b22d41c..d157971a5 100644 --- a/lib/metadataTypes/AccountUser.js +++ b/lib/metadataTypes/AccountUser.js @@ -175,24 +175,21 @@ class AccountUser extends MetadataType { /** * helper to print bu names * - * @param {TYPE.BuObject} buObject needed for eid - * @param {string} buObject.eid needed to check for parent bu * @param {number} id bu id * @returns {string} "bu name (bu id)"" */ - static getBuName(buObject, id) { - const name = buObject.eid == id ? '_ParentBU_' : this.buIdName[id]; + static getBuName(id) { + const name = this.buObject.eid == id ? '_ParentBU_' : this.buIdName[id]; return `${name} (${id})`; } /** * Creates markdown documentation of all roles * - * @param {TYPE.BuObject} buObject properties for auth * @param {TYPE.MetadataTypeMap} [metadata] user list * @returns {Promise.} - */ - static async document(buObject, metadata) { - if (buObject.eid !== buObject.mid) { + static async document(metadata) { + if (this.buObject.eid !== this.buObject.mid) { Util.logger.error( `Users can only be retrieved & documented for the ${Util.parentBuName}` ); @@ -204,7 +201,7 @@ class AccountUser extends MetadataType { metadata = this.readBUMetadataForType( File.normalizePath([ this.properties.directories.retrieve, - buObject.credential, + this.buObject.credential, Util.parentBuName, ]), true @@ -252,12 +249,12 @@ class AccountUser extends MetadataType { if (user.AssociatedBusinessUnits__c) { associatedBus = user.AssociatedBusinessUnits__c.map((item) => { this.buIdName[item.ID] = item.Name; - return this.getBuName(buObject, item.ID); + return this.getBuName(item.ID); }) .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)) .join(',
'); } - const defaultBUName = this.getBuName(buObject, user.DefaultBusinessUnit); + const defaultBUName = this.getBuName(user.DefaultBusinessUnit); users.push({ TYPE: user.type__c, UserID: user.UserID, @@ -297,7 +294,7 @@ class AccountUser extends MetadataType { ['Modified Date', 'ModifiedDate'], ['Created Date', 'CreatedDate'], ]; - let output = `# User Overview - ${buObject.credential}`; + let output = `# User Overview - ${this.buObject.credential}`; output += this._generateDocMd( users.filter((user) => user.TYPE === 'User' && user.ActiveFlag === '✓'), 'User', @@ -316,7 +313,7 @@ class AccountUser extends MetadataType { const docPath = File.normalizePath([this.properties.directories.docs, 'user']); try { - const filename = buObject.credential; + const filename = this.buObject.credential; // write to disk await File.writeToFile(docPath, filename + '.accountUsers', 'md', output); Util.logger.info(`Created ${File.normalizePath([docPath, filename])}.accountUsers.md`); diff --git a/lib/metadataTypes/Automation.js b/lib/metadataTypes/Automation.js index cc966f428..504ff6d30 100644 --- a/lib/metadataTypes/Automation.js +++ b/lib/metadataTypes/Automation.js @@ -75,7 +75,7 @@ class Automation extends MetadataType { Util.getKeysString(key) ); if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) { - await this.document(this.buObject, savedMetadata); + await this.document(savedMetadata); } return { metadata: savedMetadata, type: this.definition.type }; } @@ -930,26 +930,25 @@ class Automation extends MetadataType { /** * Parses metadata into a readable Markdown/HTML format then saves it * - * @param {TYPE.BuObject} buObject properties for auth * @param {TYPE.AutomationMap} [metadata] a list of dataExtension definitions * @returns {Promise.} - */ - static async document(buObject, metadata) { + static async document(metadata) { if (['md', 'both'].includes(this.properties.options.documentType)) { if (!metadata) { metadata = this.readBUMetadataForType( File.normalizePath([ this.properties.directories.retrieve, - buObject.credential, - buObject.businessUnit, + this.buObject.credential, + this.buObject.businessUnit, ]), true ).automation; } const docPath = File.normalizePath([ this.properties.directories.retrieve, - buObject.credential, - buObject.businessUnit, + this.buObject.credential, + this.buObject.businessUnit, this.definition.type, ]); if (!metadata || !Object.keys(metadata).length) { diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index d747f9cb3..065cf866b 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -427,7 +427,7 @@ class DataExtension extends MetadataType { Util.getKeysString(key) ); if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) { - await this.document(buObject, savedMetadata); + await this.document(savedMetadata); } } return { metadata: metadata, type: 'dataExtension' }; @@ -758,18 +758,17 @@ class DataExtension extends MetadataType { /** * Parses metadata into a readable Markdown/HTML format then saves it * - * @param {TYPE.BuObject} buObject properties for auth * @param {TYPE.DataExtensionMap} [metadata] a list of dataExtension definitions * @returns {Promise.} - */ - static async document(buObject, metadata) { + static async document(metadata) { try { if (!metadata) { metadata = this.readBUMetadataForType( File.normalizePath([ this.properties.directories.retrieve, - buObject.credential, - buObject.businessUnit, + this.buObject.credential, + this.buObject.businessUnit, ]), true ).dataExtension; @@ -780,8 +779,8 @@ class DataExtension extends MetadataType { } const docPath = File.normalizePath([ this.properties.directories.retrieve, - buObject.credential, - buObject.businessUnit, + this.buObject.credential, + this.buObject.businessUnit, this.definition.type, ]); if (!metadata || !Object.keys(metadata).length) { diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 4f4b74657..994000631 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -125,7 +125,7 @@ class MetadataType { ) { // * do not await here as this might take a while and has no impact on the deploy // * this should only be run if documentation is on a per metadata record level. Types that document an overview into a single file will need a full retrieve to work instead - this.document(buObject, savedMetadata, true); + this.document(savedMetadata, true); } return upsertResults; } @@ -802,7 +802,7 @@ class MetadataType { buObject && this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type) ) { - await this.document(buObject, savedMetadata); + await this.document(savedMetadata); } } return { metadata: metadata, type: this.definition.type }; @@ -1577,12 +1577,11 @@ class MetadataType { /** * Gets metadata cache with limited fields and does not store value to disk * - * @param {TYPE.BuObject} [buObject] properties for auth * @param {TYPE.MetadataTypeMap} [metadata] a list of type definitions * @param {boolean} [isDeploy] used to skip non-supported message during deploy * @returns {void} */ - static document(buObject, metadata, isDeploy) { + static document(metadata, isDeploy) { if (!isDeploy) { Util.logger.error(`Documenting type ${this.definition.type} is not supported.`); } diff --git a/lib/metadataTypes/Role.js b/lib/metadataTypes/Role.js index 8a0b419e1..676648963 100644 --- a/lib/metadataTypes/Role.js +++ b/lib/metadataTypes/Role.js @@ -71,7 +71,7 @@ class Role extends MetadataType { Util.getKeysString(key) ); if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) { - await this.document(buObject, savedMetadata); + await this.document(savedMetadata); } } return { metadata: parsed, type: this.definition.type }; @@ -114,12 +114,11 @@ class Role extends MetadataType { /** * Creates markdown documentation of all roles * - * @param {TYPE.BuObject} buObject properties for auth * @param {TYPE.MetadataTypeMap} [metadata] role definitions * @returns {Promise.} - */ - static async document(buObject, metadata) { - if (buObject.eid !== buObject.mid) { + static async document(metadata) { + if (this.buObject.eid !== this.buObject.mid) { Util.logger.error( `Roles can only be retrieved & documented for the ${Util.parentBuName}` ); @@ -130,7 +129,7 @@ class Role extends MetadataType { metadata = this.readBUMetadataForType( File.normalizePath([ this.properties.directories.retrieve, - buObject.credential, + this.buObject.credential, Util.parentBuName, ]), true @@ -160,7 +159,7 @@ class Role extends MetadataType { } } // Create output markdown - let output = `# Permission Overview - ${buObject.credential}\n\n`; + let output = `# Permission Overview - ${this.buObject.credential}\n\n`; output += `> **Legend** > >
@@ -212,7 +211,7 @@ class Role extends MetadataType { output += '\n'; } try { - const filename = buObject.credential; + const filename = this.buObject.credential; // write to disk await File.writeToFile(directory, filename + '.roles', 'md', output); Util.logger.info(`Created ${File.normalizePath([directory, filename])}.roles.md`); From 444a3a47a8e0f0ea4c129b875a88b806551e15c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 10:38:52 +0100 Subject: [PATCH 116/132] #593: remove buObject param from retrieveForCache() --- docs/dist/documentation.md | 39 +++++++------------- lib/Deployer.js | 6 +-- lib/Retriever.js | 7 +--- lib/metadataTypes/Asset.js | 3 +- lib/metadataTypes/DataExtension.js | 8 ++-- lib/metadataTypes/Folder.js | 5 +-- lib/metadataTypes/List.js | 8 ++-- lib/metadataTypes/MetadataType.js | 11 +++--- lib/metadataTypes/TriggeredSendDefinition.js | 6 +-- 9 files changed, 32 insertions(+), 61 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 4af1a2b2f..041bee542 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -851,7 +851,7 @@ FileTransfer MetadataType * [Asset](#Asset) ⇐ [MetadataType](#MetadataType) * [.retrieve(retrieveDir, _, __, [subTypeArr], [key])](#Asset.retrieve) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> - * [.retrieveForCache(_, __, [subTypeArr])](#Asset.retrieveForCache) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> + * [.retrieveForCache(_, [subTypeArr])](#Asset.retrieveForCache) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> * [.retrieveAsTemplate(templateDir, name, templateVariables, [selectedSubType])](#Asset.retrieveAsTemplate) ⇒ Promise.<{metadata: TYPE.AssetItem, type: string}> * [.create(metadata)](#Asset.create) ⇒ Promise * [.update(metadata)](#Asset.update) ⇒ Promise @@ -894,7 +894,7 @@ Retrieves Metadata of Asset -### Asset.retrieveForCache(_, __, [subTypeArr]) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> +### Asset.retrieveForCache(_, [subTypeArr]) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> Retrieves asset metadata for caching **Kind**: static method of [Asset](#Asset) @@ -903,7 +903,6 @@ Retrieves asset metadata for caching | Param | Type | Description | | --- | --- | --- | | _ | void | unused | -| __ | void | unused | | [subTypeArr] | Array.<string> | optionally limit to a single subtype | @@ -1650,7 +1649,7 @@ DataExtension MetadataType * [.document([metadata])](#DataExtension.document) ⇒ Promise.<void> * [.deleteByKey(customerKey)](#DataExtension.deleteByKey) ⇒ Promise.<boolean> * [.postDeleteTasks(customerKey)](#DataExtension.postDeleteTasks) ⇒ void - * [.retrieveForCache(buObject)](#DataExtension.retrieveForCache) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> + * [.retrieveForCache()](#DataExtension.retrieveForCache) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> * [.retrieveAsTemplate(templateDir, name, templateVariables)](#DataExtension.retrieveAsTemplate) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> * [.setFolderPath(metadata)](#DataExtension.setFolderPath) * [.getFilesToCommit(keyArr)](#DataExtension.getFilesToCommit) ⇒ Array.<string> @@ -1808,16 +1807,11 @@ clean up after deleting a metadata item -### DataExtension.retrieveForCache(buObject) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> +### DataExtension.retrieveForCache() ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> Retrieves folder metadata into local filesystem. Also creates a uniquePath attribute for each folder. **Kind**: static method of [DataExtension](#DataExtension) **Returns**: Promise.<{metadata: TYPE.DataExtensionMap, type: string}> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| buObject | TYPE.BuObject | properties for auth | - ### DataExtension.retrieveAsTemplate(templateDir, name, templateVariables) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> @@ -2647,7 +2641,7 @@ Folder MetadataType * [Folder](#Folder) ⇐ [MetadataType](#MetadataType) * [.retrieve(retrieveDir, [additionalFields], buObject, [subTypeArr], [key])](#Folder.retrieve) ⇒ Promise - * [.retrieveForCache(buObject, _, [subTypeArr])](#Folder.retrieveForCache) ⇒ Promise + * [.retrieveForCache(_, [subTypeArr])](#Folder.retrieveForCache) ⇒ Promise * [.upsert(metadata)](#Folder.upsert) ⇒ Promise.<object> * [.create(metadataEntry)](#Folder.create) ⇒ Promise * [.update(metadataEntry)](#Folder.update) ⇒ Promise @@ -2675,7 +2669,7 @@ Retrieves metadata of metadata type into local filesystem. executes callback wit -### Folder.retrieveForCache(buObject, _, [subTypeArr]) ⇒ Promise +### Folder.retrieveForCache(_, [subTypeArr]) ⇒ Promise Retrieves folder metadata for caching **Kind**: static method of [Folder](#Folder) @@ -2683,7 +2677,6 @@ Retrieves folder metadata for caching | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | properties for auth | | _ | void | unused | | [subTypeArr] | Array.<string> | content type of folder | @@ -3109,7 +3102,7 @@ List MetadataType * [List](#List) ⇐ [MetadataType](#MetadataType) * [.retrieve(retrieveDir, [_], buObject, [___], [key])](#List.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [.retrieveForCache(buObject)](#List.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieveForCache()](#List.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [._retrieveParentAllSubs(buObject, results)](#List._retrieveParentAllSubs) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.deleteByKey(customerKey)](#List.deleteByKey) ⇒ Promise.<boolean> * [.postRetrieveTasks(list)](#List.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem @@ -3133,16 +3126,11 @@ Retrieves Metadata of Lists -### List.retrieveForCache(buObject) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### List.retrieveForCache() ⇒ Promise.<TYPE.MetadataTypeMapObj> Gets metadata cache with limited fields and does not store value to disk **Kind**: static method of [List](#List) **Returns**: Promise.<TYPE.MetadataTypeMapObj> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| buObject | TYPE.BuObject | properties for auth | - ### List.\_retrieveParentAllSubs(buObject, results) ⇒ Promise.<TYPE.MetadataTypeMapObj> @@ -3214,8 +3202,8 @@ Provides default functionality that can be overwritten by child metadata type cl * [.setFolderPath(metadata)](#MetadataType.setFolderPath) * [.setFolderId(metadata)](#MetadataType.setFolderId) * [.retrieve(retrieveDir, [additionalFields], buObject, [subTypeArr], [key])](#MetadataType.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [.retrieveChangelog([buObject], [additionalFields], [subTypeArr])](#MetadataType.retrieveChangelog) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [.retrieveForCache(buObject, [additionalFields], [subTypeArr])](#MetadataType.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieveChangelog([_], [additionalFields], [subTypeArr])](#MetadataType.retrieveChangelog) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieveForCache([additionalFields], [subTypeArr])](#MetadataType.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveAsTemplate(templateDir, name, templateVariables, [subType])](#MetadataType.retrieveAsTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.buildTemplate(retrieveDir, templateDir, key, templateVariables)](#MetadataType.buildTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.preDeployTasks(metadata, deployDir, buObject)](#MetadataType.preDeployTasks) ⇒ Promise.<TYPE.MetadataTypeItem> @@ -3381,7 +3369,7 @@ Gets metadata from Marketing Cloud -### MetadataType.retrieveChangelog([buObject], [additionalFields], [subTypeArr]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### MetadataType.retrieveChangelog([_], [additionalFields], [subTypeArr]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Gets metadata from Marketing Cloud **Kind**: static method of [MetadataType](#MetadataType) @@ -3389,13 +3377,13 @@ Gets metadata from Marketing Cloud | Param | Type | Description | | --- | --- | --- | -| [buObject] | TYPE.BuObject | properties for auth | +| [_] | void | unused parameter (buObject) | | [additionalFields] | Array.<string> | Returns specified fields even if their retrieve definition is not set to true | | [subTypeArr] | Array.<string> | optionally limit to a single subtype | -### MetadataType.retrieveForCache(buObject, [additionalFields], [subTypeArr]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### MetadataType.retrieveForCache([additionalFields], [subTypeArr]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Gets metadata cache with limited fields and does not store value to disk **Kind**: static method of [MetadataType](#MetadataType) @@ -3403,7 +3391,6 @@ Gets metadata cache with limited fields and does not store value to disk | Param | Type | Description | | --- | --- | --- | -| buObject | TYPE.BuObject | properties for auth | | [additionalFields] | Array.<string> | Returns specified fields even if their retrieve definition is not set to true | | [subTypeArr] | Array.<string> | optionally limit to a single subtype | diff --git a/lib/Deployer.js b/lib/Deployer.js index e0d8b3931..5e8bb78d4 100644 --- a/lib/Deployer.js +++ b/lib/Deployer.js @@ -260,11 +260,7 @@ class Deployer { MetadataTypeInfo[type].buObject = this.buObject; Util.logger.info(`Caching dependent Metadata: ${metadataType}`); Util.logSubtypes(subTypeArr); - const result = await MetadataTypeInfo[type].retrieveForCache( - this.buObject, - null, - subTypeArr - ); + const result = await MetadataTypeInfo[type].retrieveForCache(null, subTypeArr); cache.setMetadata(type, result.metadata); } /** @type {TYPE.MultiMetadataTypeMap} */ diff --git a/lib/Retriever.js b/lib/Retriever.js index 13532f57d..a07b719fe 100644 --- a/lib/Retriever.js +++ b/lib/Retriever.js @@ -81,11 +81,7 @@ class Retriever { } Util.logger.info(`Caching dependent Metadata: ${metadataType}`); Util.logSubtypes(subTypeArr); - result = await MetadataTypeInfo[type].retrieveForCache( - this.buObject, - null, - subTypeArr - ); + result = await MetadataTypeInfo[type].retrieveForCache(null, subTypeArr); } else if (templateVariables) { // type is in list of types to retrieve and we have template variables Util.logger.info(`Retrieving as Template: ${metadataType}`); @@ -118,7 +114,6 @@ class Retriever { Util.logger.info(`Caching dependent Metadata: ${metadataType}`); Util.logSubtypes(subTypeArr); cacheResult = await MetadataTypeInfo[type].retrieveForCache( - this.buObject, null, subTypeArr ); diff --git a/lib/metadataTypes/Asset.js b/lib/metadataTypes/Asset.js index 0fd329aa5..355c8c92c 100644 --- a/lib/metadataTypes/Asset.js +++ b/lib/metadataTypes/Asset.js @@ -57,11 +57,10 @@ class Asset extends MetadataType { * Retrieves asset metadata for caching * * @param {void} _ unused - * @param {void} __ unused * @param {string[]} [subTypeArr] optionally limit to a single subtype * @returns {Promise.<{metadata: TYPE.AssetMap, type: string}>} Promise */ - static retrieveForCache(_, __, subTypeArr) { + static retrieveForCache(_, subTypeArr) { return this.retrieve(null, null, null, subTypeArr); } diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index 065cf866b..6ecf42dfb 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -382,8 +382,9 @@ class DataExtension extends MetadataType { Util.logger.info(' - Caching dependent Metadata: folder (shared via _ParentBU_)'); Util.logSubtypes(subTypeArr); Folder.client = this.client; + Folder.buObject = buObjectParentBu; Folder.properties = this.properties; - const result = await Folder.retrieveForCache(buObjectParentBu, null, subTypeArr); + const result = await Folder.retrieveForCache(null, subTypeArr); cache.mergeMetadata('folder', result.metadata, buObject.eid); // get the types and clean out non-shared ones @@ -874,11 +875,10 @@ class DataExtension extends MetadataType { /** * Retrieves folder metadata into local filesystem. Also creates a uniquePath attribute for each folder. * - * @param {TYPE.BuObject} buObject properties for auth * @returns {Promise.<{metadata: TYPE.DataExtensionMap, type: string}>} Promise */ - static async retrieveForCache(buObject) { - return this.retrieve(null, ['ObjectID', 'CustomerKey', 'Name'], buObject, null, null); + static async retrieveForCache() { + return this.retrieve(null, ['ObjectID', 'CustomerKey', 'Name'], this.buObject, null, null); } /** * Retrieves dataExtension metadata in template format. diff --git a/lib/metadataTypes/Folder.js b/lib/metadataTypes/Folder.js index bc8fb8fff..7b3386e5e 100644 --- a/lib/metadataTypes/Folder.js +++ b/lib/metadataTypes/Folder.js @@ -151,13 +151,12 @@ class Folder extends MetadataType { /** * Retrieves folder metadata for caching * - * @param {TYPE.BuObject} buObject properties for auth * @param {void} _ unused * @param {string[]} [subTypeArr] content type of folder * @returns {Promise} Promise */ - static retrieveForCache(buObject, _, subTypeArr) { - return this.retrieve(null, null, buObject, subTypeArr, null); + static retrieveForCache(_, subTypeArr) { + return this.retrieve(null, null, this.buObject, subTypeArr, null); } /** diff --git a/lib/metadataTypes/List.js b/lib/metadataTypes/List.js index 891df4e66..aad9a2a29 100644 --- a/lib/metadataTypes/List.js +++ b/lib/metadataTypes/List.js @@ -50,11 +50,10 @@ class List extends MetadataType { /** * Gets metadata cache with limited fields and does not store value to disk * - * @param {TYPE.BuObject} buObject properties for auth * @returns {Promise.} Promise of metadata */ - static async retrieveForCache(buObject) { - const results = await this.retrieve(null, null, buObject); + static async retrieveForCache() { + const results = await this.retrieve(null, null, this.buObject); if (!cache.getCache()?.folder) { const subTypeArr = [ 'list', @@ -67,8 +66,9 @@ class List extends MetadataType { Util.logger.info(' - Caching dependent Metadata: folder'); Util.logSubtypes(subTypeArr); Folder.client = this.client; + Folder.buObject = this.buObject; Folder.properties = this.properties; - const result = await Folder.retrieveForCache(buObject, null, subTypeArr); + const result = await Folder.retrieveForCache(null, subTypeArr); cache.setMetadata('folder', result.metadata); } for (const metadataEntry in results.metadata) { diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 994000631..89828df45 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -211,25 +211,24 @@ class MetadataType { /** * Gets metadata from Marketing Cloud * - * @param {TYPE.BuObject} [buObject] properties for auth + * @param {void} [_] unused parameter (buObject) * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true * @param {string[]} [subTypeArr] optionally limit to a single subtype * @returns {Promise.} metadata */ - static retrieveChangelog(buObject, additionalFields, subTypeArr) { - return this.retrieveForCache(buObject, additionalFields, subTypeArr); + static retrieveChangelog(_, additionalFields, subTypeArr) { + return this.retrieveForCache(additionalFields, subTypeArr); } /** * Gets metadata cache with limited fields and does not store value to disk * - * @param {TYPE.BuObject} buObject properties for auth * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true * @param {string[]} [subTypeArr] optionally limit to a single subtype * @returns {Promise.} metadata */ - static async retrieveForCache(buObject, additionalFields, subTypeArr) { - return this.retrieve(null, additionalFields, buObject, subTypeArr); + static async retrieveForCache(additionalFields, subTypeArr) { + return this.retrieve(null, additionalFields, this.buObject, subTypeArr); } /** * Gets metadata cache with limited fields and does not store value to disk diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index 59856fcd4..2fbf283df 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -298,11 +298,7 @@ class TriggeredSendDefinition extends MetadataType { cacheTypes[type].buObject = this.buObject; cacheTypes[type].properties = this.properties; - const result = await cacheTypes[type].retrieveForCache( - this.buObject, - null, - subTypeArr - ); + const result = await cacheTypes[type].retrieveForCache(null, subTypeArr); cache.setMetadata(type, result.metadata); } } From 74ca453e6efa659d34c5137d48a66be88b34aa7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 13:48:48 +0100 Subject: [PATCH 117/132] #593: remove buObject param from retrieve() --- docs/dist/documentation.md | 178 +++++++------------ lib/Retriever.js | 1 - lib/metadataTypes/AccountUser.js | 19 +- lib/metadataTypes/Asset.js | 5 +- lib/metadataTypes/AttributeGroup.js | 3 +- lib/metadataTypes/Automation.js | 3 +- lib/metadataTypes/Campaign.js | 3 +- lib/metadataTypes/ContentArea.js | 3 +- lib/metadataTypes/DataExtension.js | 15 +- lib/metadataTypes/DataExtensionField.js | 5 +- lib/metadataTypes/DataExtensionTemplate.js | 3 +- lib/metadataTypes/DataExtract.js | 3 +- lib/metadataTypes/DataExtractType.js | 3 +- lib/metadataTypes/Discovery.js | 7 +- lib/metadataTypes/Email.js | 3 +- lib/metadataTypes/EmailSendDefinition.js | 3 +- lib/metadataTypes/EventDefinition.js | 3 +- lib/metadataTypes/FileTransfer.js | 3 +- lib/metadataTypes/Filter.js | 3 +- lib/metadataTypes/Folder.js | 13 +- lib/metadataTypes/FtpLocation.js | 3 +- lib/metadataTypes/ImportFile.js | 3 +- lib/metadataTypes/Interaction.js | 3 +- lib/metadataTypes/List.js | 37 ++-- lib/metadataTypes/MetadataType.js | 5 +- lib/metadataTypes/MobileCode.js | 3 +- lib/metadataTypes/MobileKeyword.js | 3 +- lib/metadataTypes/Query.js | 3 +- lib/metadataTypes/Role.js | 5 +- lib/metadataTypes/Script.js | 3 +- lib/metadataTypes/SetDefinition.js | 3 +- lib/metadataTypes/TransactionalMessage.js | 3 +- lib/metadataTypes/TriggeredSendDefinition.js | 3 +- 33 files changed, 135 insertions(+), 221 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 041bee542..a1be8835b 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -734,8 +734,8 @@ MessageSendActivity MetadataType **Extends**: [MetadataType](#MetadataType) * [AccountUser](#AccountUser) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, _, buObject, [___], [key])](#AccountUser.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [.retrieveChangelog(buObject)](#AccountUser.retrieveChangelog) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, _, [__], [key])](#AccountUser.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieveChangelog()](#AccountUser.retrieveChangelog) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.timeSinceDate(date)](#AccountUser.timeSinceDate) ⇒ number * [.getBuName(id)](#AccountUser.getBuName) ⇒ string * [.document([metadata])](#AccountUser.document) ⇒ Promise.<void> @@ -745,7 +745,7 @@ MessageSendActivity MetadataType -### AccountUser.retrieve(retrieveDir, _, buObject, [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### AccountUser.retrieve(retrieveDir, _, [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata **Kind**: static method of [AccountUser](#AccountUser) @@ -755,22 +755,16 @@ Retrieves SOAP based metadata of metadata type into local filesystem. executes c | --- | --- | --- | | retrieveDir | string | Directory where retrieved metadata directory will be saved | | _ | void | unused parameter | -| buObject | TYPE.BuObject | properties for auth | -| [___] | void | unused parameter | +| [__] | void | unused parameter | | [key] | string | customer key of single item to retrieve | -### AccountUser.retrieveChangelog(buObject) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### AccountUser.retrieveChangelog() ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata **Kind**: static method of [AccountUser](#AccountUser) **Returns**: Promise.<TYPE.MetadataTypeMapObj> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| buObject | TYPE.BuObject | properties for auth | - ### AccountUser.timeSinceDate(date) ⇒ number @@ -850,7 +844,7 @@ FileTransfer MetadataType **Extends**: [MetadataType](#MetadataType) * [Asset](#Asset) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, _, __, [subTypeArr], [key])](#Asset.retrieve) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> + * [.retrieve(retrieveDir, _, [subTypeArr], [key])](#Asset.retrieve) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> * [.retrieveForCache(_, [subTypeArr])](#Asset.retrieveForCache) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> * [.retrieveAsTemplate(templateDir, name, templateVariables, [selectedSubType])](#Asset.retrieveAsTemplate) ⇒ Promise.<{metadata: TYPE.AssetItem, type: string}> * [.create(metadata)](#Asset.create) ⇒ Promise @@ -878,7 +872,7 @@ FileTransfer MetadataType -### Asset.retrieve(retrieveDir, _, __, [subTypeArr], [key]) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> +### Asset.retrieve(retrieveDir, _, [subTypeArr], [key]) ⇒ Promise.<{metadata: TYPE.AssetMap, type: string}> Retrieves Metadata of Asset **Kind**: static method of [Asset](#Asset) @@ -888,7 +882,6 @@ Retrieves Metadata of Asset | --- | --- | --- | | retrieveDir | string | Directory where retrieved metadata directory will be saved | | _ | void | - | -| __ | void | - | | [subTypeArr] | Array.<TYPE.AssetSubType> | optionally limit to a single subtype | | [key] | string | customer key | @@ -1248,12 +1241,12 @@ AttributeGroup MetadataType **Extends**: [MetadataType](#MetadataType) * [AttributeGroup](#AttributeGroup) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#AttributeGroup.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#AttributeGroup.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache()](#AttributeGroup.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> -### AttributeGroup.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### AttributeGroup.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of schema attribute groups. **Kind**: static method of [AttributeGroup](#AttributeGroup) @@ -1264,7 +1257,6 @@ Retrieves Metadata of schema attribute groups. | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -1283,7 +1275,7 @@ Automation MetadataType **Extends**: [MetadataType](#MetadataType) * [Automation](#Automation) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#Automation.retrieve) ⇒ Promise.<TYPE.AutomationMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#Automation.retrieve) ⇒ Promise.<TYPE.AutomationMapObj> * [.retrieveChangelog()](#Automation.retrieveChangelog) ⇒ Promise.<TYPE.AutomationMapObj> * [.retrieveForCache()](#Automation.retrieveForCache) ⇒ Promise.<TYPE.AutomationMapObj> * [.retrieveAsTemplate(templateDir, name, templateVariables)](#Automation.retrieveAsTemplate) ⇒ Promise.<TYPE.AutomationItemObj> @@ -1304,7 +1296,7 @@ Automation MetadataType -### Automation.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.AutomationMapObj> +### Automation.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.AutomationMapObj> Retrieves Metadata of Automation **Kind**: static method of [Automation](#Automation) @@ -1315,7 +1307,6 @@ Retrieves Metadata of Automation | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -1530,12 +1521,12 @@ Campaign MetadataType **Extends**: [MetadataType](#MetadataType) * [Campaign](#Campaign) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#Campaign.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#Campaign.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.getAssetTags(retrieveDir, id, name)](#Campaign.getAssetTags) ⇒ Promise.<TYPE.MetadataTypeMapObj> -### Campaign.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### Campaign.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of campaigns. Afterwards, starts metadata retrieval for their campaign assets **Kind**: static method of [Campaign](#Campaign) @@ -1546,7 +1537,6 @@ Retrieves Metadata of campaigns. Afterwards, starts metadata retrieval for their | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -1572,14 +1562,14 @@ ContentArea MetadataType **Extends**: [MetadataType](#MetadataType) * [ContentArea](#ContentArea) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#ContentArea.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#ContentArea.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.postRetrieveTasks(metadata)](#ContentArea.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.setFolderPath(metadata)](#ContentArea.setFolderPath) * [.parseMetadata(metadata)](#ContentArea.parseMetadata) ⇒ TYPE.MetadataTypeItem -### ContentArea.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### ContentArea.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata **Kind**: static method of [ContentArea](#ContentArea) @@ -1590,7 +1580,6 @@ Retrieves SOAP based metadata of metadata type into local filesystem. executes c | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -1642,7 +1631,7 @@ DataExtension MetadataType * [.create(metadata)](#DataExtension.create) ⇒ Promise * [.update(metadata)](#DataExtension.update) ⇒ Promise * [.postDeployTasks(upsertedMetadata, originalMetadata)](#DataExtension.postDeployTasks) ⇒ void - * [.retrieve(retrieveDir, [additionalFields], buObject, [_], [key])](#DataExtension.retrieve) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> + * [.retrieve(retrieveDir, [additionalFields], [_], [key])](#DataExtension.retrieve) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> * [.retrieveChangelog([buObject], [additionalFields])](#DataExtension.retrieveChangelog) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> * [.postRetrieveTasks(metadata)](#DataExtension.postRetrieveTasks) ⇒ TYPE.DataExtensionItem * [.preDeployTasks(metadata)](#DataExtension.preDeployTasks) ⇒ Promise.<TYPE.DataExtensionItem> @@ -1719,7 +1708,7 @@ Gets executed after deployment of metadata type -### DataExtension.retrieve(retrieveDir, [additionalFields], buObject, [_], [key]) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> +### DataExtension.retrieve(retrieveDir, [additionalFields], [_], [key]) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> Retrieves dataExtension metadata. Afterwards starts retrieval of dataExtensionColumn metadata retrieval **Kind**: static method of [DataExtension](#DataExtension) @@ -1729,7 +1718,6 @@ Retrieves dataExtension metadata. Afterwards starts retrieval of dataExtensionCo | --- | --- | --- | | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [additionalFields] | Array.<string> | Returns specified fields even if their retrieve definition is not set to true | -| buObject | TYPE.BuObject | properties for auth | | [_] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -1860,7 +1848,7 @@ DataExtensionField MetadataType **Extends**: [MetadataType](#MetadataType) * [DataExtensionField](#DataExtensionField) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [additionalFields], buObject)](#DataExtensionField.retrieve) ⇒ Promise.<{metadata: TYPE.DataExtensionFieldMap, type: string}> + * [.retrieve(retrieveDir, [additionalFields])](#DataExtensionField.retrieve) ⇒ Promise.<{metadata: TYPE.DataExtensionFieldMap, type: string}> * [.retrieveForCache([requestParams], [additionalFields])](#DataExtensionField.retrieveForCache) ⇒ Promise.<{metadata: TYPE.DataExtensionFieldMap, type: string}> * [.convertToSortedArray(fieldsObj)](#DataExtensionField.convertToSortedArray) ⇒ Array.<TYPE.DataExtensionFieldItem> * [.sortDeFields(a, b)](#DataExtensionField.sortDeFields) ⇒ boolean @@ -1872,7 +1860,7 @@ DataExtensionField MetadataType -### DataExtensionField.retrieve(retrieveDir, [additionalFields], buObject) ⇒ Promise.<{metadata: TYPE.DataExtensionFieldMap, type: string}> +### DataExtensionField.retrieve(retrieveDir, [additionalFields]) ⇒ Promise.<{metadata: TYPE.DataExtensionFieldMap, type: string}> Retrieves all records and saves it to disk **Kind**: static method of [DataExtensionField](#DataExtensionField) @@ -1882,7 +1870,6 @@ Retrieves all records and saves it to disk | --- | --- | --- | | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [additionalFields] | Array.<string> | Returns specified fields even if their retrieve definition is not set to true | -| buObject | TYPE.BuObject | properties for auth | @@ -1994,7 +1981,7 @@ DataExtensionTemplate MetadataType **Extends**: [MetadataType](#MetadataType) -### DataExtensionTemplate.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### DataExtensionTemplate.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata **Kind**: static method of [DataExtensionTemplate](#DataExtensionTemplate) @@ -2005,7 +1992,6 @@ Retrieves SOAP based metadata of metadata type into local filesystem. executes c | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -2017,7 +2003,7 @@ DataExtract MetadataType **Extends**: [MetadataType](#MetadataType) * [DataExtract](#DataExtract) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#DataExtract.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#DataExtract.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache()](#DataExtract.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveAsTemplate(templateDir, name, templateVariables)](#DataExtract.retrieveAsTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.postRetrieveTasks(fileTransfer)](#DataExtract.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem @@ -2028,7 +2014,7 @@ DataExtract MetadataType -### DataExtract.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### DataExtract.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of Data Extract Activity. Endpoint /automation/v1/dataextracts/ returns all Data Extracts @@ -2040,7 +2026,6 @@ Endpoint /automation/v1/dataextracts/ returns all Data Extracts | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -2135,12 +2120,12 @@ as this is a configuration in the EID **Extends**: [MetadataType](#MetadataType) * [DataExtractType](#DataExtractType) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#DataExtractType.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#DataExtractType.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache()](#DataExtractType.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> -### DataExtractType.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### DataExtractType.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of Data Extract Type. **Kind**: static method of [DataExtractType](#DataExtractType) @@ -2151,7 +2136,6 @@ Retrieves Metadata of Data Extract Type. | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -2170,7 +2154,7 @@ ImportFile MetadataType **Extends**: [MetadataType](#MetadataType) -### Discovery.retrieve(retrieveDir, [_], buObject, [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### Discovery.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves API endpoint documentation: https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/routes.htm @@ -2181,8 +2165,7 @@ documentation: https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-ap | --- | --- | --- | | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | not used | -| buObject | TYPE.BuObject | properties for auth | -| [___] | void | unused parameter | +| [__] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -2194,13 +2177,13 @@ Email MetadataType **Extends**: [MetadataType](#MetadataType) * [Email](#Email) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#Email.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#Email.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.postRetrieveTasks(metadata)](#Email.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.parseMetadata(metadata)](#Email.parseMetadata) ⇒ TYPE.MetadataTypeItem -### Email.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### Email.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata **Kind**: static method of [Email](#Email) @@ -2211,7 +2194,6 @@ Retrieves SOAP based metadata of metadata type into local filesystem. executes c | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -2247,7 +2229,7 @@ MessageSendActivity MetadataType **Extends**: [MetadataType](#MetadataType) * [EmailSendDefinition](#EmailSendDefinition) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#EmailSendDefinition.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#EmailSendDefinition.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.update(metadataItem)](#EmailSendDefinition.update) ⇒ Promise * [.create(metadataItem)](#EmailSendDefinition.create) ⇒ Promise * [.deleteByKey(customerKey)](#EmailSendDefinition.deleteByKey) ⇒ Promise.<boolean> @@ -2257,7 +2239,7 @@ MessageSendActivity MetadataType -### EmailSendDefinition.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### EmailSendDefinition.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata **Kind**: static method of [EmailSendDefinition](#EmailSendDefinition) @@ -2268,7 +2250,6 @@ Retrieves SOAP based metadata of metadata type into local filesystem. executes c | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -2352,7 +2333,7 @@ EventDefinition MetadataType **Extends**: [MetadataType](#MetadataType) * [EventDefinition](#EventDefinition) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#EventDefinition.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#EventDefinition.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache()](#EventDefinition.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveAsTemplate(templateDir, name, templateVariables)](#EventDefinition.retrieveAsTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.postRetrieveTasks(eventDef)](#EventDefinition.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem @@ -2365,7 +2346,7 @@ EventDefinition MetadataType -### EventDefinition.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### EventDefinition.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of Event Definition. Endpoint /interaction/v1/EventDefinitions return all Event Definitions with all details. Currently it is not needed to loop over Imports with endpoint /interaction/v1/EventDefinitions/{id} @@ -2378,7 +2359,6 @@ Currently it is not needed to loop over Imports with endpoint /interaction/v1/Ev | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -2498,7 +2478,7 @@ FileTransfer MetadataType **Extends**: [MetadataType](#MetadataType) * [FileTransfer](#FileTransfer) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#FileTransfer.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#FileTransfer.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache()](#FileTransfer.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveAsTemplate(templateDir, name, templateVariables)](#FileTransfer.retrieveAsTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.postRetrieveTasks(metadata)](#FileTransfer.postRetrieveTasks) ⇒ Array.<object> @@ -2509,7 +2489,7 @@ FileTransfer MetadataType -### FileTransfer.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### FileTransfer.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of FileTransfer Activity. Endpoint /automation/v1/filetransfers/ returns all File Transfers @@ -2521,7 +2501,6 @@ Endpoint /automation/v1/filetransfers/ returns all File Transfers | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -2614,7 +2593,7 @@ Filter MetadataType **Extends**: [MetadataType](#MetadataType) -### Filter.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### Filter.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of Filter. Endpoint /automation/v1/filters/ returns all Filters, but only with some of the fields. So it is needed to loop over @@ -2628,7 +2607,6 @@ Filters with the endpoint /automation/v1/filters/{id} | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -2640,7 +2618,7 @@ Folder MetadataType **Extends**: [MetadataType](#MetadataType) * [Folder](#Folder) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [additionalFields], buObject, [subTypeArr], [key])](#Folder.retrieve) ⇒ Promise + * [.retrieve(retrieveDir, [additionalFields], [subTypeArr], [key])](#Folder.retrieve) ⇒ Promise * [.retrieveForCache(_, [subTypeArr])](#Folder.retrieveForCache) ⇒ Promise * [.upsert(metadata)](#Folder.upsert) ⇒ Promise.<object> * [.create(metadataEntry)](#Folder.create) ⇒ Promise @@ -2653,7 +2631,7 @@ Folder MetadataType -### Folder.retrieve(retrieveDir, [additionalFields], buObject, [subTypeArr], [key]) ⇒ Promise +### Folder.retrieve(retrieveDir, [additionalFields], [subTypeArr], [key]) ⇒ Promise Retrieves metadata of metadata type into local filesystem. executes callback with retrieved metadata **Kind**: static method of [Folder](#Folder) @@ -2663,7 +2641,6 @@ Retrieves metadata of metadata type into local filesystem. executes callback wit | --- | --- | --- | | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [additionalFields] | Array.<string> | Returns specified fields even if their retrieve definition is not set to true | -| buObject | TYPE.BuObject | properties for auth | | [subTypeArr] | Array.<string> | content type of folder | | [key] | string | customer key of single item to retrieve | @@ -2792,12 +2769,12 @@ ImportFile MetadataType **Extends**: [MetadataType](#MetadataType) * [FtpLocation](#FtpLocation) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#FtpLocation.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#FtpLocation.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache()](#FtpLocation.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> -### FtpLocation.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### FtpLocation.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of FtpLocation Endpoint /automation/v1/ftplocations/ return all FtpLocations @@ -2809,7 +2786,6 @@ Endpoint /automation/v1/ftplocations/ return all FtpLocations | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -2828,7 +2804,7 @@ ImportFile MetadataType **Extends**: [MetadataType](#MetadataType) * [ImportFile](#ImportFile) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#ImportFile.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#ImportFile.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache()](#ImportFile.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveAsTemplate(templateDir, name, templateVariables)](#ImportFile.retrieveAsTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.postRetrieveTasks(importDef)](#ImportFile.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem @@ -2839,7 +2815,7 @@ ImportFile MetadataType -### ImportFile.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### ImportFile.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of Import File. Endpoint /automation/v1/imports/ return all Import Files with all details. Currently it is not needed to loop over Imports with endpoint /automation/v1/imports/{id} @@ -2852,7 +2828,6 @@ Currently it is not needed to loop over Imports with endpoint /automation/v1/imp | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -2949,7 +2924,7 @@ definitionId: A unique UUID provided by Salesforce Marketing Cloud. Each version **Extends**: [MetadataType](#MetadataType) * [Interaction](#Interaction) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#Interaction.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#Interaction.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.deleteByKey(key)](#Interaction.deleteByKey) ⇒ Promise.<boolean> * [.deploy(metadata, deployDir, retrieveDir, buObject)](#Interaction.deploy) ⇒ Promise.<TYPE.MetadataTypeMap> * [.update(metadata)](#Interaction.update) ⇒ Promise @@ -2962,7 +2937,7 @@ definitionId: A unique UUID provided by Salesforce Marketing Cloud. Each version -### Interaction.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### Interaction.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of Interaction **Kind**: static method of [Interaction](#Interaction) @@ -2973,7 +2948,6 @@ Retrieves Metadata of Interaction | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -3101,16 +3075,15 @@ List MetadataType **Extends**: [MetadataType](#MetadataType) * [List](#List) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], buObject, [___], [key])](#List.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#List.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache()](#List.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [._retrieveParentAllSubs(buObject, results)](#List._retrieveParentAllSubs) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.deleteByKey(customerKey)](#List.deleteByKey) ⇒ Promise.<boolean> * [.postRetrieveTasks(list)](#List.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.parseMetadata(metadata, [parseForCache])](#List.parseMetadata) ⇒ TYPE.MetadataTypeItem -### List.retrieve(retrieveDir, [_], buObject, [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### List.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of Lists **Kind**: static method of [List](#List) @@ -3120,8 +3093,7 @@ Retrieves Metadata of Lists | --- | --- | --- | | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | -| buObject | TYPE.BuObject | properties for auth | -| [___] | void | unused parameter | +| [__] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -3131,19 +3103,6 @@ Gets metadata cache with limited fields and does not store value to disk **Kind**: static method of [List](#List) **Returns**: Promise.<TYPE.MetadataTypeMapObj> - Promise of metadata - - -### List.\_retrieveParentAllSubs(buObject, results) ⇒ Promise.<TYPE.MetadataTypeMapObj> -helper for @link retrieveForCache and @link retrieve - -**Kind**: static method of [List](#List) -**Returns**: Promise.<TYPE.MetadataTypeMapObj> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| buObject | TYPE.BuObject | properties for auth | -| results | TYPE.MetadataTypeMapObj | metadata from retrieve for current BU | - ### List.deleteByKey(customerKey) ⇒ Promise.<boolean> @@ -3201,7 +3160,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.postRetrieveTasks(metadata, targetDir, [isTemplating])](#MetadataType.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.setFolderPath(metadata)](#MetadataType.setFolderPath) * [.setFolderId(metadata)](#MetadataType.setFolderId) - * [.retrieve(retrieveDir, [additionalFields], buObject, [subTypeArr], [key])](#MetadataType.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [additionalFields], [subTypeArr], [key])](#MetadataType.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveChangelog([_], [additionalFields], [subTypeArr])](#MetadataType.retrieveChangelog) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache([additionalFields], [subTypeArr])](#MetadataType.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveAsTemplate(templateDir, name, templateVariables, [subType])](#MetadataType.retrieveAsTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> @@ -3353,7 +3312,7 @@ generic script that retrieves the folder ID from cache and updates the given met -### MetadataType.retrieve(retrieveDir, [additionalFields], buObject, [subTypeArr], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### MetadataType.retrieve(retrieveDir, [additionalFields], [subTypeArr], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Gets metadata from Marketing Cloud **Kind**: static method of [MetadataType](#MetadataType) @@ -3363,7 +3322,6 @@ Gets metadata from Marketing Cloud | --- | --- | --- | | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [additionalFields] | Array.<string> | Returns specified fields even if their retrieve definition is not set to true | -| buObject | TYPE.BuObject | properties for auth | | [subTypeArr] | Array.<string> | optionally limit to a single subtype | | [key] | string | customer key of single item to retrieve | @@ -3969,12 +3927,12 @@ MobileCode MetadataType **Extends**: [MetadataType](#MetadataType) * [MobileCode](#MobileCode) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#MobileCode.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#MobileCode.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache()](#MobileCode.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> -### MobileCode.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### MobileCode.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of Mobile Keywords Endpoint /legacy/v1/beta/mobile/code/ return all Mobile Codes with all details. @@ -3986,7 +3944,6 @@ Endpoint /legacy/v1/beta/mobile/code/ return all Mobile Codes with all details. | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -4005,7 +3962,7 @@ MobileKeyword MetadataType **Extends**: [MetadataType](#MetadataType) * [MobileKeyword](#MobileKeyword) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#MobileKeyword.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#MobileKeyword.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache()](#MobileKeyword.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveAsTemplate(templateDir, name, templateVariables)](#MobileKeyword.retrieveAsTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.create(MobileKeyword)](#MobileKeyword.create) ⇒ Promise @@ -4013,7 +3970,7 @@ MobileKeyword MetadataType -### MobileKeyword.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### MobileKeyword.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of Mobile Keywords Endpoint /legacy/v1/beta/mobile/keyword/ return all Mobile Keywords with all details. @@ -4025,7 +3982,6 @@ Endpoint /legacy/v1/beta/mobile/keyword/ return all Mobile Keywords with all det | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -4082,7 +4038,7 @@ Query MetadataType **Extends**: [MetadataType](#MetadataType) * [Query](#Query) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#Query.retrieve) ⇒ Promise.<{metadata: TYPE.QueryMap, type: string}> + * [.retrieve(retrieveDir, [_], [__], [key])](#Query.retrieve) ⇒ Promise.<{metadata: TYPE.QueryMap, type: string}> * [.retrieveForCache()](#Query.retrieveForCache) ⇒ Promise.<{metadata: TYPE.QueryMap, type: string}> * [.retrieveAsTemplate(templateDir, name, templateVariables)](#Query.retrieveAsTemplate) ⇒ Promise.<{metadata: Query, type: string}> * [.postRetrieveTasks(metadata)](#Query.postRetrieveTasks) ⇒ TYPE.CodeExtractItem @@ -4098,7 +4054,7 @@ Query MetadataType -### Query.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<{metadata: TYPE.QueryMap, type: string}> +### Query.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<{metadata: TYPE.QueryMap, type: string}> Retrieves Metadata of queries **Kind**: static method of [Query](#Query) @@ -4109,7 +4065,6 @@ Retrieves Metadata of queries | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -4280,7 +4235,7 @@ ImportFile MetadataType **Extends**: [MetadataType](#MetadataType) * [Role](#Role) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, _, buObject, [___], [key])](#Role.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, _, [___], [key])](#Role.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.preDeployTasks(metadata)](#Role.preDeployTasks) ⇒ TYPE.MetadataTypeItem * [.create(metadata)](#Role.create) ⇒ Promise * [.update(metadata)](#Role.update) ⇒ Promise @@ -4289,7 +4244,7 @@ ImportFile MetadataType -### Role.retrieve(retrieveDir, _, buObject, [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### Role.retrieve(retrieveDir, _, [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Gets metadata from Marketing Cloud **Kind**: static method of [Role](#Role) @@ -4299,7 +4254,6 @@ Gets metadata from Marketing Cloud | --- | --- | --- | | retrieveDir | string | Directory where retrieved metadata directory will be saved | | _ | Array.<string> | Returns specified fields even if their retrieve definition is not set to true | -| buObject | TYPE.BuObject | properties for auth | | [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -4374,7 +4328,7 @@ Script MetadataType **Extends**: [MetadataType](#MetadataType) * [Script](#Script) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#Script.retrieve) ⇒ Promise.<{metadata: TYPE.ScriptMap, type: string}> + * [.retrieve(retrieveDir, [_], [__], [key])](#Script.retrieve) ⇒ Promise.<{metadata: TYPE.ScriptMap, type: string}> * [.retrieveForCache()](#Script.retrieveForCache) ⇒ Promise.<{metadata: TYPE.ScriptMap, type: string}> * [.retrieveAsTemplate(templateDir, name, templateVariables)](#Script.retrieveAsTemplate) ⇒ Promise.<{metadata: TYPE.Script, type: string}> * [.postRetrieveTasks(metadata)](#Script.postRetrieveTasks) ⇒ TYPE.CodeExtractItem @@ -4391,7 +4345,7 @@ Script MetadataType -### Script.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<{metadata: TYPE.ScriptMap, type: string}> +### Script.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<{metadata: TYPE.ScriptMap, type: string}> Retrieves Metadata of Script Endpoint /automation/v1/scripts/ return all Scripts with all details. @@ -4403,7 +4357,6 @@ Endpoint /automation/v1/scripts/ return all Scripts with all details. | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -4593,12 +4546,12 @@ SetDefinition MetadataType **Extends**: [MetadataType](#MetadataType) * [SetDefinition](#SetDefinition) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#SetDefinition.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#SetDefinition.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache()](#SetDefinition.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> -### SetDefinition.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### SetDefinition.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of schema set Definitions. **Kind**: static method of [SetDefinition](#SetDefinition) @@ -4609,7 +4562,6 @@ Retrieves Metadata of schema set Definitions. | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -4677,7 +4629,7 @@ TransactionalMessage MetadataType **Extends**: [MetadataType](#MetadataType) * [TransactionalMessage](#TransactionalMessage) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#TransactionalMessage.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#TransactionalMessage.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache()](#TransactionalMessage.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.update(metadata)](#TransactionalMessage.update) ⇒ Promise * [.create(metadata)](#TransactionalMessage.create) ⇒ Promise @@ -4685,7 +4637,7 @@ TransactionalMessage MetadataType -### TransactionalMessage.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### TransactionalMessage.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves Metadata of Mobile Keywords Endpoint /legacy/v1/beta/mobile/code/ return all Mobile Codes with all details. @@ -4697,7 +4649,6 @@ Endpoint /legacy/v1/beta/mobile/code/ return all Mobile Codes with all details. | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | @@ -4951,7 +4902,7 @@ MessageSendActivity MetadataType **Extends**: [MetadataType](#MetadataType) * [TriggeredSendDefinition](#TriggeredSendDefinition) ⇐ [MetadataType](#MetadataType) - * [.retrieve(retrieveDir, [_], [__], [___], [key])](#TriggeredSendDefinition.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieve(retrieveDir, [_], [__], [key])](#TriggeredSendDefinition.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.create(metadata)](#TriggeredSendDefinition.create) ⇒ Promise * [.update(metadata, [handleOutside])](#TriggeredSendDefinition.update) ⇒ Promise * [.deleteByKey(customerKey)](#TriggeredSendDefinition.deleteByKey) ⇒ Promise.<boolean> @@ -4965,7 +4916,7 @@ MessageSendActivity MetadataType -### TriggeredSendDefinition.retrieve(retrieveDir, [_], [__], [___], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### TriggeredSendDefinition.retrieve(retrieveDir, [_], [__], [key]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata **Kind**: static method of [TriggeredSendDefinition](#TriggeredSendDefinition) @@ -4976,7 +4927,6 @@ Retrieves SOAP based metadata of metadata type into local filesystem. executes c | retrieveDir | string | Directory where retrieved metadata directory will be saved | | [_] | void | unused parameter | | [__] | void | unused parameter | -| [___] | void | unused parameter | | [key] | string | customer key of single item to retrieve | diff --git a/lib/Retriever.js b/lib/Retriever.js index a07b719fe..a5af51f94 100644 --- a/lib/Retriever.js +++ b/lib/Retriever.js @@ -131,7 +131,6 @@ class Retriever { MetadataTypeInfo[type].retrieve( this.savePath, null, - this.buObject, subTypeArr, key ) diff --git a/lib/metadataTypes/AccountUser.js b/lib/metadataTypes/AccountUser.js index d157971a5..9cc2b1f98 100644 --- a/lib/metadataTypes/AccountUser.js +++ b/lib/metadataTypes/AccountUser.js @@ -16,37 +16,34 @@ class AccountUser extends MetadataType { * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} _ unused parameter - * @param {TYPE.BuObject} buObject properties for auth - * @param {void} [___] unused parameter + * @param {void} [__] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static async retrieve(retrieveDir, _, buObject, ___, key) { - if (buObject.eid !== buObject.mid) { + static async retrieve(retrieveDir, _, __, key) { + if (this.buObject.eid !== this.buObject.mid) { Util.logger.info(' - Skipping User retrieval on non-parent BU'); return; } - return this._retrieve(retrieveDir, buObject, key); + return this._retrieve(retrieveDir, key); } /** * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata * - * @param {TYPE.BuObject} buObject properties for auth * @returns {Promise.} Promise of metadata */ - static async retrieveChangelog(buObject) { - return this._retrieve(null, buObject, null); + static async retrieveChangelog() { + return this._retrieve(null, null); } /** * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata * * @private * @param {string} retrieveDir Directory where retrieved metadata directory will be saved - * @param {TYPE.BuObject} buObject properties for auth * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static async _retrieve(retrieveDir, buObject, key) { + static async _retrieve(retrieveDir, key) { Util.logger.info(' - Caching dependent Metadata: AccountUserAccount'); // get BUs that each users have access to @@ -113,7 +110,7 @@ class AccountUser extends MetadataType { }; } Util.logger.info(` - Loading ${this.definition.type}. This might take a while...`); - return super.retrieveSOAP(retrieveDir, buObject, requestParams); + return super.retrieveSOAP(retrieveDir, this.buObject, requestParams); } /** * diff --git a/lib/metadataTypes/Asset.js b/lib/metadataTypes/Asset.js index 355c8c92c..6acb771c1 100644 --- a/lib/metadataTypes/Asset.js +++ b/lib/metadataTypes/Asset.js @@ -19,12 +19,11 @@ class Asset extends MetadataType { * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} _ - - * @param {void} __ - * @param {TYPE.AssetSubType[]} [subTypeArr] optionally limit to a single subtype * @param {string} [key] customer key * @returns {Promise.<{metadata: TYPE.AssetMap, type: string}>} Promise */ - static async retrieve(retrieveDir, _, __, subTypeArr, key) { + static async retrieve(retrieveDir, _, subTypeArr, key) { const items = []; subTypeArr = subTypeArr || this._getSubTypes(); await File.initPrettier(); @@ -61,7 +60,7 @@ class Asset extends MetadataType { * @returns {Promise.<{metadata: TYPE.AssetMap, type: string}>} Promise */ static retrieveForCache(_, subTypeArr) { - return this.retrieve(null, null, null, subTypeArr); + return this.retrieve(null, null, subTypeArr); } /** diff --git a/lib/metadataTypes/AttributeGroup.js b/lib/metadataTypes/AttributeGroup.js index 36e7860a8..77b5e008b 100644 --- a/lib/metadataTypes/AttributeGroup.js +++ b/lib/metadataTypes/AttributeGroup.js @@ -15,11 +15,10 @@ class AttributeGroup extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static retrieve(retrieveDir, _, __, ___, key) { + static retrieve(retrieveDir, _, __, key) { return super.retrieveREST( retrieveDir, '/hub/v1/contacts/schema/attributeGroups', diff --git a/lib/metadataTypes/Automation.js b/lib/metadataTypes/Automation.js index 504ff6d30..a7fc88b3c 100644 --- a/lib/metadataTypes/Automation.js +++ b/lib/metadataTypes/Automation.js @@ -19,11 +19,10 @@ class Automation extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static async retrieve(retrieveDir, _, __, ___, key) { + static async retrieve(retrieveDir, _, __, key) { /** @type {TYPE.SoapRequestParams} */ let requestParams = null; if (key) { diff --git a/lib/metadataTypes/Campaign.js b/lib/metadataTypes/Campaign.js index 77283cd99..5a3035443 100644 --- a/lib/metadataTypes/Campaign.js +++ b/lib/metadataTypes/Campaign.js @@ -17,11 +17,10 @@ class Campaign extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise */ - static async retrieve(retrieveDir, _, __, ___, key) { + static async retrieve(retrieveDir, _, __, key) { const res = await super.retrieveREST(retrieveDir, '/hub/v1/campaigns', null, null, key); // get assignments diff --git a/lib/metadataTypes/ContentArea.js b/lib/metadataTypes/ContentArea.js index 3b634cfe3..3a7736dfb 100644 --- a/lib/metadataTypes/ContentArea.js +++ b/lib/metadataTypes/ContentArea.js @@ -17,11 +17,10 @@ class ContentArea extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static retrieve(retrieveDir, _, __, ___, key) { + static retrieve(retrieveDir, _, __, key) { Util.logger.warn( ' - Classic Content Areas are deprecated and will be discontinued by SFMC in the near future. Ensure that you migrate any existing Content Areas to Content Builder as soon as possible.' ); diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index 6ecf42dfb..b15e31544 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -323,12 +323,11 @@ class DataExtension extends MetadataType { * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @param {TYPE.BuObject} buObject properties for auth * @param {void} [_] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.<{metadata: TYPE.DataExtensionMap, type: string}>} Promise of item map */ - static async retrieve(retrieveDir, additionalFields, buObject, _, key) { + static async retrieve(retrieveDir, additionalFields, _, key) { /** @type {TYPE.SoapRequestParams} */ let requestParams = null; /** @type {TYPE.SoapRequestParams} */ @@ -355,17 +354,17 @@ class DataExtension extends MetadataType { // get fields from API await this._attachFields(metadata, fieldOptions, additionalFields); } - if (!retrieveDir && buObject.eid !== buObject.mid) { + if (!retrieveDir && this.buObject.eid !== this.buObject.mid) { // for caching, we want to retrieve shared DEs as well from the instance parent BU Util.logger.info( ' - Caching dependent Metadata: dataExtension (shared via _ParentBU_)' ); /** @type {TYPE.BuObject} */ const buObjectParentBu = { - eid: this.properties.credentials[buObject.credential].eid, - mid: this.properties.credentials[buObject.credential].eid, + eid: this.properties.credentials[this.buObject.credential].eid, + mid: this.properties.credentials[this.buObject.credential].eid, businessUnit: Util.parentBuName, - credential: buObject.credential, + credential: this.buObject.credential, }; try { this.client = auth.getSDK(buObjectParentBu); @@ -385,7 +384,7 @@ class DataExtension extends MetadataType { Folder.buObject = buObjectParentBu; Folder.properties = this.properties; const result = await Folder.retrieveForCache(null, subTypeArr); - cache.mergeMetadata('folder', result.metadata, buObject.eid); + cache.mergeMetadata('folder', result.metadata, this.buObject.eid); // get the types and clean out non-shared ones const folderTypesFromParent = require('../MetadataTypeDefinitions').folder @@ -398,7 +397,7 @@ class DataExtension extends MetadataType { metadataParentBu[metadataEntry].CategoryID, 'ID', 'ContentType', - buObject.eid + this.buObject.eid ); if (!folderTypesFromParent.includes(folderContentType)) { Util.logger.verbose( diff --git a/lib/metadataTypes/DataExtensionField.js b/lib/metadataTypes/DataExtensionField.js index e203c27ff..d07b393b0 100644 --- a/lib/metadataTypes/DataExtensionField.js +++ b/lib/metadataTypes/DataExtensionField.js @@ -15,11 +15,10 @@ class DataExtensionField extends MetadataType { * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @param {TYPE.BuObject} buObject properties for auth * @returns {Promise.<{metadata: TYPE.DataExtensionFieldMap, type: string}>} Promise of items */ - static async retrieve(retrieveDir, additionalFields, buObject) { - return super.retrieveSOAP(retrieveDir, buObject, null, additionalFields); + static async retrieve(retrieveDir, additionalFields) { + return super.retrieveSOAP(retrieveDir, this.buObject, null, additionalFields); } /** * Retrieves all records for caching diff --git a/lib/metadataTypes/DataExtensionTemplate.js b/lib/metadataTypes/DataExtensionTemplate.js index cbdc6efdf..d896405b8 100644 --- a/lib/metadataTypes/DataExtensionTemplate.js +++ b/lib/metadataTypes/DataExtensionTemplate.js @@ -15,11 +15,10 @@ class DataExtensionTemplate extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static retrieve(retrieveDir, _, __, ___, key) { + static retrieve(retrieveDir, _, __, key) { /** @type {TYPE.SoapRequestParams} */ let requestParams = null; if (key) { diff --git a/lib/metadataTypes/DataExtract.js b/lib/metadataTypes/DataExtract.js index 858fe3937..46a94ec32 100644 --- a/lib/metadataTypes/DataExtract.js +++ b/lib/metadataTypes/DataExtract.js @@ -19,11 +19,10 @@ class DataExtract extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static async retrieve(retrieveDir, _, __, ___, key) { + static async retrieve(retrieveDir, _, __, key) { return super.retrieveREST(retrieveDir, '/automation/v1/dataextracts/', null, null, key); } /** diff --git a/lib/metadataTypes/DataExtractType.js b/lib/metadataTypes/DataExtractType.js index b379a8588..e627e6c5d 100644 --- a/lib/metadataTypes/DataExtractType.js +++ b/lib/metadataTypes/DataExtractType.js @@ -17,11 +17,10 @@ class DataExtractType extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static retrieve(retrieveDir, _, __, ___, key) { + static retrieve(retrieveDir, _, __, key) { return super.retrieveREST(retrieveDir, '/automation/v1/dataextracttypes/', null, null, key); } /** diff --git a/lib/metadataTypes/Discovery.js b/lib/metadataTypes/Discovery.js index d737ecdd0..8f6191e71 100644 --- a/lib/metadataTypes/Discovery.js +++ b/lib/metadataTypes/Discovery.js @@ -16,16 +16,15 @@ class Discovery extends MetadataType { * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] not used - * @param {TYPE.BuObject} buObject properties for auth - * @param {void} [___] unused parameter + * @param {void} [__] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise */ - static async retrieve(retrieveDir, _, buObject, ___, key) { + static async retrieve(retrieveDir, _, __, key) { if (key) { Util.logger.error('Discovery.retrieve() does not support key parameter'); } - if (buObject.eid === buObject.mid) { + if (this.buObject.eid === this.buObject.mid) { const res = await this.client.rest.getCollection( Object.keys(this.definition.endPointMapping).map( (endpoint) => this.definition.endPointMapping[endpoint] diff --git a/lib/metadataTypes/Email.js b/lib/metadataTypes/Email.js index feccbeaf6..5343edd21 100644 --- a/lib/metadataTypes/Email.js +++ b/lib/metadataTypes/Email.js @@ -16,11 +16,10 @@ class Email extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static retrieve(retrieveDir, _, __, ___, key) { + static retrieve(retrieveDir, _, __, key) { Util.logger.warn( ' - Classic E-Mails are deprecated and will be discontinued by SFMC in the near future. Ensure that you migrate any existing E-Mails to Content Builder as soon as possible.' ); diff --git a/lib/metadataTypes/EmailSendDefinition.js b/lib/metadataTypes/EmailSendDefinition.js index c6d3c954c..6e7f1fb8a 100644 --- a/lib/metadataTypes/EmailSendDefinition.js +++ b/lib/metadataTypes/EmailSendDefinition.js @@ -17,11 +17,10 @@ class EmailSendDefinition extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static retrieve(retrieveDir, _, __, ___, key) { + static retrieve(retrieveDir, _, __, key) { /** @type {TYPE.SoapRequestParams} */ let requestParams = { filter: { diff --git a/lib/metadataTypes/EventDefinition.js b/lib/metadataTypes/EventDefinition.js index 9a6899cb7..52d04a1b4 100644 --- a/lib/metadataTypes/EventDefinition.js +++ b/lib/metadataTypes/EventDefinition.js @@ -20,11 +20,10 @@ class EventDefinition extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static retrieve(retrieveDir, _, __, ___, key) { + static retrieve(retrieveDir, _, __, key) { Util.logBeta(this.definition.type); return super.retrieveREST( retrieveDir, diff --git a/lib/metadataTypes/FileTransfer.js b/lib/metadataTypes/FileTransfer.js index 68c6350af..16eb2bbb3 100644 --- a/lib/metadataTypes/FileTransfer.js +++ b/lib/metadataTypes/FileTransfer.js @@ -19,11 +19,10 @@ class FileTransfer extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise */ - static async retrieve(retrieveDir, _, __, ___, key) { + static async retrieve(retrieveDir, _, __, key) { return super.retrieveREST(retrieveDir, '/automation/v1/filetransfers/', null, null, key); } /** diff --git a/lib/metadataTypes/Filter.js b/lib/metadataTypes/Filter.js index 8cd01c55b..1aaf6efd7 100644 --- a/lib/metadataTypes/Filter.js +++ b/lib/metadataTypes/Filter.js @@ -18,11 +18,10 @@ class Filter extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise */ - static async retrieve(retrieveDir, _, __, ___, key) { + static async retrieve(retrieveDir, _, __, key) { return super.retrieveREST(retrieveDir, '/automation/v1/filters/', null, null, key); } } diff --git a/lib/metadataTypes/Folder.js b/lib/metadataTypes/Folder.js index 7b3386e5e..984cdda5b 100644 --- a/lib/metadataTypes/Folder.js +++ b/lib/metadataTypes/Folder.js @@ -18,18 +18,17 @@ class Folder extends MetadataType { * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @param {TYPE.BuObject} buObject properties for auth * @param {string[]} [subTypeArr] content type of folder * @param {string} [key] customer key of single item to retrieve * @returns {Promise} Promise */ - static async retrieve(retrieveDir, additionalFields, buObject, subTypeArr, key) { + static async retrieve(retrieveDir, additionalFields, subTypeArr, key) { if (key) { Util.logger.error(`Folder.retrieve() does not support key parameter`); } const queryAllFolders = await this.retrieveHelper(additionalFields, true, subTypeArr); - if (buObject.eid !== buObject.mid) { + if (this.buObject.eid !== this.buObject.mid) { queryAllFolders.push( ...(await this.retrieveHelper(additionalFields, false, subTypeArr)) ); @@ -44,7 +43,7 @@ class Folder extends MetadataType { } // by default folders do not have an external key, we set this to ID plus EID as this will be unique else if (!val.CustomerKey) { - val.CustomerKey = [buObject.eid, val.ID].join('-'); + val.CustomerKey = [this.buObject.eid, val.ID].join('-'); } // ensure name is a string and not a number (SFMC-SDK workaround) val.Name = val.Name + ''; @@ -107,7 +106,7 @@ class Folder extends MetadataType { // remove keys which are listed in other BUs and skip root if ( idMap[id].Client?.ID && - (buObject.mid == idMap[id].Client.ID || + (this.buObject.mid == idMap[id].Client.ID || this.definition.folderTypesFromParent.includes( idMap[id].ContentType.toLowerCase() )) @@ -140,7 +139,7 @@ class Folder extends MetadataType { } } if (retrieveDir) { - const savedMetadata = await this.saveResults(metadata, retrieveDir, buObject.mid); + const savedMetadata = await this.saveResults(metadata, retrieveDir, this.buObject.mid); Util.logger.info( `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` ); @@ -156,7 +155,7 @@ class Folder extends MetadataType { * @returns {Promise} Promise */ static retrieveForCache(_, subTypeArr) { - return this.retrieve(null, null, this.buObject, subTypeArr, null); + return this.retrieve(null, null, subTypeArr, null); } /** diff --git a/lib/metadataTypes/FtpLocation.js b/lib/metadataTypes/FtpLocation.js index cce98c565..b85e513ce 100644 --- a/lib/metadataTypes/FtpLocation.js +++ b/lib/metadataTypes/FtpLocation.js @@ -16,11 +16,10 @@ class FtpLocation extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise */ - static retrieve(retrieveDir, _, __, ___, key) { + static retrieve(retrieveDir, _, __, key) { return super.retrieveREST(retrieveDir, '/automation/v1/ftplocations/', null, null, key); } diff --git a/lib/metadataTypes/ImportFile.js b/lib/metadataTypes/ImportFile.js index b9c5b0016..3aca611bb 100644 --- a/lib/metadataTypes/ImportFile.js +++ b/lib/metadataTypes/ImportFile.js @@ -20,11 +20,10 @@ class ImportFile extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise */ - static retrieve(retrieveDir, _, __, ___, key) { + static retrieve(retrieveDir, _, __, key) { return super.retrieveREST(retrieveDir, '/automation/v1/imports/', null, null, key); } diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index e0388e4ed..2e6a09c5d 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -23,11 +23,10 @@ class Interaction extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise */ - static async retrieve(retrieveDir, _, __, ___, key) { + static async retrieve(retrieveDir, _, __, key) { if (retrieveDir) { // only print this during retrieve, not during retrieveForCache Util.logBeta(this.definition.type); diff --git a/lib/metadataTypes/List.js b/lib/metadataTypes/List.js index aad9a2a29..a58d1d2e5 100644 --- a/lib/metadataTypes/List.js +++ b/lib/metadataTypes/List.js @@ -18,12 +18,11 @@ class List extends MetadataType { * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter - * @param {TYPE.BuObject} buObject properties for auth - * @param {void} [___] unused parameter + * @param {void} [__] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise */ - static async retrieve(retrieveDir, _, buObject, ___, key) { + static async retrieve(retrieveDir, _, __, key) { /** @type {TYPE.SoapRequestParams} */ let requestParams = null; if (key) { @@ -45,7 +44,7 @@ class List extends MetadataType { }; } const results = await super.retrieveSOAP(retrieveDir, null, requestParams); - return await this._retrieveParentAllSubs(buObject, results); + return await this._retrieveParentAllSubs(results); } /** * Gets metadata cache with limited fields and does not store value to disk @@ -53,7 +52,7 @@ class List extends MetadataType { * @returns {Promise.} Promise of metadata */ static async retrieveForCache() { - const results = await this.retrieve(null, null, this.buObject); + const results = await this.retrieve(); if (!cache.getCache()?.folder) { const subTypeArr = [ 'list', @@ -80,28 +79,30 @@ class List extends MetadataType { /** * helper for @link retrieveForCache and @link retrieve * - * @param {TYPE.BuObject} buObject properties for auth + * @private * @param {TYPE.MetadataTypeMapObj} results metadata from retrieve for current BU * @returns {Promise.} Promise */ - static async _retrieveParentAllSubs(buObject, results) { - if (buObject.eid !== buObject.mid) { + static async _retrieveParentAllSubs(results) { + if (this.buObject.eid !== this.buObject.mid) { // for caching, we want to get the All Subscriber List from the Parent Account Util.logger.debug(' - Checking MasterUnsubscribeBehavior for current BU'); /** @type {TYPE.BuObject} */ const buObjectParentBu = { - eid: this.properties.credentials[buObject.credential].eid, - mid: this.properties.credentials[buObject.credential].eid, + eid: this.properties.credentials[this.buObject.credential].eid, + mid: this.properties.credentials[this.buObject.credential].eid, businessUnit: Util.parentBuName, - credential: buObject.credential, + credential: this.buObject.credential, }; const clientBackup = this.client; + const buObjectBackup = this.buObject; try { this.client = auth.getSDK(buObjectParentBu); } catch (ex) { Util.logger.error(ex.message); return; } + this.buObject = buObjectParentBu; const buResult = await this.client.soap.retrieve( 'BusinessUnit', ['MasterUnsubscribeBehavior'], @@ -110,7 +111,7 @@ class List extends MetadataType { filter: { leftOperand: 'ID', operator: 'equals', - rightOperand: this.properties.credentials[buObject.credential].eid, + rightOperand: this.properties.credentials[this.buObject.credential].eid, }, } ); @@ -120,13 +121,8 @@ class List extends MetadataType { Util.logger.info( ' - Caching dependent Metadata: All Subscriber list (on _ParentBU_)' ); - const metadataParentBu = await this.retrieve( - null, - null, - buObjectParentBu, - null, - 'All Subscribers' - ); + // do not use retrieveForCache here because (a) it does not support key-filtering and (b) it would cache folders on top which we do not need for the global all subscriber list + const metadataParentBu = await this.retrieve(null, null, null, 'All Subscribers'); // manually set folder path of parent's All Subscriber List to avoid retrieving folders for (const key of Object.keys(metadataParentBu.metadata)) { metadataParentBu.metadata[key].r__folder_Path = 'my subscribers'; @@ -139,8 +135,9 @@ class List extends MetadataType { } } - // revert client to current default + // revert to current default this.client = clientBackup; + this.buObject = buObjectBackup; // make sure to overwrite parent bu DEs with local ones return { diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 89828df45..07e3e7ed6 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -198,12 +198,11 @@ class MetadataType { * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @param {TYPE.BuObject} buObject properties for auth * @param {string[]} [subTypeArr] optionally limit to a single subtype * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} metadata */ - static retrieve(retrieveDir, additionalFields, buObject, subTypeArr, key) { + static retrieve(retrieveDir, additionalFields, subTypeArr, key) { Util.metadataLogger('error', this.definition.type, 'retrieve', `Not Supported`); const metadata = {}; return { metadata: null, type: this.definition.type }; @@ -228,7 +227,7 @@ class MetadataType { * @returns {Promise.} metadata */ static async retrieveForCache(additionalFields, subTypeArr) { - return this.retrieve(null, additionalFields, this.buObject, subTypeArr); + return this.retrieve(null, additionalFields, subTypeArr); } /** * Gets metadata cache with limited fields and does not store value to disk diff --git a/lib/metadataTypes/MobileCode.js b/lib/metadataTypes/MobileCode.js index 00c7ce53e..5f4783f5a 100644 --- a/lib/metadataTypes/MobileCode.js +++ b/lib/metadataTypes/MobileCode.js @@ -16,11 +16,10 @@ class MobileCode extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static retrieve(retrieveDir, _, __, ___, key) { + static retrieve(retrieveDir, _, __, key) { return super.retrieveREST( retrieveDir, '/legacy/v1/beta/mobile/code/' + (key ? `?$where=keyword%20eq%20%27${key}%27%20` : ''), diff --git a/lib/metadataTypes/MobileKeyword.js b/lib/metadataTypes/MobileKeyword.js index 40a5fdea6..9580aed30 100644 --- a/lib/metadataTypes/MobileKeyword.js +++ b/lib/metadataTypes/MobileKeyword.js @@ -19,11 +19,10 @@ class MobileKeyword extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static retrieve(retrieveDir, _, __, ___, key) { + static retrieve(retrieveDir, _, __, key) { return super.retrieveREST( retrieveDir, '/legacy/v1/beta/mobile/keyword/?view=simple' + diff --git a/lib/metadataTypes/Query.js b/lib/metadataTypes/Query.js index 7f5a4e0c0..c94e1db26 100644 --- a/lib/metadataTypes/Query.js +++ b/lib/metadataTypes/Query.js @@ -27,11 +27,10 @@ class Query extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.<{metadata: TYPE.QueryMap, type: string}>} Promise of metadata */ - static async retrieve(retrieveDir, _, __, ___, key) { + static async retrieve(retrieveDir, _, __, key) { await File.initPrettier('sql'); const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : null; return super.retrieveREST( diff --git a/lib/metadataTypes/Role.js b/lib/metadataTypes/Role.js index 676648963..2990ee403 100644 --- a/lib/metadataTypes/Role.js +++ b/lib/metadataTypes/Role.js @@ -16,13 +16,12 @@ class Role extends MetadataType { * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {string[]} _ Returns specified fields even if their retrieve definition is not set to true - * @param {TYPE.BuObject} buObject properties for auth * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Metadata store object */ - static async retrieve(retrieveDir, _, buObject, ___, key) { - if (retrieveDir && buObject.eid !== buObject.mid) { + static async retrieve(retrieveDir, _, ___, key) { + if (retrieveDir && this.buObject.eid !== this.buObject.mid) { // don't run for BUs other than Parent BU // this check does not work during caching Util.logger.info(' - Skipping Role retrieval on non-parent BU'); diff --git a/lib/metadataTypes/Script.js b/lib/metadataTypes/Script.js index c509de7a6..be313a425 100644 --- a/lib/metadataTypes/Script.js +++ b/lib/metadataTypes/Script.js @@ -18,11 +18,10 @@ class Script extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.<{metadata: TYPE.ScriptMap, type: string}>} Promise */ - static async retrieve(retrieveDir, _, __, ___, key) { + static async retrieve(retrieveDir, _, __, key) { await File.initPrettier('ssjs'); return super.retrieveREST(retrieveDir, '/automation/v1/scripts/', null, null, key); } diff --git a/lib/metadataTypes/SetDefinition.js b/lib/metadataTypes/SetDefinition.js index 687fb21e3..bcbf64ff0 100644 --- a/lib/metadataTypes/SetDefinition.js +++ b/lib/metadataTypes/SetDefinition.js @@ -15,11 +15,10 @@ class SetDefinition extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise */ - static retrieve(retrieveDir, _, __, ___, key) { + static retrieve(retrieveDir, _, __, key) { return super.retrieveREST( retrieveDir, '/hub/v1/contacts/schema/setDefinitions', diff --git a/lib/metadataTypes/TransactionalMessage.js b/lib/metadataTypes/TransactionalMessage.js index f2f1440aa..283c1fe0f 100644 --- a/lib/metadataTypes/TransactionalMessage.js +++ b/lib/metadataTypes/TransactionalMessage.js @@ -19,11 +19,10 @@ class TransactionalMessage extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static async retrieve(retrieveDir, _, __, ___, key) { + static async retrieve(retrieveDir, _, __, key) { let keyList; const baseUri = '/messaging/v1/' + this.subType + '/definitions/'; if (key) { diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index 2fbf283df..3a7aec6da 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -23,11 +23,10 @@ class TriggeredSendDefinition extends MetadataType { * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {void} [_] unused parameter * @param {void} [__] unused parameter - * @param {void} [___] unused parameter * @param {string} [key] customer key of single item to retrieve * @returns {Promise.} Promise of metadata */ - static retrieve(retrieveDir, _, __, ___, key) { + static retrieve(retrieveDir, _, __, key) { /** @type {TYPE.SoapRequestParams} */ let requestParams = { filter: { From 9cacacbccee6ec27d0aaacc44bca9408217487a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 13:53:18 +0100 Subject: [PATCH 118/132] #593: remove buObject param from retrieveChangelog() --- docs/dist/documentation.md | 5 ++--- lib/Retriever.js | 2 +- lib/metadataTypes/AccountUser.js | 2 +- lib/metadataTypes/DataExtension.js | 2 +- lib/metadataTypes/MetadataType.js | 3 +-- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index a1be8835b..385ead457 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -3161,7 +3161,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.setFolderPath(metadata)](#MetadataType.setFolderPath) * [.setFolderId(metadata)](#MetadataType.setFolderId) * [.retrieve(retrieveDir, [additionalFields], [subTypeArr], [key])](#MetadataType.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> - * [.retrieveChangelog([_], [additionalFields], [subTypeArr])](#MetadataType.retrieveChangelog) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieveChangelog([additionalFields], [subTypeArr])](#MetadataType.retrieveChangelog) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveForCache([additionalFields], [subTypeArr])](#MetadataType.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveAsTemplate(templateDir, name, templateVariables, [subType])](#MetadataType.retrieveAsTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.buildTemplate(retrieveDir, templateDir, key, templateVariables)](#MetadataType.buildTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> @@ -3327,7 +3327,7 @@ Gets metadata from Marketing Cloud -### MetadataType.retrieveChangelog([_], [additionalFields], [subTypeArr]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### MetadataType.retrieveChangelog([additionalFields], [subTypeArr]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Gets metadata from Marketing Cloud **Kind**: static method of [MetadataType](#MetadataType) @@ -3335,7 +3335,6 @@ Gets metadata from Marketing Cloud | Param | Type | Description | | --- | --- | --- | -| [_] | void | unused parameter (buObject) | | [additionalFields] | Array.<string> | Returns specified fields even if their retrieve definition is not set to true | | [subTypeArr] | Array.<string> | optionally limit to a single subtype | diff --git a/lib/Retriever.js b/lib/Retriever.js index a5af51f94..e8b5243e4 100644 --- a/lib/Retriever.js +++ b/lib/Retriever.js @@ -125,7 +125,7 @@ class Retriever { : Util.getKeysString(typeKeyMap[metadataType])) ); result = await (changelogOnly - ? MetadataTypeInfo[type].retrieveChangelog(this.buObject, null, subTypeArr) + ? MetadataTypeInfo[type].retrieveChangelog(null, subTypeArr) : Promise.all( typeKeyMap[metadataType].map((key) => MetadataTypeInfo[type].retrieve( diff --git a/lib/metadataTypes/AccountUser.js b/lib/metadataTypes/AccountUser.js index 9cc2b1f98..883496d38 100644 --- a/lib/metadataTypes/AccountUser.js +++ b/lib/metadataTypes/AccountUser.js @@ -33,7 +33,7 @@ class AccountUser extends MetadataType { * @returns {Promise.} Promise of metadata */ static async retrieveChangelog() { - return this._retrieve(null, null); + return this._retrieve(); } /** * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index b15e31544..1f633ce9e 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -474,7 +474,7 @@ class DataExtension extends MetadataType { * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true * @returns {Promise.<{metadata: TYPE.DataExtensionMap, type: string}>} Promise of item map */ - static async retrieveChangelog(buObject, additionalFields) { + static async retrieveChangelog(additionalFields) { const metadata = await this._retrieveAll(additionalFields); return { metadata: metadata, type: 'dataExtension' }; } diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 07e3e7ed6..2c5c7ed13 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -210,12 +210,11 @@ class MetadataType { /** * Gets metadata from Marketing Cloud * - * @param {void} [_] unused parameter (buObject) * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true * @param {string[]} [subTypeArr] optionally limit to a single subtype * @returns {Promise.} metadata */ - static retrieveChangelog(_, additionalFields, subTypeArr) { + static retrieveChangelog(additionalFields, subTypeArr) { return this.retrieveForCache(additionalFields, subTypeArr); } From 81250d96ed300889457ad65e4279be45231b9c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 13:59:37 +0100 Subject: [PATCH 119/132] #593: remove buObject param from deploy() --- docs/dist/documentation.md | 10 ++++------ lib/Deployer.js | 3 +-- lib/metadataTypes/EventDefinition.js | 5 ++--- lib/metadataTypes/Interaction.js | 4 ++-- lib/metadataTypes/MetadataType.js | 5 ++--- 5 files changed, 11 insertions(+), 16 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 385ead457..568b4aabc 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -2338,7 +2338,7 @@ EventDefinition MetadataType * [.retrieveAsTemplate(templateDir, name, templateVariables)](#EventDefinition.retrieveAsTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.postRetrieveTasks(eventDef)](#EventDefinition.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.deleteByKey(key)](#EventDefinition.deleteByKey) ⇒ Promise.<boolean> - * [.deploy(metadata, deployDir, retrieveDir, buObject)](#EventDefinition.deploy) ⇒ Promise.<TYPE.MetadataTypeMap> + * [.deploy(metadata, deployDir, retrieveDir)](#EventDefinition.deploy) ⇒ Promise.<TYPE.MetadataTypeMap> * [.create(EventDefinition)](#EventDefinition.create) ⇒ Promise * [.update(metadataEntry)](#EventDefinition.update) ⇒ Promise * [.preDeployTasks(metadata)](#EventDefinition.preDeployTasks) ⇒ TYPE.MetadataTypeItem @@ -2408,7 +2408,7 @@ Delete a metadata item from the specified business unit -### EventDefinition.deploy(metadata, deployDir, retrieveDir, buObject) ⇒ Promise.<TYPE.MetadataTypeMap> +### EventDefinition.deploy(metadata, deployDir, retrieveDir) ⇒ Promise.<TYPE.MetadataTypeMap> Deploys metadata - merely kept here to be able to print [logBeta](#Util.logBeta) once per deploy **Kind**: static method of [EventDefinition](#EventDefinition) @@ -2419,7 +2419,6 @@ Deploys metadata - merely kept here to be able to print [logBeta](#Util.logBeta) | metadata | TYPE.MetadataTypeMap | metadata mapped by their keyField | | deployDir | string | directory where deploy metadata are saved | | retrieveDir | string | directory where metadata after deploy should be saved | -| buObject | TYPE.BuObject | properties for auth | @@ -3155,7 +3154,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.buObject](#MetadataType.buObject) : TYPE.BuObject * [.getJsonFromFS(dir, [listBadKeys])](#MetadataType.getJsonFromFS) ⇒ TYPE.MetadataTypeMap * [.getFieldNamesToRetrieve([additionalFields])](#MetadataType.getFieldNamesToRetrieve) ⇒ Array.<string> - * [.deploy(metadata, deployDir, retrieveDir, buObject)](#MetadataType.deploy) ⇒ Promise.<TYPE.MetadataTypeMap> + * [.deploy(metadata, deployDir, retrieveDir)](#MetadataType.deploy) ⇒ Promise.<TYPE.MetadataTypeMap> * [.postDeployTasks(metadata, originalMetadata)](#MetadataType.postDeployTasks) ⇒ void * [.postRetrieveTasks(metadata, targetDir, [isTemplating])](#MetadataType.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.setFolderPath(metadata)](#MetadataType.setFolderPath) @@ -3249,7 +3248,7 @@ Returns fieldnames of Metadata Type. 'this.definition.fields' variable only set -### MetadataType.deploy(metadata, deployDir, retrieveDir, buObject) ⇒ Promise.<TYPE.MetadataTypeMap> +### MetadataType.deploy(metadata, deployDir, retrieveDir) ⇒ Promise.<TYPE.MetadataTypeMap> Deploys metadata **Kind**: static method of [MetadataType](#MetadataType) @@ -3260,7 +3259,6 @@ Deploys metadata | metadata | TYPE.MetadataTypeMap | metadata mapped by their keyField | | deployDir | string | directory where deploy metadata are saved | | retrieveDir | string | directory where metadata after deploy should be saved | -| buObject | TYPE.BuObject | properties for auth | diff --git a/lib/Deployer.js b/lib/Deployer.js index 5e8bb78d4..03b960556 100644 --- a/lib/Deployer.js +++ b/lib/Deployer.js @@ -275,8 +275,7 @@ class Deployer { const result = await MetadataTypeInfo[type].deploy( this.metadata[type], this.deployDir, - this.retrieveDir, - this.buObject + this.retrieveDir ); multiMetadataTypeMap[type] = result; cache.mergeMetadata(type, result); diff --git a/lib/metadataTypes/EventDefinition.js b/lib/metadataTypes/EventDefinition.js index 52d04a1b4..9fdd2855b 100644 --- a/lib/metadataTypes/EventDefinition.js +++ b/lib/metadataTypes/EventDefinition.js @@ -137,12 +137,11 @@ class EventDefinition extends MetadataType { * @param {TYPE.MetadataTypeMap} metadata metadata mapped by their keyField * @param {string} deployDir directory where deploy metadata are saved * @param {string} retrieveDir directory where metadata after deploy should be saved - * @param {TYPE.BuObject} buObject properties for auth * @returns {Promise.} Promise of keyField => metadata map */ - static async deploy(metadata, deployDir, retrieveDir, buObject) { + static async deploy(metadata, deployDir, retrieveDir) { Util.logBeta(this.definition.type); - return super.deploy(metadata, deployDir, retrieveDir, buObject); + return super.deploy(metadata, deployDir, retrieveDir); } /** diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 2e6a09c5d..cd7c2f43c 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -154,9 +154,9 @@ class Interaction extends MetadataType { * @param {TYPE.BuObject} buObject properties for auth * @returns {Promise.} Promise of keyField => metadata map */ - static async deploy(metadata, deployDir, retrieveDir, buObject) { + static async deploy(metadata, deployDir, retrieveDir) { Util.logBeta(this.definition.type); - return super.deploy(metadata, deployDir, retrieveDir, buObject); + return super.deploy(metadata, deployDir, retrieveDir); } /** diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 2c5c7ed13..ac68b9fa2 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -112,11 +112,10 @@ class MetadataType { * @param {TYPE.MetadataTypeMap} metadata metadata mapped by their keyField * @param {string} deployDir directory where deploy metadata are saved * @param {string} retrieveDir directory where metadata after deploy should be saved - * @param {TYPE.BuObject} buObject properties for auth * @returns {Promise.} Promise of keyField => metadata map */ - static async deploy(metadata, deployDir, retrieveDir, buObject) { - const upsertResults = await this.upsert(metadata, deployDir, buObject); + static async deploy(metadata, deployDir, retrieveDir) { + const upsertResults = await this.upsert(metadata, deployDir, this.buObject); await this.postDeployTasks(upsertResults, metadata); const savedMetadata = await this.saveResults(upsertResults, retrieveDir, null); if ( From bc322621822e29b3a099f23a25aa360378b59377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 14:02:26 +0100 Subject: [PATCH 120/132] #593: remove buObject param from upsert() --- docs/dist/documentation.md | 21 ++++++++------------- lib/metadataTypes/DataExtension.js | 7 ++----- lib/metadataTypes/Interaction.js | 1 - lib/metadataTypes/MetadataType.js | 7 +++---- 4 files changed, 13 insertions(+), 23 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 568b4aabc..065e2c8c5 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -1626,13 +1626,13 @@ DataExtension MetadataType **Extends**: [MetadataType](#MetadataType) * [DataExtension](#DataExtension) ⇐ [MetadataType](#MetadataType) - * [.upsert(desToDeploy, _, buObject)](#DataExtension.upsert) ⇒ Promise + * [.upsert(desToDeploy)](#DataExtension.upsert) ⇒ Promise * [._filterUpsertResults(res)](#DataExtension._filterUpsertResults) ⇒ boolean * [.create(metadata)](#DataExtension.create) ⇒ Promise * [.update(metadata)](#DataExtension.update) ⇒ Promise * [.postDeployTasks(upsertedMetadata, originalMetadata)](#DataExtension.postDeployTasks) ⇒ void * [.retrieve(retrieveDir, [additionalFields], [_], [key])](#DataExtension.retrieve) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> - * [.retrieveChangelog([buObject], [additionalFields])](#DataExtension.retrieveChangelog) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> + * [.retrieveChangelog([additionalFields])](#DataExtension.retrieveChangelog) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> * [.postRetrieveTasks(metadata)](#DataExtension.postRetrieveTasks) ⇒ TYPE.DataExtensionItem * [.preDeployTasks(metadata)](#DataExtension.preDeployTasks) ⇒ Promise.<TYPE.DataExtensionItem> * [.document([metadata])](#DataExtension.document) ⇒ Promise.<void> @@ -1645,7 +1645,7 @@ DataExtension MetadataType -### DataExtension.upsert(desToDeploy, _, buObject) ⇒ Promise +### DataExtension.upsert(desToDeploy) ⇒ Promise Upserts dataExtensions after retrieving them from source and target to compare if create or update operation is needed. @@ -1655,8 +1655,6 @@ if create or update operation is needed. | Param | Type | Description | | --- | --- | --- | | desToDeploy | TYPE.DataExtensionMap | dataExtensions mapped by their customerKey | -| _ | void | unused parameter | -| buObject | TYPE.BuObject | properties for auth | @@ -1723,7 +1721,7 @@ Retrieves dataExtension metadata. Afterwards starts retrieval of dataExtensionCo -### DataExtension.retrieveChangelog([buObject], [additionalFields]) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> +### DataExtension.retrieveChangelog([additionalFields]) ⇒ Promise.<{metadata: TYPE.DataExtensionMap, type: string}> Retrieves dataExtension metadata. Afterwards starts retrieval of dataExtensionColumn metadata retrieval **Kind**: static method of [DataExtension](#DataExtension) @@ -1731,7 +1729,6 @@ Retrieves dataExtension metadata. Afterwards starts retrieval of dataExtensionCo | Param | Type | Description | | --- | --- | --- | -| [buObject] | TYPE.BuObject | properties for auth | | [additionalFields] | Array.<string> | Returns specified fields even if their retrieve definition is not set to true | @@ -2925,7 +2922,7 @@ definitionId: A unique UUID provided by Salesforce Marketing Cloud. Each version * [Interaction](#Interaction) ⇐ [MetadataType](#MetadataType) * [.retrieve(retrieveDir, [_], [__], [key])](#Interaction.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.deleteByKey(key)](#Interaction.deleteByKey) ⇒ Promise.<boolean> - * [.deploy(metadata, deployDir, retrieveDir, buObject)](#Interaction.deploy) ⇒ Promise.<TYPE.MetadataTypeMap> + * [.deploy(metadata, deployDir, retrieveDir)](#Interaction.deploy) ⇒ Promise.<TYPE.MetadataTypeMap> * [.update(metadata)](#Interaction.update) ⇒ Promise * [.create(metadata)](#Interaction.create) ⇒ Promise * [.saveResults(results, retrieveDir, [overrideType], [templateVariables])](#Interaction.saveResults) ⇒ Promise.<TYPE.MetadataTypeMap> @@ -2963,7 +2960,7 @@ Delete a metadata item from the specified business unit -### Interaction.deploy(metadata, deployDir, retrieveDir, buObject) ⇒ Promise.<TYPE.MetadataTypeMap> +### Interaction.deploy(metadata, deployDir, retrieveDir) ⇒ Promise.<TYPE.MetadataTypeMap> Deploys metadata - merely kept here to be able to print [logBeta](#Util.logBeta) once per deploy **Kind**: static method of [Interaction](#Interaction) @@ -2974,7 +2971,6 @@ Deploys metadata - merely kept here to be able to print [logBeta](#Util.logBeta) | metadata | TYPE.MetadataTypeMap | metadata mapped by their keyField | | deployDir | string | directory where deploy metadata are saved | | retrieveDir | string | directory where metadata after deploy should be saved | -| buObject | TYPE.BuObject | properties for auth | @@ -3170,7 +3166,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.refresh()](#MetadataType.refresh) ⇒ void * [.hasChanged(cachedVersion, metadata, [fieldName])](#MetadataType.hasChanged) ⇒ boolean * [.hasChangedGeneric(cachedVersion, metadata, [fieldName], [silent])](#MetadataType.hasChangedGeneric) ⇒ boolean - * [.upsert(metadata, deployDir, [buObject])](#MetadataType.upsert) ⇒ Promise.<TYPE.MetadataTypeMap> + * [.upsert(metadata, deployDir)](#MetadataType.upsert) ⇒ Promise.<TYPE.MetadataTypeMap> * [.createOrUpdate(metadata, metadataKey, hasError, metadataToUpdate, metadataToCreate)](#MetadataType.createOrUpdate) ⇒ void * [.createREST(metadataEntry, uri)](#MetadataType.createREST) ⇒ Promise.<object> \| null * [.createSOAP(metadataEntry, [overrideType], [handleOutside])](#MetadataType.createSOAP) ⇒ Promise.<object> \| null @@ -3454,7 +3450,7 @@ test if metadata was actually changed or not to potentially skip it during deplo -### MetadataType.upsert(metadata, deployDir, [buObject]) ⇒ Promise.<TYPE.MetadataTypeMap> +### MetadataType.upsert(metadata, deployDir) ⇒ Promise.<TYPE.MetadataTypeMap> MetadataType upsert, after retrieving from target and comparing to check if create or update operation is needed. **Kind**: static method of [MetadataType](#MetadataType) @@ -3464,7 +3460,6 @@ MetadataType upsert, after retrieving from target and comparing to check if crea | --- | --- | --- | | metadata | TYPE.MetadataTypeMap | metadata mapped by their keyField | | deployDir | string | directory where deploy metadata are saved | -| [buObject] | TYPE.BuObject | properties for auth | diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index 1f633ce9e..97bc14f6e 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -21,11 +21,9 @@ class DataExtension extends MetadataType { * if create or update operation is needed. * * @param {TYPE.DataExtensionMap} desToDeploy dataExtensions mapped by their customerKey - * @param {void} _ unused parameter - * @param {TYPE.BuObject} buObject properties for auth * @returns {Promise} Promise */ - static async upsert(desToDeploy, _, buObject) { + static async upsert(desToDeploy) { // get dataExtensions from target BU for add/update decision /** @type {TYPE.DataExtensionMap} */ const targetMetadata = cache.getCache().dataExtension || {}; @@ -65,7 +63,7 @@ class DataExtension extends MetadataType { continue; } if ( - buObject.eid !== buObject.mid && + this.buObject.eid !== this.buObject.mid && desToDeploy[dataExtension].r__folder_Path.startsWith('Shared Items') ) { // this needs to be run before executing preDeployTasks() @@ -470,7 +468,6 @@ class DataExtension extends MetadataType { /** * Retrieves dataExtension metadata. Afterwards starts retrieval of dataExtensionColumn metadata retrieval * - * @param {TYPE.BuObject} [buObject] properties for auth * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true * @returns {Promise.<{metadata: TYPE.DataExtensionMap, type: string}>} Promise of item map */ diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index cd7c2f43c..18a5d72c6 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -151,7 +151,6 @@ class Interaction extends MetadataType { * @param {TYPE.MetadataTypeMap} metadata metadata mapped by their keyField * @param {string} deployDir directory where deploy metadata are saved * @param {string} retrieveDir directory where metadata after deploy should be saved - * @param {TYPE.BuObject} buObject properties for auth * @returns {Promise.} Promise of keyField => metadata map */ static async deploy(metadata, deployDir, retrieveDir) { diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index ac68b9fa2..09ec44bce 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -115,7 +115,7 @@ class MetadataType { * @returns {Promise.} Promise of keyField => metadata map */ static async deploy(metadata, deployDir, retrieveDir) { - const upsertResults = await this.upsert(metadata, deployDir, this.buObject); + const upsertResults = await this.upsert(metadata, deployDir); await this.postDeployTasks(upsertResults, metadata); const savedMetadata = await this.saveResults(upsertResults, retrieveDir, null); if ( @@ -447,10 +447,9 @@ class MetadataType { * * @param {TYPE.MetadataTypeMap} metadata metadata mapped by their keyField * @param {string} deployDir directory where deploy metadata are saved - * @param {TYPE.BuObject} [buObject] properties for auth * @returns {Promise.} keyField => metadata map */ - static async upsert(metadata, deployDir, buObject) { + static async upsert(metadata, deployDir) { const metadataToUpdate = []; const metadataToCreate = []; let filteredByPreDeploy = 0; @@ -463,7 +462,7 @@ class MetadataType { deployableMetadata = await this.preDeployTasks( metadata[metadataKey], deployDir, - buObject + this.buObject ); } catch (ex) { // do this in case something went wrong during pre-deploy steps to ensure the total counter is correct From b781d591a53c2f712eea93ad09d39cd427e7de25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 14:04:54 +0100 Subject: [PATCH 121/132] #593: remove buObject param from preDeployTasks() --- docs/dist/documentation.md | 10 ++++------ lib/metadataTypes/Asset.js | 11 +++++------ lib/metadataTypes/MetadataType.js | 6 ++---- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 065e2c8c5..bddfd20d3 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -854,7 +854,7 @@ FileTransfer MetadataType * [._retrieveExtendedFile(metadata, subType, retrieveDir)](#Asset._retrieveExtendedFile) ⇒ Promise.<void> * [._readExtendedFileFromFS(metadata, subType, deployDir, [pathOnly])](#Asset._readExtendedFileFromFS) ⇒ Promise.<string> * [.postRetrieveTasks(metadata)](#Asset.postRetrieveTasks) ⇒ TYPE.CodeExtractItem - * [.preDeployTasks(metadata, deployDir, buObject)](#Asset.preDeployTasks) ⇒ Promise.<TYPE.AssetItem> + * [.preDeployTasks(metadata, deployDir)](#Asset.preDeployTasks) ⇒ Promise.<TYPE.AssetItem> * [._getMainSubtype(extendedSubType)](#Asset._getMainSubtype) ⇒ string * [.buildDefinitionForNested(templateDir, targetDir, metadata, templateVariables, templateName)](#Asset.buildDefinitionForNested) ⇒ Promise.<void> * [.buildTemplateForNested(templateDir, targetDir, metadata, templateVariables, templateName)](#Asset.buildTemplateForNested) ⇒ Promise.<void> @@ -1015,7 +1015,7 @@ manages post retrieve steps -### Asset.preDeployTasks(metadata, deployDir, buObject) ⇒ Promise.<TYPE.AssetItem> +### Asset.preDeployTasks(metadata, deployDir) ⇒ Promise.<TYPE.AssetItem> prepares an asset definition for deployment **Kind**: static method of [Asset](#Asset) @@ -1025,7 +1025,6 @@ prepares an asset definition for deployment | --- | --- | --- | | metadata | TYPE.AssetItem | a single asset | | deployDir | string | directory of deploy files | -| buObject | TYPE.BuObject | buObject properties for auth | @@ -3160,7 +3159,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.retrieveForCache([additionalFields], [subTypeArr])](#MetadataType.retrieveForCache) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveAsTemplate(templateDir, name, templateVariables, [subType])](#MetadataType.retrieveAsTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> * [.buildTemplate(retrieveDir, templateDir, key, templateVariables)](#MetadataType.buildTemplate) ⇒ Promise.<TYPE.MetadataTypeItemObj> - * [.preDeployTasks(metadata, deployDir, buObject)](#MetadataType.preDeployTasks) ⇒ Promise.<TYPE.MetadataTypeItem> + * [.preDeployTasks(metadata, deployDir)](#MetadataType.preDeployTasks) ⇒ Promise.<TYPE.MetadataTypeItem> * [.create(metadata, deployDir)](#MetadataType.create) ⇒ void * [.update(metadata, [metadataBefore])](#MetadataType.update) ⇒ void * [.refresh()](#MetadataType.refresh) ⇒ void @@ -3377,7 +3376,7 @@ Gets metadata cache with limited fields and does not store value to disk -### MetadataType.preDeployTasks(metadata, deployDir, buObject) ⇒ Promise.<TYPE.MetadataTypeItem> +### MetadataType.preDeployTasks(metadata, deployDir) ⇒ Promise.<TYPE.MetadataTypeItem> Gets executed before deploying metadata **Kind**: static method of [MetadataType](#MetadataType) @@ -3387,7 +3386,6 @@ Gets executed before deploying metadata | --- | --- | --- | | metadata | TYPE.MetadataTypeItem | a single metadata item | | deployDir | string | folder where files for deployment are stored | -| buObject | TYPE.BuObject | buObject properties for auth | diff --git a/lib/metadataTypes/Asset.js b/lib/metadataTypes/Asset.js index 6acb771c1..6734173d9 100644 --- a/lib/metadataTypes/Asset.js +++ b/lib/metadataTypes/Asset.js @@ -507,10 +507,9 @@ class Asset extends MetadataType { * * @param {TYPE.AssetItem} metadata a single asset * @param {string} deployDir directory of deploy files - * @param {TYPE.BuObject} buObject buObject properties for auth * @returns {Promise.} Promise */ - static async preDeployTasks(metadata, deployDir, buObject) { + static async preDeployTasks(metadata, deployDir) { // additonalattributes fail where the value is "" so we need to remove them from deploy if (metadata?.data?.email?.attributes?.length > 0) { metadata.data.email.attributes = metadata.data.email.attributes.filter( @@ -535,13 +534,13 @@ class Asset extends MetadataType { // only execute #3 if we are deploying / copying from one BU to another, not while using mcdev as a developer tool if ( - buObject.mid && - metadata.memberId !== buObject.mid && - !metadata[this.definition.keyField].endsWith(buObject.mid) + this.buObject.mid && + metadata.memberId !== this.buObject.mid && + !metadata[this.definition.keyField].endsWith(this.buObject.mid) ) { // #3 make sure customer key is unique by suffixing it with target MID (unless we are deploying to the same MID) // check if this suffixed with the source MID - const suffix = '-' + buObject.mid; + const suffix = '-' + this.buObject.mid; // for customer key max is 36 chars metadata[this.definition.keyField] = metadata[this.definition.keyField].slice(0, Math.max(0, 36 - suffix.length)) + diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 09ec44bce..02183eed0 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -326,10 +326,9 @@ class MetadataType { * * @param {TYPE.MetadataTypeItem} metadata a single metadata item * @param {string} deployDir folder where files for deployment are stored - * @param {TYPE.BuObject} buObject buObject properties for auth * @returns {Promise.} Promise of a single metadata item */ - static async preDeployTasks(metadata, deployDir, buObject) { + static async preDeployTasks(metadata, deployDir) { return metadata; } @@ -461,8 +460,7 @@ class MetadataType { try { deployableMetadata = await this.preDeployTasks( metadata[metadataKey], - deployDir, - this.buObject + deployDir ); } catch (ex) { // do this in case something went wrong during pre-deploy steps to ensure the total counter is correct From 6b2e6f57baf4a69115140bdb1a9efeef4f9a4d1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 14:08:33 +0100 Subject: [PATCH 122/132] #593: remove buObject param from retrieveSOAP() --- docs/dist/documentation.md | 5 ++--- lib/metadataTypes/AccountUser.js | 2 +- lib/metadataTypes/ContentArea.js | 2 +- lib/metadataTypes/DataExtension.js | 2 +- lib/metadataTypes/DataExtensionField.js | 4 ++-- lib/metadataTypes/DataExtensionTemplate.js | 2 +- lib/metadataTypes/Email.js | 2 +- lib/metadataTypes/EmailSendDefinition.js | 2 +- lib/metadataTypes/List.js | 2 +- lib/metadataTypes/MetadataType.js | 5 ++--- lib/metadataTypes/TriggeredSendDefinition.js | 6 +++--- 11 files changed, 16 insertions(+), 18 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index bddfd20d3..1993e4d9e 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -3173,7 +3173,7 @@ Provides default functionality that can be overwritten by child metadata type cl * [.updateSOAP(metadataEntry, [overrideType], [handleOutside])](#MetadataType.updateSOAP) ⇒ Promise.<object> \| null * [._handleSOAPErrors(ex, msg, [metadataEntry], [handleOutside])](#MetadataType._handleSOAPErrors) * [.getSOAPErrorMsg(ex)](#MetadataType.getSOAPErrorMsg) ⇒ string - * [.retrieveSOAP(retrieveDir, buObject, [requestParams], [additionalFields])](#MetadataType.retrieveSOAP) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.retrieveSOAP(retrieveDir, [requestParams], [additionalFields])](#MetadataType.retrieveSOAP) ⇒ Promise.<TYPE.MetadataTypeMapObj> * [.retrieveREST(retrieveDir, uri, [overrideType], [templateVariables], [singleRetrieve])](#MetadataType.retrieveREST) ⇒ Promise.<{metadata: (TYPE.MetadataTypeMap\|TYPE.MetadataTypeItem), type: string}> * [.parseResponseBody(body, [singleRetrieve])](#MetadataType.parseResponseBody) ⇒ TYPE.MetadataTypeMap * [.deleteFieldByDefinition(metadataEntry, fieldPath, definitionProperty, origin)](#MetadataType.deleteFieldByDefinition) ⇒ void @@ -3553,7 +3553,7 @@ helper for [_handleSOAPErrors](_handleSOAPErrors) -### MetadataType.retrieveSOAP(retrieveDir, buObject, [requestParams], [additionalFields]) ⇒ Promise.<TYPE.MetadataTypeMapObj> +### MetadataType.retrieveSOAP(retrieveDir, [requestParams], [additionalFields]) ⇒ Promise.<TYPE.MetadataTypeMapObj> Retrieves SOAP via generic fuel-soap wrapper based metadata of metadata type into local filesystem. executes callback with retrieved metadata **Kind**: static method of [MetadataType](#MetadataType) @@ -3562,7 +3562,6 @@ Retrieves SOAP via generic fuel-soap wrapper based metadata of metadata type int | Param | Type | Description | | --- | --- | --- | | retrieveDir | string | Directory where retrieved metadata directory will be saved | -| buObject | TYPE.BuObject | properties for auth | | [requestParams] | TYPE.SoapRequestParams | required for the specific request (filter for example) | | [additionalFields] | Array.<string> | Returns specified fields even if their retrieve definition is not set to true | diff --git a/lib/metadataTypes/AccountUser.js b/lib/metadataTypes/AccountUser.js index 883496d38..f320b6d32 100644 --- a/lib/metadataTypes/AccountUser.js +++ b/lib/metadataTypes/AccountUser.js @@ -110,7 +110,7 @@ class AccountUser extends MetadataType { }; } Util.logger.info(` - Loading ${this.definition.type}. This might take a while...`); - return super.retrieveSOAP(retrieveDir, this.buObject, requestParams); + return super.retrieveSOAP(retrieveDir, requestParams); } /** * diff --git a/lib/metadataTypes/ContentArea.js b/lib/metadataTypes/ContentArea.js index 3a7736dfb..e9eec26d2 100644 --- a/lib/metadataTypes/ContentArea.js +++ b/lib/metadataTypes/ContentArea.js @@ -36,7 +36,7 @@ class ContentArea extends MetadataType { }; } // !dont activate `await File.initPrettier('html');` as we only want to retrieve for migration and formatting might mess with the outcome - return super.retrieveSOAP(retrieveDir, null, requestParams); + return super.retrieveSOAP(retrieveDir, requestParams); } /** * manages post retrieve steps diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index 97bc14f6e..d4779228e 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -1037,7 +1037,7 @@ class DataExtension extends MetadataType { * @returns {Promise.} keyField => metadata map */ static async _retrieveAll(additionalFields, options) { - const { metadata } = await super.retrieveSOAP(null, null, options, additionalFields); + const { metadata } = await super.retrieveSOAP(null, options, additionalFields); for (const key in metadata) { // some system data extensions do not have CategoryID which throws errors in other places. These do not need to be parsed if (metadata[key].CategoryID) { diff --git a/lib/metadataTypes/DataExtensionField.js b/lib/metadataTypes/DataExtensionField.js index d07b393b0..997a48f64 100644 --- a/lib/metadataTypes/DataExtensionField.js +++ b/lib/metadataTypes/DataExtensionField.js @@ -18,7 +18,7 @@ class DataExtensionField extends MetadataType { * @returns {Promise.<{metadata: TYPE.DataExtensionFieldMap, type: string}>} Promise of items */ static async retrieve(retrieveDir, additionalFields) { - return super.retrieveSOAP(retrieveDir, this.buObject, null, additionalFields); + return super.retrieveSOAP(retrieveDir, null, additionalFields); } /** * Retrieves all records for caching @@ -28,7 +28,7 @@ class DataExtensionField extends MetadataType { * @returns {Promise.<{metadata: TYPE.DataExtensionFieldMap, type: string}>} Promise of items */ static async retrieveForCache(requestParams, additionalFields) { - return super.retrieveSOAP(null, null, requestParams, additionalFields); + return super.retrieveSOAP(null, requestParams, additionalFields); } /** * helper for {@link DataExtension._retrieveFieldsForSingleDe} that sorts the fields into an array diff --git a/lib/metadataTypes/DataExtensionTemplate.js b/lib/metadataTypes/DataExtensionTemplate.js index d896405b8..7312e0b3e 100644 --- a/lib/metadataTypes/DataExtensionTemplate.js +++ b/lib/metadataTypes/DataExtensionTemplate.js @@ -30,7 +30,7 @@ class DataExtensionTemplate extends MetadataType { }, }; } - return super.retrieveSOAP(retrieveDir, null, requestParams); + return super.retrieveSOAP(retrieveDir, requestParams); } } diff --git a/lib/metadataTypes/Email.js b/lib/metadataTypes/Email.js index 5343edd21..fe1715b39 100644 --- a/lib/metadataTypes/Email.js +++ b/lib/metadataTypes/Email.js @@ -35,7 +35,7 @@ class Email extends MetadataType { }; } // !dont activate `await File.initPrettier('html');` as we only want to retrieve for migration and formatting might mess with the outcome - return super.retrieveSOAP(retrieveDir, null, requestParams); + return super.retrieveSOAP(retrieveDir, requestParams); } /** * manages post retrieve steps diff --git a/lib/metadataTypes/EmailSendDefinition.js b/lib/metadataTypes/EmailSendDefinition.js index 6e7f1fb8a..8a868cd85 100644 --- a/lib/metadataTypes/EmailSendDefinition.js +++ b/lib/metadataTypes/EmailSendDefinition.js @@ -52,7 +52,7 @@ class EmailSendDefinition extends MetadataType { }, }; } - return super.retrieveSOAP(retrieveDir, null, requestParams); + return super.retrieveSOAP(retrieveDir, requestParams); } /** diff --git a/lib/metadataTypes/List.js b/lib/metadataTypes/List.js index a58d1d2e5..475aa2db3 100644 --- a/lib/metadataTypes/List.js +++ b/lib/metadataTypes/List.js @@ -43,7 +43,7 @@ class List extends MetadataType { }, }; } - const results = await super.retrieveSOAP(retrieveDir, null, requestParams); + const results = await super.retrieveSOAP(retrieveDir, requestParams); return await this._retrieveParentAllSubs(results); } /** diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 02183eed0..3c80006b6 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -765,12 +765,11 @@ class MetadataType { * Retrieves SOAP via generic fuel-soap wrapper based metadata of metadata type into local filesystem. executes callback with retrieved metadata * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved - * @param {TYPE.BuObject} buObject properties for auth * @param {TYPE.SoapRequestParams} [requestParams] required for the specific request (filter for example) * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true * @returns {Promise.} Promise of item map */ - static async retrieveSOAP(retrieveDir, buObject, requestParams, additionalFields) { + static async retrieveSOAP(retrieveDir, requestParams, additionalFields) { requestParams = requestParams || {}; const fields = this.getFieldNamesToRetrieve(additionalFields); let response; @@ -792,7 +791,7 @@ class MetadataType { `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` ); if ( - buObject && + this.buObject && this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type) ) { await this.document(savedMetadata); diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js index 3a7aec6da..44a1d795e 100644 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ b/lib/metadataTypes/TriggeredSendDefinition.js @@ -50,7 +50,7 @@ class TriggeredSendDefinition extends MetadataType { }; } - return super.retrieveSOAP(retrieveDir, null, requestParams); + return super.retrieveSOAP(retrieveDir, requestParams); } /** @@ -310,7 +310,7 @@ class TriggeredSendDefinition extends MetadataType { rightOperand: ['dummy', 'Active'], // using equals does not work for this field for an unknown reason and IN requires at least 2 values, hence the 'dummy' entry }, }; - const metadata = (await super.retrieveSOAP(null, null, requestParams)).metadata; + const metadata = (await super.retrieveSOAP(null, requestParams)).metadata; const keyArr = Object.keys(metadata).filter((key) => { const test = this.postRetrieveTasks(metadata[key]); return test?.CustomerKey || false; @@ -342,7 +342,7 @@ class TriggeredSendDefinition extends MetadataType { }; try { test = ( - await super.retrieveSOAP(null, null, requestParams, [ + await super.retrieveSOAP(null, requestParams, [ 'CustomerKey', 'TriggeredSendStatus', ]) From e585b797e2e915155e45b3ab6cb94c37f1d09067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 14:18:43 +0100 Subject: [PATCH 123/132] #567: fix selectTypes to show subtypes only if retrieveByDefault limits them --- lib/util/cli.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/util/cli.js b/lib/util/cli.js index 2cb508c68..674bc4990 100644 --- a/lib/util/cli.js +++ b/lib/util/cli.js @@ -410,7 +410,10 @@ const Cli = { const flattenedDefinitions = []; for (const el in MetadataDefinitions) { // if subtypes on metadata (eg. Assets) then add each nested subtype - if (MetadataDefinitions[el].subTypes) { + if ( + MetadataDefinitions[el].subTypes && + Array.isArray(MetadataDefinitions[el].typeRetrieveByDefault) + ) { for (const subtype of MetadataDefinitions[el].subTypes) { flattenedDefinitions.push({ typeName: From f3d13705961c3c101366daee0286f40087d66942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 15:10:28 +0100 Subject: [PATCH 124/132] #678: fix retrieve 'cred/' with selecting * via wizard --- lib/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index 9bae8032f..71bd2aab1 100644 --- a/lib/index.js +++ b/lib/index.js @@ -147,7 +147,7 @@ class Mcdev { if ( properties.credentials && (!properties.credentials[cred] || - (bu !== '*' && properties.credentials[cred].businessUnits[bu])) + (bu !== '*' && !properties.credentials[cred].businessUnits[bu])) ) { const buObject = await Cli.getCredentialObject( properties, From 18280de2c3c6b14df6914e0f3f8902d2df2bd4a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 15:34:16 +0100 Subject: [PATCH 125/132] #679: only show email-deprecation notice during retrieve and when records were found --- docs/dist/documentation.md | 16 ++++++++++++++++ lib/metadataTypes/Email.js | 21 ++++++++++++++++++--- lib/metadataTypes/Interaction.js | 1 + 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 1993e4d9e..b071d9912 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -2174,6 +2174,7 @@ Email MetadataType * [Email](#Email) ⇐ [MetadataType](#MetadataType) * [.retrieve(retrieveDir, [_], [__], [key])](#Email.retrieve) ⇒ Promise.<TYPE.MetadataTypeMapObj> + * [.saveResults(results, retrieveDir, [overrideType], [templateVariables])](#Email.saveResults) ⇒ Promise.<TYPE.MetadataTypeMap> * [.postRetrieveTasks(metadata)](#Email.postRetrieveTasks) ⇒ TYPE.MetadataTypeItem * [.parseMetadata(metadata)](#Email.parseMetadata) ⇒ TYPE.MetadataTypeItem @@ -2192,6 +2193,21 @@ Retrieves SOAP based metadata of metadata type into local filesystem. executes c | [__] | void | unused parameter | | [key] | string | customer key of single item to retrieve | + + +### Email.saveResults(results, retrieveDir, [overrideType], [templateVariables]) ⇒ Promise.<TYPE.MetadataTypeMap> +Helper for writing Metadata to disk, used for Retrieve and deploy + +**Kind**: static method of [Email](#Email) +**Returns**: Promise.<TYPE.MetadataTypeMap> - Promise of saved metadata + +| Param | Type | Description | +| --- | --- | --- | +| results | TYPE.MetadataTypeMap | metadata results from deploy | +| retrieveDir | string | directory where metadata should be stored after deploy/retrieve | +| [overrideType] | string | for use when there is a subtype (such as folder-queries) | +| [templateVariables] | TYPE.TemplateMap | variables to be replaced in the metadata | + ### Email.postRetrieveTasks(metadata) ⇒ TYPE.MetadataTypeItem diff --git a/lib/metadataTypes/Email.js b/lib/metadataTypes/Email.js index fe1715b39..11fcb71c8 100644 --- a/lib/metadataTypes/Email.js +++ b/lib/metadataTypes/Email.js @@ -20,9 +20,6 @@ class Email extends MetadataType { * @returns {Promise.} Promise of metadata */ static retrieve(retrieveDir, _, __, key) { - Util.logger.warn( - ' - Classic E-Mails are deprecated and will be discontinued by SFMC in the near future. Ensure that you migrate any existing E-Mails to Content Builder as soon as possible.' - ); /** @type {TYPE.SoapRequestParams} */ let requestParams = null; if (key) { @@ -37,6 +34,24 @@ class Email extends MetadataType { // !dont activate `await File.initPrettier('html');` as we only want to retrieve for migration and formatting might mess with the outcome return super.retrieveSOAP(retrieveDir, requestParams); } + /** + * Helper for writing Metadata to disk, used for Retrieve and deploy + * + * @param {TYPE.MetadataTypeMap} results metadata results from deploy + * @param {string} retrieveDir directory where metadata should be stored after deploy/retrieve + * @param {string} [overrideType] for use when there is a subtype (such as folder-queries) + * @param {TYPE.TemplateMap} [templateVariables] variables to be replaced in the metadata + * @returns {Promise.} Promise of saved metadata + */ + static async saveResults(results, retrieveDir, overrideType, templateVariables) { + if (Object.keys(results).length) { + // only execute the following if records were found + Util.logger.warn( + ' - Classic E-Mails are deprecated and will be discontinued by SFMC in the near future. Ensure that you migrate any existing E-Mails to Content Builder as soon as possible.' + ); + } + return super.saveResults(results, retrieveDir, overrideType, templateVariables); + } /** * manages post retrieve steps * diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js index 18a5d72c6..a36cb9fbe 100644 --- a/lib/metadataTypes/Interaction.js +++ b/lib/metadataTypes/Interaction.js @@ -188,6 +188,7 @@ class Interaction extends MetadataType { */ static async saveResults(results, retrieveDir, overrideType, templateVariables) { if (Object.keys(results).length) { + // only execute the following if records were found await this._postRetrieveTasksBulk(results); } return super.saveResults(results, retrieveDir, overrideType, templateVariables); From e273f04435a6ea04357a950e1b344ed51bd58937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 15:42:52 +0100 Subject: [PATCH 126/132] 4.3.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 54b9a6cd1..5c9f5d94b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mcdev", - "version": "4.2.1", + "version": "4.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mcdev", - "version": "4.2.1", + "version": "4.3.0", "license": "MIT", "dependencies": { "beauty-amp-core": "0.3.7", diff --git a/package.json b/package.json index ae54c5337..acab6139d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mcdev", - "version": "4.2.1", + "version": "4.3.0", "description": "Accenture Salesforce Marketing Cloud DevTools", "author": "Accenture: joern.berkefeld, douglas.midgley, robert.zimmermann, maciej.barnas", "license": "MIT", From 9b17a5bcf4d624180b21c84295063f8a0b99db4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 16:28:17 +0100 Subject: [PATCH 127/132] #684: fix for no automations found causing a javascript error --- lib/metadataTypes/Automation.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/metadataTypes/Automation.js b/lib/metadataTypes/Automation.js index a7fc88b3c..9565985e9 100644 --- a/lib/metadataTypes/Automation.js +++ b/lib/metadataTypes/Automation.js @@ -35,9 +35,14 @@ class Automation extends MetadataType { }; } const results = await this.client.soap.retrieveBulk('Program', ['ObjectID'], requestParams); - Util.logger.info( - Util.getGrayMsg(` - ${results.Results.length} Automations found. Retrieving details...`) - ); + if (results.Results?.length) { + // empty results will come back without "Results" defined + Util.logger.info( + Util.getGrayMsg( + ` - ${results.Results?.length} Automations found. Retrieving details...` + ) + ); + } const details = results.Results ? await Promise.all( results.Results.map(async (a) => { From b1a2d54e204d4d903650c70730b3df62f44d861d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 16:29:17 +0100 Subject: [PATCH 128/132] #0: keep often used logger ready to use for future developments --- lib/util/auth.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/util/auth.js b/lib/util/auth.js index 90ef50b35..d9aabe6bf 100644 --- a/lib/util/auth.js +++ b/lib/util/auth.js @@ -114,6 +114,8 @@ function setupSDK(sessionKey, authObject) { ); Util.logger.errorStack(ex); }, + // logRequest: (req) => console.log('request', req), // uncomment to log requests + // logResponse: (res) => console.log('response:', res), // uncomment to log responses }, requestAttempts: 4, retryOnConnectionError: true, From 133245da546aa07980bc6c6bc53cae46dbd59fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 16:42:39 +0100 Subject: [PATCH 129/132] #636: fix for subtypes that have "-" in their name --- lib/util/util.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/util/util.js b/lib/util/util.js index d9e7da66a..de320e5e5 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -352,7 +352,11 @@ const Util = { continue; } finalList[key] = subTypeDeps[key] - ? [...subTypeDeps[key]].map((a) => a.split('-')[1]) + ? [...subTypeDeps[key]].map((a) => { + const temp = a.split('-'); + temp.shift(); // remove first item which is the main type + return temp.join('-'); + }) : null; } else { finalList[type] = null; From 09658149f0e5b7abb40b4b41a11ffb408fb2f08e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 16:48:38 +0100 Subject: [PATCH 130/132] #0: prep 4.3.0 release --- .github/ISSUE_TEMPLATE/bug.yml | 1 + test/mockRoot/.mcdevrc.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 4220dcb2a..5fa0ac66d 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -39,6 +39,7 @@ body: label: Version description: What version of our software are you running? (mcdev --version) options: + - 4.3.0 - 4.2.1 - 4.2.0 - 4.1.12 diff --git a/test/mockRoot/.mcdevrc.json b/test/mockRoot/.mcdevrc.json index c67fae6db..8ad5c0163 100644 --- a/test/mockRoot/.mcdevrc.json +++ b/test/mockRoot/.mcdevrc.json @@ -74,5 +74,5 @@ "triggeredSendDefinition" ] }, - "version": "4.2.0" + "version": "4.3.0" } From 717a6e11ddb2e8d1d7d6646cadaa7936ccef57ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 16:53:58 +0100 Subject: [PATCH 131/132] #636: fix for subtypes that have "-" in their name --- lib/util/util.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/util/util.js b/lib/util/util.js index de320e5e5..4c7fd2651 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -159,7 +159,14 @@ const Util = { * @returns {boolean} type ok or not */ _isValidType(selectedType, handleOutside) { - const [type, subType] = selectedType ? selectedType.split('-') : []; + let type; + let subType; + if (selectedType) { + const temp = selectedType.split('-'); + type = temp[0]; + temp.shift(); // remove first item which is the main type + subType = temp.join('-'); // subType can include "-" + } if (type && !MetadataDefinitions[type]) { if (!handleOutside) { Util.logger.error(`:: '${type}' is not a valid metadata type`); @@ -355,7 +362,7 @@ const Util = { ? [...subTypeDeps[key]].map((a) => { const temp = a.split('-'); temp.shift(); // remove first item which is the main type - return temp.join('-'); + return temp.join('-'); // subType can include "-" }) : null; } else { From 0aed3a1c2e86adb6e06221cf1f19337132db5d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Mon, 30 Jan 2023 17:03:38 +0100 Subject: [PATCH 132/132] #636: fix for subtypes that have "-" in their name --- docs/dist/documentation.md | 26 ++++++++++++++++++++++++++ lib/index.js | 4 ++-- lib/util/util.js | 26 ++++++++++++++++++-------- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index b071d9912..90e848d8a 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -5119,6 +5119,7 @@ CLI entry for SFMC DevTools * [.isTrue(attrValue)](#Util.isTrue) ⇒ boolean * [.isFalse(attrValue)](#Util.isFalse) ⇒ boolean * [._isValidType(selectedType, [handleOutside])](#Util._isValidType) ⇒ boolean + * [.getTypeAndSubType(selectedType)](#Util.getTypeAndSubType) ⇒ Array.<string> * [.getRetrieveTypeChoices()](#Util.getRetrieveTypeChoices) ⇒ Array.<TYPE.SupportedMetadataTypes> * [.metadataLogger(level, type, method, payload, [source])](#Util.metadataLogger) ⇒ void * [.replaceByObject(str, obj)](#Util.replaceByObject) ⇒ string \| object @@ -5252,6 +5253,18 @@ helper for [retrieve](#Mcdev.retrieve), [retrieveAsTemplate](#Mcdev.retrieveAsTe | selectedType | TYPE.SupportedMetadataTypes | type or type-subtype | | [handleOutside] | boolean | if the API reponse is irregular this allows you to handle it outside of this generic method | + + +### Util.getTypeAndSubType(selectedType) ⇒ Array.<string> +helper that deals with extracting type and subtype + +**Kind**: static method of [Util](#Util) +**Returns**: Array.<string> - first elem is type, second elem is subType + +| Param | Type | Description | +| --- | --- | --- | +| selectedType | string | "type" or "type-subtype" | + ### Util.getRetrieveTypeChoices() ⇒ Array.<TYPE.SupportedMetadataTypes> @@ -6921,6 +6934,7 @@ Util that contains logger and simple util methods * [.isTrue(attrValue)](#Util.isTrue) ⇒ boolean * [.isFalse(attrValue)](#Util.isFalse) ⇒ boolean * [._isValidType(selectedType, [handleOutside])](#Util._isValidType) ⇒ boolean + * [.getTypeAndSubType(selectedType)](#Util.getTypeAndSubType) ⇒ Array.<string> * [.getRetrieveTypeChoices()](#Util.getRetrieveTypeChoices) ⇒ Array.<TYPE.SupportedMetadataTypes> * [.metadataLogger(level, type, method, payload, [source])](#Util.metadataLogger) ⇒ void * [.replaceByObject(str, obj)](#Util.replaceByObject) ⇒ string \| object @@ -7054,6 +7068,18 @@ helper for [retrieve](#Mcdev.retrieve), [retrieveAsTemplate](#Mcdev.retrieveAsTe | selectedType | TYPE.SupportedMetadataTypes | type or type-subtype | | [handleOutside] | boolean | if the API reponse is irregular this allows you to handle it outside of this generic method | + + +### Util.getTypeAndSubType(selectedType) ⇒ Array.<string> +helper that deals with extracting type and subtype + +**Kind**: static method of [Util](#Util) +**Returns**: Array.<string> - first elem is type, second elem is subType + +| Param | Type | Description | +| --- | --- | --- | +| selectedType | string | "type" or "type-subtype" | + ### Util.getRetrieveTypeChoices() ⇒ Array.<TYPE.SupportedMetadataTypes> diff --git a/lib/index.js b/lib/index.js index 71bd2aab1..f88341a53 100644 --- a/lib/index.js +++ b/lib/index.js @@ -220,7 +220,7 @@ class Mcdev { for (const selectedType of Array.isArray(selectedTypesArr) ? selectedTypesArr : Object.keys(selectedTypesArr)) { - const [type, subType] = selectedType ? selectedType.split('-') : []; + const [type, subType] = Util.getTypeAndSubType(selectedType); const removePathArr = [properties.directories.retrieve, cred, bu, type]; if ( type && @@ -518,7 +518,7 @@ class Mcdev { if (!Util._isValidType(selectedType)) { return; } - const [type, subType] = selectedType ? selectedType.split('-') : []; + const [type, subType] = Util.getTypeAndSubType(selectedType); let retrieveTypesArr; if ( diff --git a/lib/util/util.js b/lib/util/util.js index 4c7fd2651..be2ca7cc5 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -159,14 +159,7 @@ const Util = { * @returns {boolean} type ok or not */ _isValidType(selectedType, handleOutside) { - let type; - let subType; - if (selectedType) { - const temp = selectedType.split('-'); - type = temp[0]; - temp.shift(); // remove first item which is the main type - subType = temp.join('-'); // subType can include "-" - } + const [type, subType] = Util.getTypeAndSubType(selectedType); if (type && !MetadataDefinitions[type]) { if (!handleOutside) { Util.logger.error(`:: '${type}' is not a valid metadata type`); @@ -185,6 +178,23 @@ const Util = { return true; }, + /** + * helper that deals with extracting type and subtype + * + * @param {string} selectedType "type" or "type-subtype" + * @returns {string[]} first elem is type, second elem is subType + */ + getTypeAndSubType(selectedType) { + if (selectedType) { + const temp = selectedType.split('-'); + const type = temp.shift(); // remove first item which is the main typ + const subType = temp.join('-'); // subType can include "-" + return [type, subType]; + } else { + return []; + } + }, + /** * helper for getDefaultProperties() *