mcdev 8.2.1 → 8.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug.yml +1 -0
- package/.github/workflows/code-test.yml +1 -1
- package/.github/workflows/coverage-base-update.yml +1 -1
- package/.github/workflows/coverage-develop-branch.yml +1 -1
- package/.github/workflows/coverage-main-branch.yml +1 -1
- package/.github/workflows/coverage.yml +1 -1
- package/.github/workflows/npm-publish.yml +9 -5
- package/@types/lib/MetadataTypeDefinitions.d.ts +4 -0
- package/@types/lib/MetadataTypeDefinitions.d.ts.map +1 -1
- package/@types/lib/MetadataTypeInfo.d.ts +4 -0
- package/@types/lib/MetadataTypeInfo.d.ts.map +1 -1
- package/@types/lib/Retriever.d.ts.map +1 -1
- package/@types/lib/index.d.ts +20 -9
- package/@types/lib/index.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Asset.d.ts +3 -3
- package/@types/lib/metadataTypes/Asset.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Automation.d.ts +7 -7
- package/@types/lib/metadataTypes/Automation.d.ts.map +1 -1
- package/@types/lib/metadataTypes/DataExtension.d.ts +9 -9
- package/@types/lib/metadataTypes/DataExtension.d.ts.map +1 -1
- package/@types/lib/metadataTypes/DataExtensionField.d.ts +7 -0
- package/@types/lib/metadataTypes/DataExtensionField.d.ts.map +1 -1
- package/@types/lib/metadataTypes/DataFilter.d.ts +326 -0
- package/@types/lib/metadataTypes/DataFilter.d.ts.map +1 -0
- package/@types/lib/metadataTypes/DataFilterHidden.d.ts +164 -0
- package/@types/lib/metadataTypes/DataFilterHidden.d.ts.map +1 -0
- package/@types/lib/metadataTypes/Filter.d.ts +181 -6
- package/@types/lib/metadataTypes/Filter.d.ts.map +1 -1
- package/@types/lib/metadataTypes/FilterDefinition.d.ts +318 -0
- package/@types/lib/metadataTypes/FilterDefinition.d.ts.map +1 -0
- package/@types/lib/metadataTypes/FilterDefinitionHidden.d.ts +156 -0
- package/@types/lib/metadataTypes/FilterDefinitionHidden.d.ts.map +1 -0
- package/@types/lib/metadataTypes/ImportFile.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Journey.d.ts +18 -0
- package/@types/lib/metadataTypes/Journey.d.ts.map +1 -1
- package/@types/lib/metadataTypes/MobileKeyword.d.ts +2 -2
- package/@types/lib/metadataTypes/MobileKeyword.d.ts.map +1 -1
- package/@types/lib/metadataTypes/User.d.ts +1 -1
- package/@types/lib/metadataTypes/User.d.ts.map +1 -1
- package/@types/lib/metadataTypes/definitions/DataFilter.definition.d.ts +230 -0
- package/@types/lib/metadataTypes/definitions/DataFilter.definition.d.ts.map +1 -0
- package/@types/lib/metadataTypes/definitions/DataFilterHidden.definition.d.ts +230 -0
- package/@types/lib/metadataTypes/definitions/DataFilterHidden.definition.d.ts.map +1 -0
- package/@types/lib/metadataTypes/definitions/Filter.definition.d.ts +203 -31
- package/@types/lib/metadataTypes/definitions/FilterDefinition.definition.d.ts +218 -0
- package/@types/lib/metadataTypes/definitions/FilterDefinition.definition.d.ts.map +1 -0
- package/@types/lib/metadataTypes/definitions/FilterDefinitionHidden.definition.d.ts +218 -0
- package/@types/lib/metadataTypes/definitions/FilterDefinitionHidden.definition.d.ts.map +1 -0
- package/@types/lib/metadataTypes/definitions/Journey.definition.d.ts +18 -0
- package/@types/lib/util/devops.d.ts +1 -0
- package/@types/lib/util/devops.d.ts.map +1 -1
- package/@types/lib/util/replaceContentBlockReference.d.ts +3 -3
- package/@types/lib/util/replaceContentBlockReference.d.ts.map +1 -1
- package/@types/lib/util/util.d.ts.map +1 -1
- package/@types/lib/util/validations.d.ts.map +1 -1
- package/@types/types/mcdev.d.d.ts +296 -0
- package/@types/types/mcdev.d.d.ts.map +1 -1
- package/lib/MetadataTypeDefinitions.js +4 -0
- package/lib/MetadataTypeInfo.js +4 -0
- package/lib/Retriever.js +3 -0
- package/lib/index.js +87 -3
- package/lib/metadataTypes/DataExtensionField.js +21 -0
- package/lib/metadataTypes/DataFilter.js +653 -0
- package/lib/metadataTypes/DataFilterHidden.js +18 -0
- package/lib/metadataTypes/Filter.js +315 -1
- package/lib/metadataTypes/ImportFile.js +11 -1
- package/lib/metadataTypes/Journey.js +111 -7
- package/lib/metadataTypes/definitions/Automation.definition.js +1 -0
- package/lib/metadataTypes/definitions/DataFilter.definition.js +168 -0
- package/lib/metadataTypes/definitions/DataFilterHidden.definition.js +169 -0
- package/lib/metadataTypes/definitions/Filter.definition.js +136 -22
- package/lib/metadataTypes/definitions/Journey.definition.js +20 -1
- package/lib/util/devops.js +14 -4
- package/lib/util/util.js +7 -2
- package/lib/util/validations.js +7 -1
- package/package.json +10 -10
- package/test/general.test.js +17 -19
- package/test/mockRoot/.mcdevrc.json +4 -1
- package/test/mockRoot/deploy/testInstance/testBU/dataFilter/testExisting_dataFilter.dataFilter-meta.json +19 -0
- package/test/mockRoot/deploy/testInstance/testBU/dataFilter/testNew_dataFilter.dataFilter-meta.json +19 -0
- package/test/mockRoot/deploy/testInstance/testBU/filter/testExisting_filter.filter-meta.json +10 -0
- package/test/mockRoot/deploy/testInstance/testBU/filter/testNew_filter.filter-meta.json +11 -0
- package/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_journey_updatecontact.journey-meta.json +108 -0
- package/test/resources/9999999/automation/v1/filters/a0f1a1bc-4ea1-44b3-8fe1-ce40ef35c1c0/patch-response.json +18 -0
- package/test/resources/9999999/automation/v1/filters/f018f237-f7ef-40b0-afc8-39ea2e5dcca4/delete-response.txt +0 -0
- package/test/resources/9999999/automation/v1/filters/f018f237-f7ef-40b0-afc8-39ea2e5dcca4/get-response.json +15 -0
- package/test/resources/9999999/automation/v1/filters/f018f237-f7ef-40b0-afc8-39ea2e5dcca4/patch-response.json +15 -0
- package/test/resources/9999999/automation/v1/filters/get-response.json +22 -0
- package/test/resources/9999999/dataFilter/build-expected.json +19 -0
- package/test/resources/9999999/dataFilter/get-expected.json +23 -0
- package/test/resources/9999999/dataFilter/patch-expected.json +20 -0
- package/test/resources/9999999/dataFilter/post-expected.json +20 -0
- package/test/resources/9999999/dataFilter/template-expected.json +19 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,automatio,cloudpage,dataexten,filteract,filterdef,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,useriniti-response.xml +765 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentTypeINfilteractivity,hidden-response.xml +139 -0
- package/test/resources/9999999/dataFolder/retrieve-ContentTypeINfilterdefinition,hidden-response.xml +116 -0
- package/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/delete-response.txt +1 -0
- package/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/get-response.json +19 -0
- package/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/patch-response.json +15 -0
- package/test/resources/9999999/email/v1/filters/filterdefinition/category/5318/get-response.json +27 -0
- package/test/resources/9999999/email/v1/filters/filterdefinition/category/8502/get-response.json +7 -0
- package/test/resources/9999999/email/v1/filters/filterdefinition/category/8503/get-response.json +7 -0
- package/test/resources/9999999/email/v1/filters/filterdefinition/post-response.json +15 -0
- package/test/resources/9999999/filter/build-expected.json +10 -0
- package/test/resources/9999999/filter/get-expected.json +11 -0
- package/test/resources/9999999/filter/patch-expected.json +11 -0
- package/test/resources/9999999/filter/post-expected.json +11 -0
- package/test/resources/9999999/filter/template-expected.json +10 -0
- package/test/resources/9999999/filterActivity/create-response.xml +46 -0
- package/test/resources/9999999/filterActivity/retrieve-CustomerKey=testExisting_filter-response.xml +30 -0
- package/test/resources/9999999/filterDefinition/retrieve-CustomerKey=testExisting_dataFilter-response.xml +30 -0
- package/test/resources/9999999/interaction/v1/interactions/get-response.json +45 -3
- package/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_updatecontact/get-response.json +119 -0
- package/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_updatecontact/put-response.json +106 -0
- package/test/resources/9999999/journey/get-updatecontact-expected.json +108 -0
- package/test/resources/9999999/journey/put-updatecontact-expected.json +108 -0
- package/test/type.automation.test.js +14 -14
- package/test/type.dataFilter.test.js +174 -0
- package/test/type.filter.test.js +170 -0
- package/test/type.journey.test.js +59 -7
- package/test/type.query.test.js +2 -2
- package/test/utils.js +8 -0
- package/types/mcdev.d.js +101 -0
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
import MetadataType from './MetadataType.js';
|
|
4
|
+
import { Util } from '../util/util.js';
|
|
5
|
+
import cache from '../util/cache.js';
|
|
6
|
+
import File from '../util/file.js';
|
|
7
|
+
|
|
8
|
+
const dataTypes = {
|
|
9
|
+
1: 'List',
|
|
10
|
+
2: 'DataExtension',
|
|
11
|
+
3: 'Group Wizard',
|
|
12
|
+
4: 'Behavioral Data',
|
|
13
|
+
};
|
|
4
14
|
|
|
5
15
|
/**
|
|
6
16
|
* @typedef {import('../../types/mcdev.d.js').BuObject} BuObject
|
|
@@ -13,6 +23,7 @@ import MetadataType from './MetadataType.js';
|
|
|
13
23
|
* @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj
|
|
14
24
|
* @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams
|
|
15
25
|
* @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap
|
|
26
|
+
* @typedef {import('../../types/mcdev.d.js').FilterItem} FilterItem
|
|
16
27
|
*/
|
|
17
28
|
|
|
18
29
|
/**
|
|
@@ -34,7 +45,310 @@ class Filter extends MetadataType {
|
|
|
34
45
|
* @returns {Promise.<MetadataTypeMapObj>} Promise
|
|
35
46
|
*/
|
|
36
47
|
static async retrieve(retrieveDir, _, __, key) {
|
|
37
|
-
|
|
48
|
+
const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : '';
|
|
49
|
+
return super.retrieveREST(retrieveDir, '/automation/v1/filters/' + objectId, null, key);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* parses retrieved Metadata before saving
|
|
53
|
+
*
|
|
54
|
+
* @param {FilterItem} metadata a single record
|
|
55
|
+
* @returns {FilterItem} parsed metadata definition
|
|
56
|
+
*/
|
|
57
|
+
static postRetrieveTasks(metadata) {
|
|
58
|
+
// folder
|
|
59
|
+
super.setFolderPath(metadata);
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
// filterDefinition
|
|
63
|
+
metadata.r__dataFilter_key = cache.searchForField(
|
|
64
|
+
'dataFilter',
|
|
65
|
+
metadata.filterDefinitionId,
|
|
66
|
+
'id',
|
|
67
|
+
'key'
|
|
68
|
+
);
|
|
69
|
+
delete metadata.filterDefinitionId;
|
|
70
|
+
} catch {
|
|
71
|
+
try {
|
|
72
|
+
// filterDefinitionHidden - auto-generated for filtered dataExtensions
|
|
73
|
+
metadata.r__dataFilter_key = cache.searchForField(
|
|
74
|
+
'dataFilterHidden',
|
|
75
|
+
metadata.filterDefinitionId,
|
|
76
|
+
'id',
|
|
77
|
+
'key'
|
|
78
|
+
);
|
|
79
|
+
delete metadata.filterDefinitionId;
|
|
80
|
+
} catch {
|
|
81
|
+
// ignore
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// rest API does not return description property when it's empty but we always want this as part of our json
|
|
86
|
+
metadata.description ||= '';
|
|
87
|
+
|
|
88
|
+
this._postRetrieve_dataTypeMapping('source', metadata);
|
|
89
|
+
this._postRetrieve_dataTypeMapping('destination', metadata);
|
|
90
|
+
return metadata;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* helper for postRetrieveTasks to map data types
|
|
95
|
+
*
|
|
96
|
+
* @param {'source'|'destination'} target we are processing source and destinations
|
|
97
|
+
* @param {FilterItem} metadata single record
|
|
98
|
+
*/
|
|
99
|
+
static _postRetrieve_dataTypeMapping(target, metadata) {
|
|
100
|
+
try {
|
|
101
|
+
switch (metadata[`${target}TypeId`]) {
|
|
102
|
+
// case 1: {
|
|
103
|
+
// // List
|
|
104
|
+
// // TODO
|
|
105
|
+
// break;
|
|
106
|
+
case 2: {
|
|
107
|
+
// dataExtension
|
|
108
|
+
metadata[`r__${target}_dataExtension_key`] = cache.searchForField(
|
|
109
|
+
'dataExtension',
|
|
110
|
+
metadata[`${target}ObjectId`],
|
|
111
|
+
'ObjectID',
|
|
112
|
+
'CustomerKey'
|
|
113
|
+
);
|
|
114
|
+
delete metadata[`${target}ObjectId`];
|
|
115
|
+
delete metadata[`${target}TypeId`];
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
// case 3: {
|
|
119
|
+
// // GroupWizard
|
|
120
|
+
// // TODO
|
|
121
|
+
// break;
|
|
122
|
+
// }
|
|
123
|
+
// case 4: {
|
|
124
|
+
// // BehavioralData
|
|
125
|
+
// // TODO
|
|
126
|
+
// break;
|
|
127
|
+
// }
|
|
128
|
+
default: {
|
|
129
|
+
Util.logger.warn(
|
|
130
|
+
` - Filter '${metadata.name}' (${
|
|
131
|
+
metadata.customerKey
|
|
132
|
+
}): Unsupported ${target} type '${dataTypes[metadata[`${target}TypeId`]]}'`
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
} catch (ex) {
|
|
137
|
+
Util.logger.warn(
|
|
138
|
+
` - filter '${metadata.name}' (${metadata.customerKey}): ${target} not found (${ex.message})`
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* helper for preDeployTasks to map data types
|
|
144
|
+
*
|
|
145
|
+
* @param {'source'|'destination'} target we are processing source and destinations
|
|
146
|
+
* @param {FilterItem} metadata single record
|
|
147
|
+
* @param {FilterItem} cachedVersion cached version of the metadata
|
|
148
|
+
*/
|
|
149
|
+
static _preDeploy_dataTypeMapping(target, metadata, cachedVersion) {
|
|
150
|
+
// TODO List / TypeId==1
|
|
151
|
+
|
|
152
|
+
// dataExtension
|
|
153
|
+
if (metadata[`r__${target}_dataExtension_key`]) {
|
|
154
|
+
metadata[`${target}TypeId`] = 2;
|
|
155
|
+
|
|
156
|
+
metadata[`${target}ObjectId`] = cache.searchForField(
|
|
157
|
+
'dataExtension',
|
|
158
|
+
metadata[`r__${target}_dataExtension_key`],
|
|
159
|
+
'CustomerKey',
|
|
160
|
+
'ObjectID'
|
|
161
|
+
);
|
|
162
|
+
if (
|
|
163
|
+
cachedVersion &&
|
|
164
|
+
cachedVersion[`${target}ObjectId`] !== metadata[`${target}ObjectId`]
|
|
165
|
+
) {
|
|
166
|
+
throw new Error(
|
|
167
|
+
`Updating r__${target}_dataExtension_key is not allowed. You need to delete and re-create the filter to change this.`
|
|
168
|
+
);
|
|
169
|
+
// metadata[`${target}ObjectId`] = cachedVersion[`${target}ObjectId`];
|
|
170
|
+
}
|
|
171
|
+
if (target === 'source') {
|
|
172
|
+
// this seems to be duplicated in update calls from the GUI
|
|
173
|
+
metadata.filterDefinitionSourceTypeId = metadata[`${target}TypeId`];
|
|
174
|
+
metadata.sourceId = null;
|
|
175
|
+
} else if (target === 'destination') {
|
|
176
|
+
const deItem = cache.getByKey(
|
|
177
|
+
'dataExtension',
|
|
178
|
+
metadata[`r__${target}_dataExtension_key`]
|
|
179
|
+
);
|
|
180
|
+
metadata.resultDEDescription = deItem?.Description || '';
|
|
181
|
+
metadata.resultDEName = deItem?.Name || '';
|
|
182
|
+
metadata.resultDEKey = deItem?.CustomerKey || '';
|
|
183
|
+
|
|
184
|
+
metadata.resultGroupFolderId = null;
|
|
185
|
+
metadata.resultGroupName = null;
|
|
186
|
+
}
|
|
187
|
+
delete metadata[`r__${target}_dataExtension_key`];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// TODO GroupWizard / TypeId==3
|
|
191
|
+
|
|
192
|
+
// TODO BehavioralData / TypeId==4
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Creates a single item
|
|
197
|
+
* this uses soap API because the rest api does not allow hotlinking to an existing target DE
|
|
198
|
+
*
|
|
199
|
+
* @param {FilterItem} item a single item
|
|
200
|
+
* @returns {Promise} Promise
|
|
201
|
+
*/
|
|
202
|
+
static async create(item) {
|
|
203
|
+
// create: POST automation/v1/filters/
|
|
204
|
+
// {"filterDefinitionId":"4b9adc79-8f56-488c-9910-ab7ad7afc13a","name":"jb_talent_flat_2_gui","description":"","categoryId":"5319","sourceId":null,"resultGroupFolderId":null,"resultGroupName":null,"filterDefinitionSourceTypeId":2,"folderLocationText":"Filter","customerKey":"jb_talent_flat_2_gui","resultDEName":"jb_talent_flat_2_gui","resultDEKey":"jb_talent_flat_2_gui","resultDEDescription":""}
|
|
205
|
+
// return super.createREST(item, '/automation/v1/filters/');
|
|
206
|
+
|
|
207
|
+
let response = null;
|
|
208
|
+
try {
|
|
209
|
+
response = await super.createSOAP(this.preCreateSOAPItem(item), true);
|
|
210
|
+
|
|
211
|
+
Util.logger.info(` - created ${Util.getTypeKeyName(this.definition, item)}`);
|
|
212
|
+
} catch (ex) {
|
|
213
|
+
this._handleSOAPErrors(ex, 'creating', item, false);
|
|
214
|
+
}
|
|
215
|
+
return this.postCreateTasks(item, response);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* helper that converts the rest item into a soap item
|
|
220
|
+
*
|
|
221
|
+
* @param {FilterItem} item a single item
|
|
222
|
+
* @returns {object} SOAP formatted filter item
|
|
223
|
+
*/
|
|
224
|
+
static preCreateSOAPItem(item) {
|
|
225
|
+
return {
|
|
226
|
+
FilterDefinitionID: item.filterDefinitionId,
|
|
227
|
+
Name: item.name,
|
|
228
|
+
Description: item.description || '',
|
|
229
|
+
// CategoryID: item.categoryId,
|
|
230
|
+
CustomerKey: item.customerKey,
|
|
231
|
+
DestinationTypeID: item.destinationTypeId,
|
|
232
|
+
DestinationObjectID: item.destinationObjectId,
|
|
233
|
+
SourceTypeID: item.sourceTypeId,
|
|
234
|
+
SourceObjectID: item.sourceObjectId,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* helper that runs update on all create calls to ensure all fields are set
|
|
240
|
+
*
|
|
241
|
+
* @param {FilterItem} restItem original rest item
|
|
242
|
+
* @param {object} response SOAP response
|
|
243
|
+
* @returns {Promise.<FilterItem>} created item
|
|
244
|
+
*/
|
|
245
|
+
static async postCreateTasks(restItem, response) {
|
|
246
|
+
Util.logger.debug(
|
|
247
|
+
` - running post create tasks for ${Util.getTypeKeyName(this.definition, restItem)} to set the folder ID`
|
|
248
|
+
);
|
|
249
|
+
if (!response) {
|
|
250
|
+
return response;
|
|
251
|
+
}
|
|
252
|
+
const soapItem = response.Results?.[0].Object;
|
|
253
|
+
restItem.filterActivityId = soapItem.FilterActivityID;
|
|
254
|
+
return super.updateREST(
|
|
255
|
+
restItem,
|
|
256
|
+
'/automation/v1/filters/' + restItem[this.definition.idField],
|
|
257
|
+
undefined,
|
|
258
|
+
true
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Updates a single item
|
|
264
|
+
*
|
|
265
|
+
* @param {MetadataTypeItem} item a single item
|
|
266
|
+
* @returns {Promise} Promise
|
|
267
|
+
*/
|
|
268
|
+
static update(item) {
|
|
269
|
+
return super.updateREST(item, '/automation/v1/filters/' + item[this.definition.idField]);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* prepares a record for deployment
|
|
274
|
+
*
|
|
275
|
+
* @param {FilterItem} metadata a single record
|
|
276
|
+
* @returns {Promise.<FilterItem>} Promise of updated single record
|
|
277
|
+
*/
|
|
278
|
+
static async preDeployTasks(metadata) {
|
|
279
|
+
// folder
|
|
280
|
+
super.setFolderId(metadata);
|
|
281
|
+
|
|
282
|
+
// disable updates to r__dataFilter_key, r__source_dataExtension_key, r__destination_dataExtension_key
|
|
283
|
+
// technically, the API allows changing the reference to the dataFilter but the GUI does not.
|
|
284
|
+
// the API and GUI prevent changes to the source & destination data extensions.
|
|
285
|
+
// to avoid confusion and accidental changes, we will reset the values from cache before deployment
|
|
286
|
+
const normalizedKey = File.reverseFilterIllegalFilenames(
|
|
287
|
+
metadata[this.definition.keyField]
|
|
288
|
+
);
|
|
289
|
+
const cachedVersion = cache.getByKey(this.definition.type, normalizedKey);
|
|
290
|
+
|
|
291
|
+
// filterDefinition
|
|
292
|
+
if (metadata.r__dataFilter_key) {
|
|
293
|
+
metadata.filterDefinitionId = cache.searchForField(
|
|
294
|
+
'dataFilter',
|
|
295
|
+
metadata.r__dataFilter_key,
|
|
296
|
+
'key',
|
|
297
|
+
'id'
|
|
298
|
+
);
|
|
299
|
+
if (cachedVersion && cachedVersion.filterDefinitionId !== metadata.filterDefinitionId) {
|
|
300
|
+
throw new Error(
|
|
301
|
+
`Updating r__dataFilter_key is not allowed. You need to delete and re-create the filter to change this.`
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
delete metadata.r__dataFilter_key;
|
|
305
|
+
}
|
|
306
|
+
if (!metadata.description) {
|
|
307
|
+
metadata.description = '';
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
metadata.resultGroupFolderId = null;
|
|
311
|
+
metadata.sourceId = null;
|
|
312
|
+
|
|
313
|
+
this._preDeploy_dataTypeMapping('source', metadata, cachedVersion);
|
|
314
|
+
this._preDeploy_dataTypeMapping('destination', metadata, cachedVersion);
|
|
315
|
+
|
|
316
|
+
return metadata;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* helper to allow us to select single metadata entries via REST
|
|
321
|
+
*
|
|
322
|
+
* @private
|
|
323
|
+
* @param {string} key customer key
|
|
324
|
+
* @returns {Promise.<string>} objectId or empty string
|
|
325
|
+
*/
|
|
326
|
+
static async _getObjectIdForSingleRetrieve(key) {
|
|
327
|
+
const name = key.startsWith('name:') ? key.slice(5) : null;
|
|
328
|
+
const response = await this.client.soap.retrieve(this.definition.soapType, ['ObjectID'], {
|
|
329
|
+
filter: {
|
|
330
|
+
leftOperand: name ? 'Name' : 'CustomerKey',
|
|
331
|
+
operator: 'equals',
|
|
332
|
+
rightOperand: name || key,
|
|
333
|
+
},
|
|
334
|
+
});
|
|
335
|
+
return response?.Results?.length ? response.Results[0].ObjectID : '';
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Delete a metadata item from the specified business unit
|
|
340
|
+
*
|
|
341
|
+
* @param {string} key Identifier of data extension
|
|
342
|
+
* @returns {Promise.<boolean>} deletion success flag
|
|
343
|
+
*/
|
|
344
|
+
static async deleteByKey(key) {
|
|
345
|
+
// delete only works with the query's object id
|
|
346
|
+
const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : null;
|
|
347
|
+
if (!objectId) {
|
|
348
|
+
await this.deleteNotFound(key);
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
return super.deleteByKeyREST('/automation/v1/filters/' + objectId, key);
|
|
38
352
|
}
|
|
39
353
|
}
|
|
40
354
|
|
|
@@ -57,12 +57,22 @@ class ImportFile extends MetadataType {
|
|
|
57
57
|
);
|
|
58
58
|
this.smsImports = {};
|
|
59
59
|
if (smsImportResults.totalResults > 0 && smsImportResults.entry.length > 0) {
|
|
60
|
-
|
|
60
|
+
if (smsImportResults.entry.filter((item) => !!item.sourceObjectId).length > 0) {
|
|
61
|
+
// imports from data extensions require additional information (item.sourceFile != '_CustomObject' and item.sourceObjectId is not set)
|
|
62
|
+
Util.logger.info(
|
|
63
|
+
Util.getGrayMsg(
|
|
64
|
+
` - Caching dependent Metadata: dataExtension (source for SMS imports)`
|
|
65
|
+
)
|
|
66
|
+
);
|
|
67
|
+
}
|
|
61
68
|
const sourceObject = {};
|
|
62
69
|
for (const item of smsImportResults.entry) {
|
|
63
70
|
// this api does not show the key but the name is assumed to be unique
|
|
64
71
|
this.smsImports[item.name] = item;
|
|
65
72
|
|
|
73
|
+
if (!item.sourceObjectId) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
66
76
|
try {
|
|
67
77
|
if (!sourceObject[item.sourceObjectId]) {
|
|
68
78
|
sourceObject[item.sourceObjectId] = await this.client.rest.get(
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import MetadataType from './MetadataType.js';
|
|
4
4
|
import TransactionalEmail from './TransactionalEmail.js';
|
|
5
|
+
import DataExtensionField from './DataExtensionField.js';
|
|
5
6
|
import TriggeredSend from './TriggeredSend.js';
|
|
6
7
|
import Event from './Event.js';
|
|
7
8
|
import { Util } from '../util/util.js';
|
|
@@ -512,7 +513,7 @@ class Journey extends MetadataType {
|
|
|
512
513
|
}
|
|
513
514
|
// ~~~ ACTIVITIES ~~~~
|
|
514
515
|
|
|
515
|
-
this._postRetrieveTasks_activities(metadata);
|
|
516
|
+
await this._postRetrieveTasks_activities(metadata);
|
|
516
517
|
|
|
517
518
|
// TODO: journey template id? / metaData.templateId
|
|
518
519
|
break;
|
|
@@ -581,7 +582,7 @@ class Journey extends MetadataType {
|
|
|
581
582
|
delete activity.metaData.highThroughput.definitionKey;
|
|
582
583
|
}
|
|
583
584
|
|
|
584
|
-
this._postRetrieveTasks_activities(metadata);
|
|
585
|
+
await this._postRetrieveTasks_activities(metadata);
|
|
585
586
|
|
|
586
587
|
if (activity.metaData?.highThroughput?.dataExtensionId) {
|
|
587
588
|
try {
|
|
@@ -639,7 +640,7 @@ class Journey extends MetadataType {
|
|
|
639
640
|
* @private
|
|
640
641
|
* @param {MetadataTypeItem} metadata a single item
|
|
641
642
|
*/
|
|
642
|
-
static _postRetrieveTasks_activities(metadata) {
|
|
643
|
+
static async _postRetrieveTasks_activities(metadata) {
|
|
643
644
|
if (!metadata.activities) {
|
|
644
645
|
return;
|
|
645
646
|
}
|
|
@@ -1239,6 +1240,58 @@ class Journey extends MetadataType {
|
|
|
1239
1240
|
}
|
|
1240
1241
|
break;
|
|
1241
1242
|
}
|
|
1243
|
+
case 'UPDATECONTACTDATA': {
|
|
1244
|
+
const contactFields =
|
|
1245
|
+
activity?.arguments?.activityData?.updateContactFields ?? [];
|
|
1246
|
+
let tempCachedFields = false;
|
|
1247
|
+
for (const contactField of contactFields) {
|
|
1248
|
+
try {
|
|
1249
|
+
contactField.r__dataExtension_key = cache.searchForField(
|
|
1250
|
+
'dataExtension',
|
|
1251
|
+
contactField.dataExtensionId,
|
|
1252
|
+
'ObjectID',
|
|
1253
|
+
'CustomerKey'
|
|
1254
|
+
);
|
|
1255
|
+
delete contactField.dataExtensionId;
|
|
1256
|
+
} catch (ex) {
|
|
1257
|
+
Util.logger.warn(
|
|
1258
|
+
` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${
|
|
1259
|
+
metadata[this.definition.keyField]
|
|
1260
|
+
}) activity-key=${activity.key}: ${ex.message}`
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1263
|
+
// Don't replace the field Id with the name if DE CustomerKey was not found
|
|
1264
|
+
try {
|
|
1265
|
+
if (!cache.getCache().dataExtensionField) {
|
|
1266
|
+
tempCachedFields = true;
|
|
1267
|
+
DataExtensionField.buObject = this.buObject;
|
|
1268
|
+
DataExtensionField.client = this.client;
|
|
1269
|
+
DataExtensionField.properties = this.properties;
|
|
1270
|
+
const fields = await DataExtensionField.retrieveFieldsForSingleDe(
|
|
1271
|
+
contactField.r__dataExtension_key
|
|
1272
|
+
);
|
|
1273
|
+
cache.setMetadata('dataExtensionField', fields);
|
|
1274
|
+
}
|
|
1275
|
+
contactField.r__dataExtensionField_name = cache.searchForField(
|
|
1276
|
+
'dataExtensionField',
|
|
1277
|
+
contactField.field,
|
|
1278
|
+
'ObjectID',
|
|
1279
|
+
'Name'
|
|
1280
|
+
);
|
|
1281
|
+
delete contactField.field;
|
|
1282
|
+
} catch (ex) {
|
|
1283
|
+
Util.logger.warn(
|
|
1284
|
+
` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${
|
|
1285
|
+
metadata[this.definition.keyField]
|
|
1286
|
+
}) activity-key=${activity.key}: ${ex.message}`
|
|
1287
|
+
);
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
if (tempCachedFields) {
|
|
1291
|
+
// reset dataExtensionField caching to trigger re-caching
|
|
1292
|
+
cache.clearCache(this.buObject.mid, 'dataExtensionField');
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1242
1295
|
}
|
|
1243
1296
|
}
|
|
1244
1297
|
|
|
@@ -1310,7 +1363,7 @@ class Journey extends MetadataType {
|
|
|
1310
1363
|
|
|
1311
1364
|
// ~~~ ACTIVITIES ~~~~
|
|
1312
1365
|
|
|
1313
|
-
this._preDeployTasks_activities(metadata);
|
|
1366
|
+
await this._preDeployTasks_activities(metadata);
|
|
1314
1367
|
|
|
1315
1368
|
break;
|
|
1316
1369
|
}
|
|
@@ -1338,7 +1391,7 @@ class Journey extends MetadataType {
|
|
|
1338
1391
|
cachedVersion.status = 'Paused';
|
|
1339
1392
|
} else {
|
|
1340
1393
|
throw new Error(
|
|
1341
|
-
`Cannot update transactional-send journey in Published status. Run
|
|
1394
|
+
`Cannot update transactional-send journey in Published status. Run deploy with --publish to auto-pause & republish the journey.`
|
|
1342
1395
|
);
|
|
1343
1396
|
}
|
|
1344
1397
|
}
|
|
@@ -1404,7 +1457,7 @@ class Journey extends MetadataType {
|
|
|
1404
1457
|
delete activity.metaData.highThroughput.r__dataExtension_key;
|
|
1405
1458
|
}
|
|
1406
1459
|
|
|
1407
|
-
this._preDeployTasks_activities(metadata);
|
|
1460
|
+
await this._preDeployTasks_activities(metadata);
|
|
1408
1461
|
|
|
1409
1462
|
break;
|
|
1410
1463
|
}
|
|
@@ -1433,7 +1486,7 @@ class Journey extends MetadataType {
|
|
|
1433
1486
|
* @private
|
|
1434
1487
|
* @param {MetadataTypeItem} metadata a single item
|
|
1435
1488
|
*/
|
|
1436
|
-
static _preDeployTasks_activities(metadata) {
|
|
1489
|
+
static async _preDeployTasks_activities(metadata) {
|
|
1437
1490
|
for (const activity of metadata.activities) {
|
|
1438
1491
|
switch (activity.type) {
|
|
1439
1492
|
case 'EMAILV2': {
|
|
@@ -1666,6 +1719,57 @@ class Journey extends MetadataType {
|
|
|
1666
1719
|
|
|
1667
1720
|
break;
|
|
1668
1721
|
}
|
|
1722
|
+
case 'UPDATECONTACTDATA': {
|
|
1723
|
+
const contactFields =
|
|
1724
|
+
activity?.arguments?.activityData?.updateContactFields ?? [];
|
|
1725
|
+
let tempCachedFields = false;
|
|
1726
|
+
for (const contactField of contactFields) {
|
|
1727
|
+
try {
|
|
1728
|
+
contactField.dataExtensionId = cache.searchForField(
|
|
1729
|
+
'dataExtension',
|
|
1730
|
+
contactField.r__dataExtension_key,
|
|
1731
|
+
'CustomerKey',
|
|
1732
|
+
'ObjectID'
|
|
1733
|
+
);
|
|
1734
|
+
} catch (ex) {
|
|
1735
|
+
Util.logger.warn(
|
|
1736
|
+
` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${
|
|
1737
|
+
metadata[this.definition.keyField]
|
|
1738
|
+
}) activity-key=${activity.key}: ${ex.message}`
|
|
1739
|
+
);
|
|
1740
|
+
}
|
|
1741
|
+
try {
|
|
1742
|
+
if (!cache.getCache().dataExtensionField) {
|
|
1743
|
+
tempCachedFields = true;
|
|
1744
|
+
DataExtensionField.buObject = this.buObject;
|
|
1745
|
+
DataExtensionField.client = this.client;
|
|
1746
|
+
DataExtensionField.properties = this.properties;
|
|
1747
|
+
const fields = await DataExtensionField.retrieveFieldsForSingleDe(
|
|
1748
|
+
contactField.r__dataExtension_key
|
|
1749
|
+
);
|
|
1750
|
+
cache.setMetadata('dataExtensionField', fields);
|
|
1751
|
+
}
|
|
1752
|
+
contactField.field = cache.searchForField(
|
|
1753
|
+
'dataExtensionField',
|
|
1754
|
+
`[${contactField.r__dataExtension_key}].[${contactField.r__dataExtensionField_name}]`,
|
|
1755
|
+
'CustomerKey',
|
|
1756
|
+
'ObjectID'
|
|
1757
|
+
);
|
|
1758
|
+
delete contactField.r__dataExtensionField_name;
|
|
1759
|
+
delete contactField.r__dataExtension_key;
|
|
1760
|
+
} catch (ex) {
|
|
1761
|
+
Util.logger.warn(
|
|
1762
|
+
` - ${this.definition.type} '${metadata[this.definition.nameField]}'(${
|
|
1763
|
+
metadata[this.definition.keyField]
|
|
1764
|
+
}) activity - key=${activity.key}: ${ex.message} `
|
|
1765
|
+
);
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
if (tempCachedFields) {
|
|
1769
|
+
// reset dataExtensionField caching to trigger re-caching
|
|
1770
|
+
cache.clearCache(this.buObject.mid, 'dataExtensionField');
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1669
1773
|
}
|
|
1670
1774
|
}
|
|
1671
1775
|
}
|