mcdev 7.10.0 → 7.10.1
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/@types/lib/index.d.ts +4 -4
- package/@types/lib/index.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Asset.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Automation.d.ts +62 -51
- package/@types/lib/metadataTypes/Automation.d.ts.map +1 -1
- package/@types/lib/metadataTypes/DataExtract.d.ts +13 -2
- package/@types/lib/metadataTypes/DataExtract.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Event.d.ts +8 -0
- package/@types/lib/metadataTypes/Event.d.ts.map +1 -1
- package/@types/lib/metadataTypes/ImportFile.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Journey.d.ts.map +1 -1
- package/@types/lib/metadataTypes/MetadataType.d.ts +19 -3
- package/@types/lib/metadataTypes/MetadataType.d.ts.map +1 -1
- package/@types/lib/metadataTypes/MobileMessage.d.ts.map +1 -1
- package/@types/lib/metadataTypes/SenderProfile.d.ts +3 -1
- package/@types/lib/metadataTypes/SenderProfile.d.ts.map +1 -1
- package/@types/lib/metadataTypes/definitions/Automation.definition.d.ts +37 -1
- package/@types/lib/metadataTypes/definitions/DataExtract.definition.d.ts +21 -3
- package/@types/lib/metadataTypes/definitions/SenderProfile.definition.d.ts +3 -1
- package/@types/lib/util/util.d.ts +1 -0
- 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 +32 -0
- package/@types/types/mcdev.d.d.ts.map +1 -1
- package/lib/index.js +14 -7
- package/lib/metadataTypes/Asset.js +4 -5
- package/lib/metadataTypes/Automation.js +202 -399
- package/lib/metadataTypes/DataExtension.js +1 -1
- package/lib/metadataTypes/DataExtract.js +41 -6
- package/lib/metadataTypes/DomainVerification.js +1 -1
- package/lib/metadataTypes/EmailSend.js +3 -3
- package/lib/metadataTypes/Event.js +39 -20
- package/lib/metadataTypes/FileTransfer.js +5 -5
- package/lib/metadataTypes/ImportFile.js +9 -7
- package/lib/metadataTypes/Journey.js +4 -9
- package/lib/metadataTypes/MetadataType.js +80 -58
- package/lib/metadataTypes/MobileKeyword.js +2 -2
- package/lib/metadataTypes/MobileMessage.js +4 -2
- package/lib/metadataTypes/Query.js +5 -5
- package/lib/metadataTypes/Script.js +5 -5
- package/lib/metadataTypes/SendClassification.js +3 -3
- package/lib/metadataTypes/SenderProfile.js +3 -3
- package/lib/metadataTypes/TransactionalEmail.js +1 -1
- package/lib/metadataTypes/TransactionalMessage.js +1 -1
- package/lib/metadataTypes/TriggeredSend.js +3 -3
- package/lib/metadataTypes/Verification.js +1 -1
- package/lib/metadataTypes/definitions/Automation.definition.js +43 -7
- package/lib/metadataTypes/definitions/DataExtract.definition.js +16 -3
- package/lib/metadataTypes/definitions/DomainVerification.definition.js +1 -1
- package/lib/metadataTypes/definitions/SenderProfile.definition.js +3 -1
- package/lib/util/util.js +12 -0
- package/lib/util/validations.js +3 -1
- package/package.json +1 -1
- package/test/general.test.js +39 -34
- package/test/mockRoot/.mcdevrc.json +1 -1
- package/test/resourceFactory.js +8 -5
- package/test/resources/9999999/automation/create-expected.json +2 -1
- package/test/resources/9999999/automation/retrieve-expected.json +7 -1
- package/test/resources/9999999/automation/retrieve-wait-expected.json +7 -1
- package/test/resources/9999999/automation/update-expected.json +24 -2
- package/test/resources/9999999/automation/update-testExisting_automation-expected.md +5 -2
- package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_pause/patch-response.json +1 -0
- package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_schedule/patch-response.json +1 -0
- package/test/resources/9999999/dataExtract/build-expected.json +2 -2
- package/test/resources/9999999/dataExtract/get-expected.json +2 -2
- package/test/resources/9999999/dataExtract/patch-expected.json +2 -2
- package/test/resources/9999999/dataExtract/post-expected.json +2 -2
- package/test/resources/9999999/dataExtract/template-expected.json +2 -2
- package/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow-PAUSED/get-response.json +3 -0
- package/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/NewRkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/get-response.json +29 -0
- package/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/get-response.json +50 -0
- package/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow-PAUSED/get-response.json +51 -0
- package/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/bHF6Q0Q3b1VXa21OdVQzZFQ0ckVSQToyNTow/get-response.json +7 -1
- package/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/cDhLQ2o2NExxVVc5N3VZeHF5WEExUToyNTow/get-response.json +79 -0
- package/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/get-response.json +61 -2
- package/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/post-response-pauseSchedule.json +1 -0
- package/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/post-response-schedule.json +1 -0
- package/test/resources/9999999/messaging/v1/domainverification/get-response.json +10 -1
- package/test/resources/9999999/senderProfile/build-expected.json +1 -1
- package/test/resources/9999999/senderProfile/get-expected.json +1 -1
- package/test/resources/9999999/senderProfile/patch-expected.json +1 -1
- package/test/resources/9999999/senderProfile/retrieve-response.xml +1 -1
- package/test/resources/9999999/senderProfile/template-expected.json +1 -1
- package/test/type.automation.test.js +18 -17
- package/test/type.dataExtract.test.js +4 -4
- package/test/type.domainVerification.test.js +3 -3
- package/test/type.journey.test.js +11 -4
- package/test/type.query.test.js +2 -2
- package/test/type.script.test.js +1 -1
- package/test/type.senderProfile.test.js +20 -3
- package/test/type.triggeredSend.test.js +13 -1
- package/types/mcdev.d.js +8 -0
- package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml +0 -52
- package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-ad2e-pause-response.xml +0 -38
- package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-fixKey_pause-response.xml +0 -52
- package/test/resources/9999999/automation/schedule-08afb0e2-b00a-4c88-fixKey_schedule-response.xml +0 -52
- package/test/resources/9999999/automation/schedule-a8afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml +0 -52
|
@@ -1476,7 +1476,7 @@ class DataExtension extends MetadataType {
|
|
|
1476
1476
|
* @returns {Promise.<boolean>} deletion success status
|
|
1477
1477
|
*/
|
|
1478
1478
|
static deleteByKey(customerKey) {
|
|
1479
|
-
return super.deleteByKeySOAP(customerKey);
|
|
1479
|
+
return super.deleteByKeySOAP(customerKey, undefined, 310007);
|
|
1480
1480
|
}
|
|
1481
1481
|
|
|
1482
1482
|
/**
|
|
@@ -129,6 +129,21 @@ class DataExtract extends MetadataType {
|
|
|
129
129
|
* @returns {MetadataTypeItem} metadata object
|
|
130
130
|
*/
|
|
131
131
|
static preDeployTasks(metadata) {
|
|
132
|
+
// dataExtension
|
|
133
|
+
if (metadata.r__dataExtension_key) {
|
|
134
|
+
const deField = metadata.dataFields.find((field) => field.name === 'DECustomerKey');
|
|
135
|
+
if (deField) {
|
|
136
|
+
deField.value = cache.searchForField(
|
|
137
|
+
'dataExtension',
|
|
138
|
+
metadata.r__dataExtension_key,
|
|
139
|
+
'CustomerKey',
|
|
140
|
+
'CustomerKey'
|
|
141
|
+
);
|
|
142
|
+
delete metadata.r__dataExtension_key;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// dataExtractType
|
|
132
147
|
metadata.dataExtractTypeId = cache.searchForField(
|
|
133
148
|
'dataExtractType',
|
|
134
149
|
metadata.r__dataExtractType_name,
|
|
@@ -166,6 +181,7 @@ class DataExtract extends MetadataType {
|
|
|
166
181
|
* @returns {MetadataTypeItem} metadata
|
|
167
182
|
*/
|
|
168
183
|
static postRetrieveTasks(metadata) {
|
|
184
|
+
// user
|
|
169
185
|
try {
|
|
170
186
|
metadata.createdBy = cache.searchForField(
|
|
171
187
|
'user',
|
|
@@ -195,6 +211,25 @@ class DataExtract extends MetadataType {
|
|
|
195
211
|
}): ${ex.message}.`
|
|
196
212
|
);
|
|
197
213
|
}
|
|
214
|
+
// dataExtension
|
|
215
|
+
const deField = metadata.dataFields.find((field) => field.name === 'DECustomerKey');
|
|
216
|
+
if (deField && deField.value) {
|
|
217
|
+
try {
|
|
218
|
+
metadata.r__dataExtension_key = cache.searchForField(
|
|
219
|
+
'dataExtension',
|
|
220
|
+
deField.value,
|
|
221
|
+
'CustomerKey',
|
|
222
|
+
'CustomerKey'
|
|
223
|
+
);
|
|
224
|
+
delete deField.value;
|
|
225
|
+
} catch (ex) {
|
|
226
|
+
Util.logger.warn(
|
|
227
|
+
` - ${this.definition.type} ${metadata[this.definition.keyField]}: ${ex.message}`
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// dataExtractType
|
|
198
233
|
try {
|
|
199
234
|
metadata.r__dataExtractType_name = cache.searchForField(
|
|
200
235
|
'dataExtractType',
|
|
@@ -208,7 +243,7 @@ class DataExtract extends MetadataType {
|
|
|
208
243
|
` - ${this.definition.type} ${metadata[this.definition.keyField]}: ${ex.message}`
|
|
209
244
|
);
|
|
210
245
|
}
|
|
211
|
-
return
|
|
246
|
+
return metadata;
|
|
212
247
|
}
|
|
213
248
|
|
|
214
249
|
/**
|
|
@@ -232,17 +267,17 @@ class DataExtract extends MetadataType {
|
|
|
232
267
|
/**
|
|
233
268
|
* Delete a metadata item from the specified business unit
|
|
234
269
|
*
|
|
235
|
-
* @param {string}
|
|
270
|
+
* @param {string} key Identifier of data extension
|
|
236
271
|
* @returns {Promise.<boolean>} deletion success flag
|
|
237
272
|
*/
|
|
238
|
-
static async deleteByKey(
|
|
273
|
+
static async deleteByKey(key) {
|
|
239
274
|
// delete only works with the query's object id
|
|
240
|
-
const objectId =
|
|
275
|
+
const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : null;
|
|
241
276
|
if (!objectId) {
|
|
242
|
-
|
|
277
|
+
await this.deleteNotFound(key);
|
|
243
278
|
return false;
|
|
244
279
|
}
|
|
245
|
-
return super.deleteByKeyREST('/automation/v1/dataextracts/' + objectId,
|
|
280
|
+
return super.deleteByKeyREST('/automation/v1/dataextracts/' + objectId, key);
|
|
246
281
|
}
|
|
247
282
|
}
|
|
248
283
|
|
|
@@ -262,7 +262,7 @@ class DomainVerification extends MetadataType {
|
|
|
262
262
|
static async deleteByKey(key) {
|
|
263
263
|
const metadataItem = cache.getByKey(this.definition.type, key);
|
|
264
264
|
if (!metadataItem) {
|
|
265
|
-
|
|
265
|
+
await this.deleteNotFound(key);
|
|
266
266
|
return false;
|
|
267
267
|
}
|
|
268
268
|
if (metadataItem.domainType !== 'UserDomain') {
|
|
@@ -90,11 +90,11 @@ class EmailSend extends MetadataType {
|
|
|
90
90
|
/**
|
|
91
91
|
* Delete a metadata item from the specified business unit
|
|
92
92
|
*
|
|
93
|
-
* @param {string}
|
|
93
|
+
* @param {string} key Identifier of data extension
|
|
94
94
|
* @returns {Promise.<boolean>} deletion success status
|
|
95
95
|
*/
|
|
96
|
-
static deleteByKey(
|
|
97
|
-
return super.deleteByKeySOAP(
|
|
96
|
+
static deleteByKey(key) {
|
|
97
|
+
return super.deleteByKeySOAP(key, undefined, 42002);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
/**
|
|
@@ -141,26 +141,11 @@ class Event extends MetadataType {
|
|
|
141
141
|
* @returns {Promise.<boolean>} deletion success status
|
|
142
142
|
*/
|
|
143
143
|
static async deleteByKey(key) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
true
|
|
150
|
-
);
|
|
151
|
-
Util.logger.info(` - deleted ${this.definition.type}: ${key}`);
|
|
152
|
-
} catch (ex) {
|
|
153
|
-
if (ex.code === 30000) {
|
|
154
|
-
Util.logger.warn(
|
|
155
|
-
` ☇ skipping deletion of ${this.definition.type} ${key}: not found on server`
|
|
156
|
-
);
|
|
157
|
-
} else {
|
|
158
|
-
Util.logger.errorStack(ex, ` - Deleting ${this.definition.type} '${key}' failed`);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
163
|
-
return response;
|
|
144
|
+
return await super.deleteByKeyREST(
|
|
145
|
+
'/interaction/v1/eventDefinitions/key:' + encodeURIComponent(key),
|
|
146
|
+
key,
|
|
147
|
+
30000
|
|
148
|
+
);
|
|
164
149
|
}
|
|
165
150
|
|
|
166
151
|
/**
|
|
@@ -369,8 +354,20 @@ class Event extends MetadataType {
|
|
|
369
354
|
}
|
|
370
355
|
if (!deFound) {
|
|
371
356
|
if (metadataItem.r__dataExtension_key) {
|
|
357
|
+
if (!metadataItem.schema) {
|
|
358
|
+
// make sure we skip this item
|
|
359
|
+
this.removeFromDeployment(metadataKey, metadataToUpdate, metadataToCreate);
|
|
360
|
+
throw new Error(
|
|
361
|
+
`related dataExtension ${metadataItem.r__dataExtension_key} not found`
|
|
362
|
+
);
|
|
363
|
+
}
|
|
372
364
|
metadataItem.schema.name = metadataItem.r__dataExtension_key;
|
|
373
365
|
}
|
|
366
|
+
if (!metadataItem.schema) {
|
|
367
|
+
this.removeFromDeployment(metadataKey, metadataToUpdate, metadataToCreate);
|
|
368
|
+
throw new Error(`no related dataExtension and no schema found`);
|
|
369
|
+
}
|
|
370
|
+
|
|
374
371
|
Util.logger.warn(
|
|
375
372
|
`Data Extension ${metadataItem.schema.name || metadataItem[this.definition.keyField]} not found on BU. Creating it automatically based on schema-definition.`
|
|
376
373
|
);
|
|
@@ -384,6 +381,28 @@ class Event extends MetadataType {
|
|
|
384
381
|
return createOrUpdateAction;
|
|
385
382
|
}
|
|
386
383
|
|
|
384
|
+
/**
|
|
385
|
+
* helper for {@link createOrUpdate}
|
|
386
|
+
*
|
|
387
|
+
* @param {string} metadataKey key of item we are looking at
|
|
388
|
+
* @param {MetadataTypeItemDiff[]} metadataToUpdate list of items to update
|
|
389
|
+
* @param {MetadataTypeItem[]} metadataToCreate list of items to create
|
|
390
|
+
*/
|
|
391
|
+
static removeFromDeployment(metadataKey, metadataToUpdate, metadataToCreate) {
|
|
392
|
+
const removeUpdate = metadataToUpdate.findIndex(
|
|
393
|
+
(el) => el.after[this.definition.keyField] === metadataKey
|
|
394
|
+
);
|
|
395
|
+
if (removeUpdate !== -1) {
|
|
396
|
+
metadataToUpdate.splice(removeUpdate, 1);
|
|
397
|
+
}
|
|
398
|
+
const removeCreate = metadataToCreate.findIndex(
|
|
399
|
+
(el) => el[this.definition.keyField] === metadataKey
|
|
400
|
+
);
|
|
401
|
+
if (removeCreate !== -1) {
|
|
402
|
+
metadataToCreate.splice(removeCreate, 1);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
387
406
|
/**
|
|
388
407
|
* Gets executed after deployment of metadata type
|
|
389
408
|
*
|
|
@@ -187,17 +187,17 @@ class FileTransfer extends MetadataType {
|
|
|
187
187
|
/**
|
|
188
188
|
* Delete a metadata item from the specified business unit
|
|
189
189
|
*
|
|
190
|
-
* @param {string}
|
|
190
|
+
* @param {string} key Identifier of data extension
|
|
191
191
|
* @returns {Promise.<boolean>} deletion success flag
|
|
192
192
|
*/
|
|
193
|
-
static async deleteByKey(
|
|
193
|
+
static async deleteByKey(key) {
|
|
194
194
|
// delete only works with the query's object id
|
|
195
|
-
const objectId =
|
|
195
|
+
const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : null;
|
|
196
196
|
if (!objectId) {
|
|
197
|
-
|
|
197
|
+
await this.deleteNotFound(key);
|
|
198
198
|
return false;
|
|
199
199
|
}
|
|
200
|
-
return super.deleteByKeyREST('/automation/v1/filetransfers/' + objectId,
|
|
200
|
+
return super.deleteByKeyREST('/automation/v1/filetransfers/' + objectId, key);
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
203
|
|
|
@@ -228,9 +228,11 @@ class ImportFile extends MetadataType {
|
|
|
228
228
|
* @returns {Promise.<MetadataTypeItem>} Promise
|
|
229
229
|
*/
|
|
230
230
|
static async preDeployTasks(metadata) {
|
|
231
|
-
const fileLocation = cache.getByKey('fileLocation', metadata.source
|
|
231
|
+
const fileLocation = cache.getByKey('fileLocation', metadata.source?.r__fileLocation_name);
|
|
232
232
|
if (!fileLocation) {
|
|
233
|
-
throw new Error(
|
|
233
|
+
throw new Error(
|
|
234
|
+
`fileLocation ${metadata.source?.r__fileLocation_name} not found in cache`
|
|
235
|
+
);
|
|
234
236
|
}
|
|
235
237
|
|
|
236
238
|
metadata.fileTransferLocationId = fileLocation.id;
|
|
@@ -512,17 +514,17 @@ class ImportFile extends MetadataType {
|
|
|
512
514
|
/**
|
|
513
515
|
* Delete a metadata item from the specified business unit
|
|
514
516
|
*
|
|
515
|
-
* @param {string}
|
|
517
|
+
* @param {string} key Identifier of data extension
|
|
516
518
|
* @returns {Promise.<boolean>} deletion success flag
|
|
517
519
|
*/
|
|
518
|
-
static async deleteByKey(
|
|
520
|
+
static async deleteByKey(key) {
|
|
519
521
|
// delete only works with the query's object id
|
|
520
|
-
const objectId =
|
|
522
|
+
const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : null;
|
|
521
523
|
if (!objectId) {
|
|
522
|
-
|
|
524
|
+
await this.deleteNotFound(key);
|
|
523
525
|
return false;
|
|
524
526
|
}
|
|
525
|
-
return super.deleteByKeyREST('/automation/v1/imports/' + objectId,
|
|
527
|
+
return super.deleteByKeyREST('/automation/v1/imports/' + objectId, key);
|
|
526
528
|
}
|
|
527
529
|
}
|
|
528
530
|
|
|
@@ -256,9 +256,7 @@ class Journey extends MetadataType {
|
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
if (!cachedJourney?.key) {
|
|
259
|
-
|
|
260
|
-
` ☇ skipping deletion of ${this.definition.type} ${key}: not found on server`
|
|
261
|
-
);
|
|
259
|
+
await this.deleteNotFound(key);
|
|
262
260
|
return false;
|
|
263
261
|
}
|
|
264
262
|
switch (cachedJourney.definitionType) {
|
|
@@ -287,8 +285,7 @@ class Journey extends MetadataType {
|
|
|
287
285
|
'/interaction/v1/interactions/' +
|
|
288
286
|
id +
|
|
289
287
|
(version === '*' ? '' : `?versionNumber=${version}`),
|
|
290
|
-
key
|
|
291
|
-
false
|
|
288
|
+
key
|
|
292
289
|
);
|
|
293
290
|
// break;
|
|
294
291
|
}
|
|
@@ -296,8 +293,7 @@ class Journey extends MetadataType {
|
|
|
296
293
|
// Quicksend doesnt have versions
|
|
297
294
|
const isDeleted = await super.deleteByKeyREST(
|
|
298
295
|
'/interaction/v1/interactions/' + id,
|
|
299
|
-
key
|
|
300
|
-
false
|
|
296
|
+
key
|
|
301
297
|
);
|
|
302
298
|
return isDeleted;
|
|
303
299
|
}
|
|
@@ -305,8 +301,7 @@ class Journey extends MetadataType {
|
|
|
305
301
|
// Transactional dont have versions
|
|
306
302
|
const isDeleted = await super.deleteByKeyREST(
|
|
307
303
|
'/interaction/v1/interactions/' + id,
|
|
308
|
-
key
|
|
309
|
-
false
|
|
304
|
+
key
|
|
310
305
|
);
|
|
311
306
|
const transactionalEmailKey =
|
|
312
307
|
cachedJourney.activities[0]?.configurationArguments?.triggeredSendKey;
|
|
@@ -157,7 +157,7 @@ class MetadataType {
|
|
|
157
157
|
) {
|
|
158
158
|
// * do not await here as this might take a while and has no impact on the deploy
|
|
159
159
|
// * 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
|
|
160
|
-
this.document(savedMetadataMap, true);
|
|
160
|
+
await this.document(savedMetadataMap, true);
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
return upsertedMetadataMap;
|
|
@@ -299,8 +299,7 @@ class MetadataType {
|
|
|
299
299
|
* @returns {Promise.<MetadataTypeMapObj>} metadata
|
|
300
300
|
*/
|
|
301
301
|
static async retrieve(retrieveDir, additionalFields, subTypeArr, key) {
|
|
302
|
-
Util.
|
|
303
|
-
const metadata = {};
|
|
302
|
+
Util.notSupportedError(this.definition, 'retrieve');
|
|
304
303
|
return { metadata: {}, type: this.definition.type };
|
|
305
304
|
}
|
|
306
305
|
|
|
@@ -337,13 +336,7 @@ class MetadataType {
|
|
|
337
336
|
* @returns {Promise.<MetadataTypeItemObj>} metadata
|
|
338
337
|
*/
|
|
339
338
|
static async retrieveAsTemplate(templateDir, name, templateVariables, subType) {
|
|
340
|
-
Util.
|
|
341
|
-
Util.metadataLogger(
|
|
342
|
-
'debug',
|
|
343
|
-
this.definition.type,
|
|
344
|
-
'retrieveAsTemplate',
|
|
345
|
-
`(${templateDir}, ${name}, ${templateVariables}) no templating function`
|
|
346
|
-
);
|
|
339
|
+
Util.notSupportedError(this.definition, 'retrieveAsTemplate');
|
|
347
340
|
return { metadata: null, type: this.definition.type };
|
|
348
341
|
}
|
|
349
342
|
|
|
@@ -506,9 +499,7 @@ class MetadataType {
|
|
|
506
499
|
* @returns {Promise.<object> | null} Promise of API response or null in case of an error
|
|
507
500
|
*/
|
|
508
501
|
static async create(metadata, deployDir) {
|
|
509
|
-
Util.
|
|
510
|
-
` ☇ skipping ${Util.getTypeKeyName(this.definition, metadata)}: create is not supported yet for ${this.definition.type}`
|
|
511
|
-
);
|
|
502
|
+
Util.notSupportedError(this.definition, 'retrieveAsTemplate', metadata);
|
|
512
503
|
return;
|
|
513
504
|
}
|
|
514
505
|
|
|
@@ -520,9 +511,7 @@ class MetadataType {
|
|
|
520
511
|
* @returns {Promise.<object> | null} Promise of API response or null in case of an error
|
|
521
512
|
*/
|
|
522
513
|
static async update(metadata, metadataBefore) {
|
|
523
|
-
Util.
|
|
524
|
-
` ☇ skipping ${Util.getTypeKeyName(this.definition, metadata)}: update is not supported yet for ${this.definition.type}`
|
|
525
|
-
);
|
|
514
|
+
Util.notSupportedError(this.definition, 'retrieveAsTemplate', metadata);
|
|
526
515
|
return;
|
|
527
516
|
}
|
|
528
517
|
|
|
@@ -535,9 +524,7 @@ class MetadataType {
|
|
|
535
524
|
* @returns {Promise.<string[]>} Returns list of keys that were refreshed
|
|
536
525
|
*/
|
|
537
526
|
static async refresh(keyArr, checkKey = true, upsertResults) {
|
|
538
|
-
Util.
|
|
539
|
-
` ☇ skipping ${this.definition.type}: refresh is not supported yet for ${this.definition.type}`
|
|
540
|
-
);
|
|
527
|
+
Util.notSupportedError(this.definition, 'refresh');
|
|
541
528
|
return [];
|
|
542
529
|
}
|
|
543
530
|
|
|
@@ -643,9 +630,7 @@ class MetadataType {
|
|
|
643
630
|
* @returns {Promise.<MetadataTypeItem | CodeExtractItem>} key of the item that was updated
|
|
644
631
|
*/
|
|
645
632
|
static async replaceCbReference(item, retrieveDir, findAssetKeys) {
|
|
646
|
-
Util.
|
|
647
|
-
` ☇ skipping ${this.definition.type}: replaceCbReference is not supported yet for ${this.definition.type}`
|
|
648
|
-
);
|
|
633
|
+
Util.notSupportedError(this.definition, 'replaceCbReference');
|
|
649
634
|
return [];
|
|
650
635
|
}
|
|
651
636
|
|
|
@@ -657,9 +642,19 @@ class MetadataType {
|
|
|
657
642
|
* @returns {Promise.<string[]>} Returns list of keys that were executed
|
|
658
643
|
*/
|
|
659
644
|
static async execute(keyArr, cache) {
|
|
660
|
-
Util.
|
|
661
|
-
|
|
662
|
-
|
|
645
|
+
Util.notSupportedError(this.definition, 'execute');
|
|
646
|
+
return [];
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Abstract schedule method that needs to be implemented in child metadata type
|
|
651
|
+
*
|
|
652
|
+
* @param {string[]} keyArr customerkey of the metadata
|
|
653
|
+
* @param {MetadataTypeMapObj} [cache] metadata cache used by refresh to avoid recaching
|
|
654
|
+
* @returns {Promise.<string[]>} Returns list of keys that were executed
|
|
655
|
+
*/
|
|
656
|
+
static async schedule(keyArr, cache) {
|
|
657
|
+
Util.notSupportedError(this.definition, 'schedule');
|
|
663
658
|
return [];
|
|
664
659
|
}
|
|
665
660
|
|
|
@@ -671,9 +666,7 @@ class MetadataType {
|
|
|
671
666
|
* @returns {Promise.<string[]>} Returns list of keys that were paused
|
|
672
667
|
*/
|
|
673
668
|
static async pause(keyArr, cache) {
|
|
674
|
-
Util.
|
|
675
|
-
` ☇ skipping ${this.definition.type}: pause is not supported yet for ${this.definition.type}`
|
|
676
|
-
);
|
|
669
|
+
Util.notSupportedError(this.definition, 'pause');
|
|
677
670
|
return [];
|
|
678
671
|
}
|
|
679
672
|
|
|
@@ -684,9 +677,7 @@ class MetadataType {
|
|
|
684
677
|
* @returns {Promise.<string[]>} Returns list of keys that were stopped
|
|
685
678
|
*/
|
|
686
679
|
static async stop(keyArr) {
|
|
687
|
-
Util.
|
|
688
|
-
` ☇ skipping ${this.definition.type}: stop is not supported yet for ${this.definition.type}`
|
|
689
|
-
);
|
|
680
|
+
Util.notSupportedError(this.definition, 'stop');
|
|
690
681
|
return [];
|
|
691
682
|
}
|
|
692
683
|
|
|
@@ -1493,7 +1484,7 @@ class MetadataType {
|
|
|
1493
1484
|
*/
|
|
1494
1485
|
static async retrieveRESTcollection(urlArray, concurrentRequests = 10, logAmountOfUrls = true) {
|
|
1495
1486
|
if (logAmountOfUrls) {
|
|
1496
|
-
Util.logger.
|
|
1487
|
+
Util.logger.debug(
|
|
1497
1488
|
Util.getGrayMsg(
|
|
1498
1489
|
` - ${urlArray?.length} ${this.definition.type}${
|
|
1499
1490
|
urlArray?.length === 1 ? '' : 's'
|
|
@@ -2341,6 +2332,17 @@ class MetadataType {
|
|
|
2341
2332
|
);
|
|
2342
2333
|
}
|
|
2343
2334
|
|
|
2335
|
+
// run validations before buildDefinitionForNested because that method writes extracted code to disk
|
|
2336
|
+
metadata = await this.validation(
|
|
2337
|
+
'buildDefinition',
|
|
2338
|
+
metadata,
|
|
2339
|
+
Array.isArray(targetDir) ? targetDir[0] : targetDir
|
|
2340
|
+
);
|
|
2341
|
+
if (!metadata) {
|
|
2342
|
+
// we encountered a situation in our validation that made us want to filter this record
|
|
2343
|
+
return;
|
|
2344
|
+
}
|
|
2345
|
+
|
|
2344
2346
|
// handle extracted code
|
|
2345
2347
|
// run after metadata was templated and converted into JS-object
|
|
2346
2348
|
// templating to extracted content is applied inside of buildDefinitionForNested()
|
|
@@ -2353,16 +2355,6 @@ class MetadataType {
|
|
|
2353
2355
|
);
|
|
2354
2356
|
|
|
2355
2357
|
try {
|
|
2356
|
-
metadata = await this.validation(
|
|
2357
|
-
'buildDefinition',
|
|
2358
|
-
metadata,
|
|
2359
|
-
Array.isArray(targetDir) ? targetDir[0] : targetDir
|
|
2360
|
-
);
|
|
2361
|
-
if (!metadata) {
|
|
2362
|
-
// we encountered a situation in our validation that made us want to filter this record
|
|
2363
|
-
return;
|
|
2364
|
-
}
|
|
2365
|
-
|
|
2366
2358
|
// write to file
|
|
2367
2359
|
const targetDirArr = Array.isArray(targetDir) ? targetDir : [targetDir];
|
|
2368
2360
|
for (const targetDir of targetDirArr) {
|
|
@@ -2446,7 +2438,7 @@ class MetadataType {
|
|
|
2446
2438
|
*/
|
|
2447
2439
|
static document(metadata, isDeploy) {
|
|
2448
2440
|
if (!isDeploy) {
|
|
2449
|
-
Util.
|
|
2441
|
+
Util.notSupportedError(this.definition, 'document');
|
|
2450
2442
|
}
|
|
2451
2443
|
}
|
|
2452
2444
|
|
|
@@ -2457,7 +2449,7 @@ class MetadataType {
|
|
|
2457
2449
|
* @returns {Promise.<{key:string, name:string}>} key, name and path of metadata; null if not found
|
|
2458
2450
|
*/
|
|
2459
2451
|
static async resolveId(id) {
|
|
2460
|
-
Util.
|
|
2452
|
+
Util.notSupportedError(this.definition, 'resolveId');
|
|
2461
2453
|
return;
|
|
2462
2454
|
}
|
|
2463
2455
|
|
|
@@ -2468,7 +2460,7 @@ class MetadataType {
|
|
|
2468
2460
|
* @returns {Promise.<boolean>} deletion success status
|
|
2469
2461
|
*/
|
|
2470
2462
|
static async deleteByKey(customerKey) {
|
|
2471
|
-
Util.
|
|
2463
|
+
Util.notSupportedError(this.definition, 'delete');
|
|
2472
2464
|
return false;
|
|
2473
2465
|
}
|
|
2474
2466
|
|
|
@@ -2497,26 +2489,33 @@ class MetadataType {
|
|
|
2497
2489
|
/**
|
|
2498
2490
|
* Delete a data extension from the specified business unit
|
|
2499
2491
|
*
|
|
2500
|
-
* @param {string}
|
|
2492
|
+
* @param {string} key Identifier of metadata
|
|
2501
2493
|
* @param {string} [overrideKeyField] optionally change the name of the key field if the api uses a different name
|
|
2494
|
+
* @param {number} [codeNotFound] error code that is responded with if the item was not found
|
|
2502
2495
|
* @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method
|
|
2503
2496
|
* @returns {Promise.<boolean>} deletion success flag
|
|
2504
2497
|
*/
|
|
2505
|
-
static async deleteByKeySOAP(
|
|
2498
|
+
static async deleteByKeySOAP(key, overrideKeyField, codeNotFound, handleOutside) {
|
|
2506
2499
|
const metadata = {};
|
|
2507
|
-
metadata[overrideKeyField || this.definition.keyField] =
|
|
2500
|
+
metadata[overrideKeyField || this.definition.keyField] = key;
|
|
2508
2501
|
const soapType = this.definition.soapType || this.definition.type;
|
|
2509
2502
|
try {
|
|
2510
2503
|
await this.client.soap.delete(Util.capitalizeFirstLetter(soapType), metadata, null);
|
|
2511
2504
|
if (!handleOutside) {
|
|
2512
|
-
Util.logger.info(` - deleted ${this.definition.type}: ${
|
|
2505
|
+
Util.logger.info(` - deleted ${this.definition.type}: ${key}`);
|
|
2513
2506
|
}
|
|
2514
|
-
this.postDeleteTasks(
|
|
2507
|
+
await this.postDeleteTasks(key);
|
|
2515
2508
|
|
|
2516
2509
|
return true;
|
|
2517
2510
|
} catch (ex) {
|
|
2518
2511
|
if (handleOutside) {
|
|
2519
2512
|
throw ex;
|
|
2513
|
+
} else if (
|
|
2514
|
+
codeNotFound &&
|
|
2515
|
+
(ex.results?.[0]?.ErrorCode == codeNotFound ||
|
|
2516
|
+
ex.json?.Results?.[0]?.ErrorCode == codeNotFound)
|
|
2517
|
+
) {
|
|
2518
|
+
await this.deleteNotFound(key);
|
|
2520
2519
|
} else {
|
|
2521
2520
|
const errorMsg = ex?.results?.length
|
|
2522
2521
|
? `${ex.results[0].StatusMessage} (Code ${ex.results[0].ErrorCode})`
|
|
@@ -2524,7 +2523,7 @@ class MetadataType {
|
|
|
2524
2523
|
? `${ex.json.Results[0].StatusMessage} (Code ${ex.json.Results[0].ErrorCode})`
|
|
2525
2524
|
: ex.message;
|
|
2526
2525
|
Util.logger.error(
|
|
2527
|
-
` - Deleting ${this.definition.type} '${
|
|
2526
|
+
` - Deleting ${this.definition.type} '${key}' failed: ${errorMsg}`
|
|
2528
2527
|
);
|
|
2529
2528
|
}
|
|
2530
2529
|
|
|
@@ -2537,21 +2536,27 @@ class MetadataType {
|
|
|
2537
2536
|
*
|
|
2538
2537
|
* @param {string} url endpoint
|
|
2539
2538
|
* @param {string} key Identifier of metadata
|
|
2539
|
+
* @param {number} [codeNotFound] error code that is responded with if the item was not found
|
|
2540
2540
|
* @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method
|
|
2541
2541
|
* @returns {Promise.<boolean>} deletion success flag
|
|
2542
2542
|
*/
|
|
2543
|
-
static async deleteByKeyREST(url, key, handleOutside) {
|
|
2543
|
+
static async deleteByKeyREST(url, key, codeNotFound, handleOutside) {
|
|
2544
2544
|
try {
|
|
2545
2545
|
await this.client.rest.delete(url);
|
|
2546
2546
|
if (!handleOutside) {
|
|
2547
2547
|
Util.logger.info(` - deleted ${this.definition.type}: ${key}`);
|
|
2548
2548
|
}
|
|
2549
|
-
this.postDeleteTasks(key);
|
|
2549
|
+
await this.postDeleteTasks(key);
|
|
2550
2550
|
|
|
2551
2551
|
return true;
|
|
2552
2552
|
} catch (ex) {
|
|
2553
2553
|
if (handleOutside) {
|
|
2554
2554
|
throw ex;
|
|
2555
|
+
} else if (
|
|
2556
|
+
codeNotFound &&
|
|
2557
|
+
(ex.code === codeNotFound || ex.response?.status === codeNotFound)
|
|
2558
|
+
) {
|
|
2559
|
+
await this.deleteNotFound(key);
|
|
2555
2560
|
} else {
|
|
2556
2561
|
Util.logger.errorStack(ex, ` - Deleting ${this.definition.type} '${key}' failed`);
|
|
2557
2562
|
}
|
|
@@ -2560,6 +2565,18 @@ class MetadataType {
|
|
|
2560
2565
|
}
|
|
2561
2566
|
}
|
|
2562
2567
|
|
|
2568
|
+
/**
|
|
2569
|
+
* helper for {@link deleteByKey}, {@link deleteByKeyREST}, {@link deleteByKeySOAP}
|
|
2570
|
+
*
|
|
2571
|
+
* @param {string} key Identifier of metadata
|
|
2572
|
+
*/
|
|
2573
|
+
static async deleteNotFound(key) {
|
|
2574
|
+
Util.logger.error(
|
|
2575
|
+
` ☇ skipping deletion of ${this.definition.type} ${key}: not found on server`
|
|
2576
|
+
);
|
|
2577
|
+
await this.postDeleteTasks(key);
|
|
2578
|
+
}
|
|
2579
|
+
|
|
2563
2580
|
/**
|
|
2564
2581
|
* Returns metadata of a business unit that is saved locally
|
|
2565
2582
|
*
|
|
@@ -2600,7 +2617,9 @@ class MetadataType {
|
|
|
2600
2617
|
this.definition.type,
|
|
2601
2618
|
]);
|
|
2602
2619
|
|
|
2603
|
-
const fileList = keyArr.map((key) =>
|
|
2620
|
+
const fileList = keyArr.map((key) =>
|
|
2621
|
+
File.normalizePath([path, File.filterIllegalFilenames(key) + typeExtension])
|
|
2622
|
+
);
|
|
2604
2623
|
return fileList;
|
|
2605
2624
|
}
|
|
2606
2625
|
|
|
@@ -2641,7 +2660,10 @@ class MetadataType {
|
|
|
2641
2660
|
// make sure we don't retry components that we have already searched without result
|
|
2642
2661
|
!notFoundList[this.definition.type].includes(key) &&
|
|
2643
2662
|
// make sure we don't search for components that we have already found
|
|
2644
|
-
!multiTypeKeyList[this.definition.type].includes(key)
|
|
2663
|
+
!multiTypeKeyList[this.definition.type].includes(key) &&
|
|
2664
|
+
// filter out ampscript code that was used instead of actual keys; relevant e.g. for domainVerifications mentioned in senderProfiles
|
|
2665
|
+
!key.startsWith('%%') &&
|
|
2666
|
+
!key.endsWith('%%')
|
|
2645
2667
|
);
|
|
2646
2668
|
if (!keyArr.length) {
|
|
2647
2669
|
return;
|
|
@@ -2943,7 +2965,7 @@ class MetadataType {
|
|
|
2943
2965
|
let passed;
|
|
2944
2966
|
|
|
2945
2967
|
try {
|
|
2946
|
-
passed = await (mode === 'fix'
|
|
2968
|
+
passed = await (!Util.OPTIONS.skipValidation && mode === 'fix'
|
|
2947
2969
|
? validationRules[rule].fix()
|
|
2948
2970
|
: validationRules[rule].passed());
|
|
2949
2971
|
} catch (ex) {
|
|
@@ -2958,7 +2980,7 @@ class MetadataType {
|
|
|
2958
2980
|
fixed = true;
|
|
2959
2981
|
}
|
|
2960
2982
|
if (!passed) {
|
|
2961
|
-
if (mode === 'fix') {
|
|
2983
|
+
if (!Util.OPTIONS.skipValidation && mode === 'fix') {
|
|
2962
2984
|
if (passed === false) {
|
|
2963
2985
|
info.push('😎 auto-fixed: ' + validationRules[rule].failedMsg);
|
|
2964
2986
|
} else if (passed === null) {
|
|
@@ -3000,7 +3022,7 @@ class MetadataType {
|
|
|
3000
3022
|
);
|
|
3001
3023
|
}
|
|
3002
3024
|
// only return "fixed" item if --fix is set, otherwise return the original item
|
|
3003
|
-
return Util.OPTIONS.fix || fixed ? item : originalItem;
|
|
3025
|
+
return !Util.OPTIONS.skipValidation && (Util.OPTIONS.fix || fixed) ? item : originalItem;
|
|
3004
3026
|
}
|
|
3005
3027
|
}
|
|
3006
3028
|
|
|
@@ -491,7 +491,7 @@ class MobileKeyword extends MetadataType {
|
|
|
491
491
|
// get id from cache
|
|
492
492
|
const { metadata } = await this.retrieveForCache(undefined, undefined, key);
|
|
493
493
|
if (!metadata[key]) {
|
|
494
|
-
|
|
494
|
+
await this.deleteNotFound(key);
|
|
495
495
|
return false;
|
|
496
496
|
}
|
|
497
497
|
const id = metadata[key][this.definition.idField];
|
|
@@ -499,7 +499,7 @@ class MobileKeyword extends MetadataType {
|
|
|
499
499
|
Util.logger.info(
|
|
500
500
|
' - Note: As long as the provided API key once existed, you will not see an error even if the mobileKeyword is already deleted.'
|
|
501
501
|
);
|
|
502
|
-
return super.deleteByKeyREST('/legacy/v1/beta/mobile/keyword/' + id, key
|
|
502
|
+
return super.deleteByKeyREST('/legacy/v1/beta/mobile/keyword/' + id, key);
|
|
503
503
|
}
|
|
504
504
|
|
|
505
505
|
/**
|
|
@@ -491,9 +491,11 @@ class MobileMessage extends MetadataType {
|
|
|
491
491
|
*/
|
|
492
492
|
static deleteByKey(id) {
|
|
493
493
|
Util.logger.info(
|
|
494
|
-
|
|
494
|
+
Util.getGrayMsg(
|
|
495
|
+
' - Note: As long as the provided API key once existed, you will not see an error even if the mobileMessage is already deleted.'
|
|
496
|
+
)
|
|
495
497
|
);
|
|
496
|
-
return super.deleteByKeyREST('/legacy/v1/beta/mobile/message/' + id, id,
|
|
498
|
+
return super.deleteByKeyREST('/legacy/v1/beta/mobile/message/' + id, id, 400);
|
|
497
499
|
}
|
|
498
500
|
}
|
|
499
501
|
|