mcdev 4.2.1 → 4.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 +2 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +1 -2
- package/.github/pr-labeler.yml +3 -0
- package/.github/workflows/close_issues_on_merge.yml +18 -0
- package/.github/workflows/pr-labeler.yml +19 -0
- package/LICENSE +1 -1
- package/README.md +1 -1
- package/docs/dist/documentation.md +700 -281
- package/lib/Deployer.js +21 -15
- package/lib/Retriever.js +23 -19
- package/lib/cli.js +36 -6
- package/lib/index.js +56 -10
- package/lib/metadataTypes/AccountUser.js +17 -23
- package/lib/metadataTypes/Asset.js +28 -21
- package/lib/metadataTypes/AttributeGroup.js +1 -2
- package/lib/metadataTypes/Automation.js +75 -37
- package/lib/metadataTypes/Campaign.js +4 -3
- package/lib/metadataTypes/ContentArea.js +2 -3
- package/lib/metadataTypes/DataExtension.js +56 -47
- package/lib/metadataTypes/DataExtensionField.js +9 -12
- package/lib/metadataTypes/DataExtensionTemplate.js +2 -3
- package/lib/metadataTypes/DataExtract.js +1 -2
- package/lib/metadataTypes/DataExtractType.js +1 -2
- package/lib/metadataTypes/Discovery.js +3 -4
- package/lib/metadataTypes/Email.js +20 -6
- package/lib/metadataTypes/EmailSendDefinition.js +5 -8
- package/lib/metadataTypes/EventDefinition.js +29 -2
- package/lib/metadataTypes/FileTransfer.js +1 -2
- package/lib/metadataTypes/Filter.js +1 -2
- package/lib/metadataTypes/Folder.js +12 -14
- package/lib/metadataTypes/FtpLocation.js +1 -2
- package/lib/metadataTypes/ImportFile.js +1 -2
- package/lib/metadataTypes/Interaction.js +678 -12
- package/lib/metadataTypes/List.js +36 -33
- package/lib/metadataTypes/MetadataType.js +170 -124
- package/lib/metadataTypes/MobileCode.js +1 -2
- package/lib/metadataTypes/MobileKeyword.js +1 -2
- package/lib/metadataTypes/Query.js +15 -6
- package/lib/metadataTypes/Role.js +10 -11
- package/lib/metadataTypes/Script.js +2 -5
- package/lib/metadataTypes/SetDefinition.js +1 -2
- package/lib/metadataTypes/TransactionalMessage.js +25 -32
- package/lib/metadataTypes/TransactionalSMS.js +3 -4
- package/lib/metadataTypes/TriggeredSendDefinition.js +232 -56
- package/lib/metadataTypes/definitions/Asset.definition.js +1 -1
- package/lib/metadataTypes/definitions/Automation.definition.js +1 -1
- package/lib/metadataTypes/definitions/DataExtension.definition.js +10 -1
- package/lib/metadataTypes/definitions/Email.definition.js +1 -1
- package/lib/metadataTypes/definitions/EmailSendDefinition.definition.js +1 -1
- package/lib/metadataTypes/definitions/EventDefinition.definition.js +40 -1
- package/lib/metadataTypes/definitions/Folder.definition.js +31 -0
- package/lib/metadataTypes/definitions/ImportFile.definition.js +1 -1
- package/lib/metadataTypes/definitions/Interaction.definition.js +47 -26
- package/lib/metadataTypes/definitions/List.definition.js +1 -1
- package/lib/metadataTypes/definitions/Query.definition.js +1 -1
- package/lib/metadataTypes/definitions/Script.definition.js +1 -1
- package/lib/metadataTypes/definitions/TransactionalEmail.definition.js +2 -1
- package/lib/metadataTypes/definitions/TransactionalPush.definition.js +2 -1
- package/lib/metadataTypes/definitions/TransactionalSMS.definition.js +2 -1
- package/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js +10 -2
- package/lib/util/auth.js +10 -2
- package/lib/util/cli.js +4 -1
- package/lib/util/file.js +7 -3
- package/lib/util/init.js +62 -0
- package/lib/util/util.js +131 -11
- package/package.json +22 -9
- package/test/dataExtension.test.js +10 -10
- package/test/interaction.test.js +123 -0
- package/test/mockRoot/.mcdevrc.json +1 -1
- package/test/mockRoot/deploy/testInstance/testBU/interaction/testExisting_interaction.interaction-meta.json +266 -0
- package/test/mockRoot/deploy/testInstance/testBU/interaction/testNew_interaction.interaction-meta.json +266 -0
- package/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json +0 -3
- package/test/query.test.js +8 -8
- package/test/resourceFactory.js +12 -7
- package/test/resources/1111111/dataExtension/retrieve-response.xml +26 -0
- package/test/resources/9999999/data/v1/customobjectdata/key/childBU_dataextension_test/rowset/get-response.json +13 -0
- package/test/resources/9999999/dataFolder/retrieve-response.xml +22 -0
- package/test/resources/9999999/eventDefinition/get-expected.json +34 -0
- package/test/resources/9999999/interaction/build-expected.json +260 -0
- package/test/resources/9999999/interaction/get-expected.json +264 -0
- package/test/resources/9999999/interaction/post-expected.json +264 -0
- package/test/resources/9999999/interaction/put-expected.json +264 -0
- package/test/resources/9999999/interaction/template-expected.json +260 -0
- package/test/resources/9999999/interaction/v1/EventDefinitions/get-response.json +43 -0
- package/test/resources/9999999/interaction/v1/interactions/get-response.json +222 -3
- package/test/resources/9999999/interaction/v1/interactions/post-response.json +280 -0
- package/test/resources/9999999/interaction/v1/interactions/put-response.json +280 -0
- package/test/resources/9999999/messaging/v1/email/definitions/post-response.json +1 -1
- package/test/resources/9999999/query/post-expected.sql +1 -1
- package/test/resources/9999999/transactionalEmail/post-expected.json +1 -1
- package/test/transactionalEmail.test.js +7 -7
- package/test/transactionalPush.test.js +7 -7
- package/test/transactionalSMS.test.js +7 -7
- package/test/utils.js +50 -0
- package/types/mcdev.d.js +1 -0
|
@@ -19,11 +19,10 @@ class Automation extends MetadataType {
|
|
|
19
19
|
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
20
20
|
* @param {void} [_] unused parameter
|
|
21
21
|
* @param {void} [__] unused parameter
|
|
22
|
-
* @param {void} [___] unused parameter
|
|
23
22
|
* @param {string} [key] customer key of single item to retrieve
|
|
24
23
|
* @returns {Promise.<TYPE.AutomationMapObj>} Promise of metadata
|
|
25
24
|
*/
|
|
26
|
-
static async retrieve(retrieveDir, _, __,
|
|
25
|
+
static async retrieve(retrieveDir, _, __, key) {
|
|
27
26
|
/** @type {TYPE.SoapRequestParams} */
|
|
28
27
|
let requestParams = null;
|
|
29
28
|
if (key) {
|
|
@@ -36,12 +35,39 @@ class Automation extends MetadataType {
|
|
|
36
35
|
};
|
|
37
36
|
}
|
|
38
37
|
const results = await this.client.soap.retrieveBulk('Program', ['ObjectID'], requestParams);
|
|
39
|
-
|
|
38
|
+
if (results.Results?.length) {
|
|
39
|
+
// empty results will come back without "Results" defined
|
|
40
|
+
Util.logger.info(
|
|
41
|
+
Util.getGrayMsg(
|
|
42
|
+
` - ${results.Results?.length} Automations found. Retrieving details...`
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
}
|
|
40
46
|
const details = results.Results
|
|
41
47
|
? await Promise.all(
|
|
42
|
-
results.Results.map((a) =>
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
results.Results.map(async (a) => {
|
|
49
|
+
try {
|
|
50
|
+
return await this.client.rest.get(
|
|
51
|
+
'/automation/v1/automations/' + a.ObjectID
|
|
52
|
+
);
|
|
53
|
+
} catch (ex) {
|
|
54
|
+
try {
|
|
55
|
+
if (ex.message == 'socket hang up') {
|
|
56
|
+
// one more retry; it's a rare case but retrying again should solve the issue gracefully
|
|
57
|
+
return await this.client.rest.get(
|
|
58
|
+
'/automation/v1/automations/' + a.ObjectID
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
} catch {
|
|
62
|
+
// no extra action needed, handled below
|
|
63
|
+
}
|
|
64
|
+
// if we do get here, we should log the error and continue instead of failing to download all automations
|
|
65
|
+
Util.logger.error(
|
|
66
|
+
` - skipping retrieving Automation ${a.ObjectID}: ${ex.message} ${ex.code}`
|
|
67
|
+
);
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
})
|
|
45
71
|
)
|
|
46
72
|
: [];
|
|
47
73
|
const parsed = this.parseResponseBody({ items: details });
|
|
@@ -49,10 +75,11 @@ class Automation extends MetadataType {
|
|
|
49
75
|
// * retrieveDir is mandatory in this method as it is not used for caching (there is a seperate method for that)
|
|
50
76
|
const savedMetadata = await this.saveResults(parsed, retrieveDir, null, null);
|
|
51
77
|
Util.logger.info(
|
|
52
|
-
`Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})`
|
|
78
|
+
`Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` +
|
|
79
|
+
Util.getKeysString(key)
|
|
53
80
|
);
|
|
54
81
|
if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) {
|
|
55
|
-
await this.document(
|
|
82
|
+
await this.document(savedMetadata);
|
|
56
83
|
}
|
|
57
84
|
return { metadata: savedMetadata, type: this.definition.type };
|
|
58
85
|
}
|
|
@@ -245,28 +272,9 @@ class Automation extends MetadataType {
|
|
|
245
272
|
*/
|
|
246
273
|
static async preDeployTasks(metadata) {
|
|
247
274
|
if (this.validateDeployMetadata(metadata)) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
metadata.r__folder_Path,
|
|
252
|
-
'Path',
|
|
253
|
-
'ID'
|
|
254
|
-
);
|
|
255
|
-
if (metadata.r__folder_Path !== 'my automations') {
|
|
256
|
-
Util.logger.warn(
|
|
257
|
-
` - Automation '${
|
|
258
|
-
metadata[this.definition.nameField]
|
|
259
|
-
}' is located in subfolder ${
|
|
260
|
-
metadata.r__folder_Path
|
|
261
|
-
}. 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.`
|
|
262
|
-
);
|
|
263
|
-
}
|
|
264
|
-
delete metadata.r__folder_Path;
|
|
265
|
-
} catch {
|
|
266
|
-
throw new Error(
|
|
267
|
-
`Folder '${metadata.r__folder_Path}' was not found on the server. Please create this manually in the GUI. Automation-folders cannot be deployed automatically.`
|
|
268
|
-
);
|
|
269
|
-
}
|
|
275
|
+
// folder
|
|
276
|
+
this.setFolderId(metadata);
|
|
277
|
+
|
|
270
278
|
if (metadata.type === 'scheduled' && metadata?.schedule?.startDate) {
|
|
271
279
|
// Starting Source == 'Schedule'
|
|
272
280
|
|
|
@@ -493,13 +501,44 @@ class Automation extends MetadataType {
|
|
|
493
501
|
}
|
|
494
502
|
}
|
|
495
503
|
|
|
504
|
+
/**
|
|
505
|
+
* automation-specific script that retrieves the folder ID from cache and updates the given metadata with it before deploy
|
|
506
|
+
*
|
|
507
|
+
* @param {TYPE.MetadataTypeItem} metadata a single item
|
|
508
|
+
*/
|
|
509
|
+
static setFolderId(metadata) {
|
|
510
|
+
try {
|
|
511
|
+
metadata.categoryId = cache.searchForField(
|
|
512
|
+
'folder',
|
|
513
|
+
metadata.r__folder_Path,
|
|
514
|
+
'Path',
|
|
515
|
+
'ID'
|
|
516
|
+
);
|
|
517
|
+
if (metadata.r__folder_Path !== 'my automations') {
|
|
518
|
+
Util.logger.warn(
|
|
519
|
+
` - Automation '${
|
|
520
|
+
metadata[this.definition.nameField]
|
|
521
|
+
}' is located in subfolder ${
|
|
522
|
+
metadata.r__folder_Path
|
|
523
|
+
}. 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.`
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
delete metadata.r__folder_Path;
|
|
527
|
+
} catch {
|
|
528
|
+
throw new Error(
|
|
529
|
+
`Folder '${metadata.r__folder_Path}' was not found on the server. Please create this manually in the GUI. Automation-folders cannot be deployed automatically.`
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
496
534
|
/**
|
|
497
535
|
* parses retrieved Metadata before saving
|
|
498
536
|
*
|
|
499
537
|
* @param {TYPE.AutomationItem} metadata a single automation definition
|
|
500
|
-
* @returns {TYPE.AutomationItem} parsed item
|
|
538
|
+
* @returns {TYPE.AutomationItem | void} parsed item
|
|
501
539
|
*/
|
|
502
540
|
static parseMetadata(metadata) {
|
|
541
|
+
// folder
|
|
503
542
|
this.setFolderPath(metadata);
|
|
504
543
|
// automations are often skipped due to lack of support.
|
|
505
544
|
try {
|
|
@@ -895,26 +934,25 @@ class Automation extends MetadataType {
|
|
|
895
934
|
/**
|
|
896
935
|
* Parses metadata into a readable Markdown/HTML format then saves it
|
|
897
936
|
*
|
|
898
|
-
* @param {TYPE.BuObject} buObject properties for auth
|
|
899
937
|
* @param {TYPE.AutomationMap} [metadata] a list of dataExtension definitions
|
|
900
938
|
* @returns {Promise.<void>} -
|
|
901
939
|
*/
|
|
902
|
-
static async document(
|
|
940
|
+
static async document(metadata) {
|
|
903
941
|
if (['md', 'both'].includes(this.properties.options.documentType)) {
|
|
904
942
|
if (!metadata) {
|
|
905
943
|
metadata = this.readBUMetadataForType(
|
|
906
944
|
File.normalizePath([
|
|
907
945
|
this.properties.directories.retrieve,
|
|
908
|
-
buObject.credential,
|
|
909
|
-
buObject.businessUnit,
|
|
946
|
+
this.buObject.credential,
|
|
947
|
+
this.buObject.businessUnit,
|
|
910
948
|
]),
|
|
911
949
|
true
|
|
912
950
|
).automation;
|
|
913
951
|
}
|
|
914
952
|
const docPath = File.normalizePath([
|
|
915
953
|
this.properties.directories.retrieve,
|
|
916
|
-
buObject.credential,
|
|
917
|
-
buObject.businessUnit,
|
|
954
|
+
this.buObject.credential,
|
|
955
|
+
this.buObject.businessUnit,
|
|
918
956
|
this.definition.type,
|
|
919
957
|
]);
|
|
920
958
|
if (!metadata || !Object.keys(metadata).length) {
|
|
@@ -17,11 +17,10 @@ class Campaign extends MetadataType {
|
|
|
17
17
|
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
18
18
|
* @param {void} [_] unused parameter
|
|
19
19
|
* @param {void} [__] unused parameter
|
|
20
|
-
* @param {void} [___] unused parameter
|
|
21
20
|
* @param {string} [key] customer key of single item to retrieve
|
|
22
21
|
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise
|
|
23
22
|
*/
|
|
24
|
-
static async retrieve(retrieveDir, _, __,
|
|
23
|
+
static async retrieve(retrieveDir, _, __, key) {
|
|
25
24
|
const res = await super.retrieveREST(retrieveDir, '/hub/v1/campaigns', null, null, key);
|
|
26
25
|
// get assignments
|
|
27
26
|
|
|
@@ -30,7 +29,9 @@ class Campaign extends MetadataType {
|
|
|
30
29
|
this.getAssetTags(retrieveDir, res.metadata[key].id, key)
|
|
31
30
|
)
|
|
32
31
|
);
|
|
33
|
-
Util.logger.info(
|
|
32
|
+
Util.logger.info(
|
|
33
|
+
`Downloaded: campaignAssets (${campaignAssets.flat().length})` + Util.getKeysString(key)
|
|
34
|
+
);
|
|
34
35
|
|
|
35
36
|
return res;
|
|
36
37
|
}
|
|
@@ -17,11 +17,10 @@ class ContentArea extends MetadataType {
|
|
|
17
17
|
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
18
18
|
* @param {void} [_] unused parameter
|
|
19
19
|
* @param {void} [__] unused parameter
|
|
20
|
-
* @param {void} [___] unused parameter
|
|
21
20
|
* @param {string} [key] customer key of single item to retrieve
|
|
22
21
|
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
|
|
23
22
|
*/
|
|
24
|
-
static retrieve(retrieveDir, _, __,
|
|
23
|
+
static retrieve(retrieveDir, _, __, key) {
|
|
25
24
|
Util.logger.warn(
|
|
26
25
|
' - 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.'
|
|
27
26
|
);
|
|
@@ -37,7 +36,7 @@ class ContentArea extends MetadataType {
|
|
|
37
36
|
};
|
|
38
37
|
}
|
|
39
38
|
// !dont activate `await File.initPrettier('html');` as we only want to retrieve for migration and formatting might mess with the outcome
|
|
40
|
-
return super.retrieveSOAP(retrieveDir,
|
|
39
|
+
return super.retrieveSOAP(retrieveDir, requestParams);
|
|
41
40
|
}
|
|
42
41
|
/**
|
|
43
42
|
* manages post retrieve steps
|
|
@@ -21,16 +21,33 @@ class DataExtension extends MetadataType {
|
|
|
21
21
|
* if create or update operation is needed.
|
|
22
22
|
*
|
|
23
23
|
* @param {TYPE.DataExtensionMap} desToDeploy dataExtensions mapped by their customerKey
|
|
24
|
-
* @param {void} _ unused parameter
|
|
25
|
-
* @param {TYPE.BuObject} buObject properties for auth
|
|
26
24
|
* @returns {Promise} Promise
|
|
27
25
|
*/
|
|
28
|
-
static async upsert(desToDeploy
|
|
26
|
+
static async upsert(desToDeploy) {
|
|
29
27
|
// get dataExtensions from target BU for add/update decision
|
|
30
28
|
/** @type {TYPE.DataExtensionMap} */
|
|
31
29
|
const targetMetadata = cache.getCache().dataExtension || {};
|
|
32
|
-
// get existing
|
|
33
|
-
|
|
30
|
+
// get existing DE-fields for DE-keys in deployment package to properly handle add/update/delete of fields
|
|
31
|
+
const fieldOptions = {};
|
|
32
|
+
for (const key of Object.keys(desToDeploy)) {
|
|
33
|
+
fieldOptions.filter = fieldOptions.filter
|
|
34
|
+
? {
|
|
35
|
+
leftOperand: {
|
|
36
|
+
leftOperand: 'DataExtension.CustomerKey',
|
|
37
|
+
operator: 'equals',
|
|
38
|
+
rightOperand: key,
|
|
39
|
+
},
|
|
40
|
+
operator: 'OR',
|
|
41
|
+
rightOperand: fieldOptions.filter,
|
|
42
|
+
}
|
|
43
|
+
: {
|
|
44
|
+
leftOperand: 'DataExtension.CustomerKey',
|
|
45
|
+
operator: 'equals',
|
|
46
|
+
rightOperand: key,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
Util.logger.info(` - Caching dependent Metadata: dataExtensionField`);
|
|
50
|
+
await this._attachFields(desToDeploy, fieldOptions);
|
|
34
51
|
|
|
35
52
|
/** @type {Promise[]} */
|
|
36
53
|
const deCreatePromises = [];
|
|
@@ -46,7 +63,7 @@ class DataExtension extends MetadataType {
|
|
|
46
63
|
continue;
|
|
47
64
|
}
|
|
48
65
|
if (
|
|
49
|
-
buObject.eid !== buObject.mid &&
|
|
66
|
+
this.buObject.eid !== this.buObject.mid &&
|
|
50
67
|
desToDeploy[dataExtension].r__folder_Path.startsWith('Shared Items')
|
|
51
68
|
) {
|
|
52
69
|
// this needs to be run before executing preDeployTasks()
|
|
@@ -304,12 +321,11 @@ class DataExtension extends MetadataType {
|
|
|
304
321
|
*
|
|
305
322
|
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
306
323
|
* @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true
|
|
307
|
-
* @param {TYPE.BuObject} buObject properties for auth
|
|
308
324
|
* @param {void} [_] unused parameter
|
|
309
325
|
* @param {string} [key] customer key of single item to retrieve
|
|
310
326
|
* @returns {Promise.<{metadata: TYPE.DataExtensionMap, type: string}>} Promise of item map
|
|
311
327
|
*/
|
|
312
|
-
static async retrieve(retrieveDir, additionalFields,
|
|
328
|
+
static async retrieve(retrieveDir, additionalFields, _, key) {
|
|
313
329
|
/** @type {TYPE.SoapRequestParams} */
|
|
314
330
|
let requestParams = null;
|
|
315
331
|
/** @type {TYPE.SoapRequestParams} */
|
|
@@ -336,17 +352,17 @@ class DataExtension extends MetadataType {
|
|
|
336
352
|
// get fields from API
|
|
337
353
|
await this._attachFields(metadata, fieldOptions, additionalFields);
|
|
338
354
|
}
|
|
339
|
-
if (!retrieveDir && buObject.eid !== buObject.mid) {
|
|
355
|
+
if (!retrieveDir && this.buObject.eid !== this.buObject.mid) {
|
|
340
356
|
// for caching, we want to retrieve shared DEs as well from the instance parent BU
|
|
341
357
|
Util.logger.info(
|
|
342
358
|
' - Caching dependent Metadata: dataExtension (shared via _ParentBU_)'
|
|
343
359
|
);
|
|
344
360
|
/** @type {TYPE.BuObject} */
|
|
345
361
|
const buObjectParentBu = {
|
|
346
|
-
eid: this.properties.credentials[buObject.credential].eid,
|
|
347
|
-
mid: this.properties.credentials[buObject.credential].eid,
|
|
362
|
+
eid: this.properties.credentials[this.buObject.credential].eid,
|
|
363
|
+
mid: this.properties.credentials[this.buObject.credential].eid,
|
|
348
364
|
businessUnit: Util.parentBuName,
|
|
349
|
-
credential: buObject.credential,
|
|
365
|
+
credential: this.buObject.credential,
|
|
350
366
|
};
|
|
351
367
|
try {
|
|
352
368
|
this.client = auth.getSDK(buObjectParentBu);
|
|
@@ -357,17 +373,16 @@ class DataExtension extends MetadataType {
|
|
|
357
373
|
const metadataParentBu = await this._retrieveAll(additionalFields);
|
|
358
374
|
|
|
359
375
|
// get shared folders to match our shared / synched Data Extensions
|
|
376
|
+
const subTypeArr = this.definition.dependencies
|
|
377
|
+
.filter((item) => item.startsWith('folder-'))
|
|
378
|
+
.map((item) => item.slice(7));
|
|
360
379
|
Util.logger.info(' - Caching dependent Metadata: folder (shared via _ParentBU_)');
|
|
380
|
+
Util.logSubtypes(subTypeArr);
|
|
361
381
|
Folder.client = this.client;
|
|
382
|
+
Folder.buObject = buObjectParentBu;
|
|
362
383
|
Folder.properties = this.properties;
|
|
363
|
-
const result = await Folder.retrieveForCache(
|
|
364
|
-
|
|
365
|
-
'synchronizeddataextension',
|
|
366
|
-
'salesforcedataextension',
|
|
367
|
-
'shared_dataextension',
|
|
368
|
-
'dataextension',
|
|
369
|
-
]);
|
|
370
|
-
cache.mergeMetadata('folder', result.metadata, buObject.eid);
|
|
384
|
+
const result = await Folder.retrieveForCache(null, subTypeArr);
|
|
385
|
+
cache.mergeMetadata('folder', result.metadata, this.buObject.eid);
|
|
371
386
|
|
|
372
387
|
// get the types and clean out non-shared ones
|
|
373
388
|
const folderTypesFromParent = require('../MetadataTypeDefinitions').folder
|
|
@@ -380,7 +395,7 @@ class DataExtension extends MetadataType {
|
|
|
380
395
|
metadataParentBu[metadataEntry].CategoryID,
|
|
381
396
|
'ID',
|
|
382
397
|
'ContentType',
|
|
383
|
-
buObject.eid
|
|
398
|
+
this.buObject.eid
|
|
384
399
|
);
|
|
385
400
|
if (!folderTypesFromParent.includes(folderContentType)) {
|
|
386
401
|
Util.logger.verbose(
|
|
@@ -406,10 +421,11 @@ class DataExtension extends MetadataType {
|
|
|
406
421
|
if (retrieveDir) {
|
|
407
422
|
const savedMetadata = await super.saveResults(metadata, retrieveDir, null);
|
|
408
423
|
Util.logger.info(
|
|
409
|
-
`Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})`
|
|
424
|
+
`Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` +
|
|
425
|
+
Util.getKeysString(key)
|
|
410
426
|
);
|
|
411
427
|
if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) {
|
|
412
|
-
await this.document(
|
|
428
|
+
await this.document(savedMetadata);
|
|
413
429
|
}
|
|
414
430
|
}
|
|
415
431
|
return { metadata: metadata, type: 'dataExtension' };
|
|
@@ -452,11 +468,10 @@ class DataExtension extends MetadataType {
|
|
|
452
468
|
/**
|
|
453
469
|
* Retrieves dataExtension metadata. Afterwards starts retrieval of dataExtensionColumn metadata retrieval
|
|
454
470
|
*
|
|
455
|
-
* @param {TYPE.BuObject} [buObject] properties for auth
|
|
456
471
|
* @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true
|
|
457
472
|
* @returns {Promise.<{metadata: TYPE.DataExtensionMap, type: string}>} Promise of item map
|
|
458
473
|
*/
|
|
459
|
-
static async retrieveChangelog(
|
|
474
|
+
static async retrieveChangelog(additionalFields) {
|
|
460
475
|
const metadata = await this._retrieveAll(additionalFields);
|
|
461
476
|
return { metadata: metadata, type: 'dataExtension' };
|
|
462
477
|
}
|
|
@@ -533,8 +548,7 @@ class DataExtension extends MetadataType {
|
|
|
533
548
|
*/
|
|
534
549
|
static async preDeployTasks(metadata) {
|
|
535
550
|
// folder
|
|
536
|
-
|
|
537
|
-
delete metadata.r__folder_Path;
|
|
551
|
+
super.setFolderId(metadata);
|
|
538
552
|
|
|
539
553
|
// DataExtensionTemplate
|
|
540
554
|
if (metadata.r__dataExtensionTemplate_Name) {
|
|
@@ -741,18 +755,17 @@ class DataExtension extends MetadataType {
|
|
|
741
755
|
/**
|
|
742
756
|
* Parses metadata into a readable Markdown/HTML format then saves it
|
|
743
757
|
*
|
|
744
|
-
* @param {TYPE.BuObject} buObject properties for auth
|
|
745
758
|
* @param {TYPE.DataExtensionMap} [metadata] a list of dataExtension definitions
|
|
746
759
|
* @returns {Promise.<void>} -
|
|
747
760
|
*/
|
|
748
|
-
static async document(
|
|
761
|
+
static async document(metadata) {
|
|
749
762
|
try {
|
|
750
763
|
if (!metadata) {
|
|
751
764
|
metadata = this.readBUMetadataForType(
|
|
752
765
|
File.normalizePath([
|
|
753
766
|
this.properties.directories.retrieve,
|
|
754
|
-
buObject.credential,
|
|
755
|
-
buObject.businessUnit,
|
|
767
|
+
this.buObject.credential,
|
|
768
|
+
this.buObject.businessUnit,
|
|
756
769
|
]),
|
|
757
770
|
true
|
|
758
771
|
).dataExtension;
|
|
@@ -763,8 +776,8 @@ class DataExtension extends MetadataType {
|
|
|
763
776
|
}
|
|
764
777
|
const docPath = File.normalizePath([
|
|
765
778
|
this.properties.directories.retrieve,
|
|
766
|
-
buObject.credential,
|
|
767
|
-
buObject.businessUnit,
|
|
779
|
+
this.buObject.credential,
|
|
780
|
+
this.buObject.businessUnit,
|
|
768
781
|
this.definition.type,
|
|
769
782
|
]);
|
|
770
783
|
if (!metadata || !Object.keys(metadata).length) {
|
|
@@ -821,27 +834,25 @@ class DataExtension extends MetadataType {
|
|
|
821
834
|
/**
|
|
822
835
|
* Delete a metadata item from the specified business unit
|
|
823
836
|
*
|
|
824
|
-
* @param {TYPE.BuObject} buObject references credentials
|
|
825
837
|
* @param {string} customerKey Identifier of data extension
|
|
826
838
|
* @returns {Promise.<boolean>} deletion success status
|
|
827
839
|
*/
|
|
828
|
-
static deleteByKey(
|
|
829
|
-
return super.deleteByKeySOAP(
|
|
840
|
+
static deleteByKey(customerKey) {
|
|
841
|
+
return super.deleteByKeySOAP(customerKey, false);
|
|
830
842
|
}
|
|
831
843
|
|
|
832
844
|
/**
|
|
833
845
|
* clean up after deleting a metadata item
|
|
834
846
|
*
|
|
835
|
-
* @param {TYPE.BuObject} buObject references credentials
|
|
836
847
|
* @param {string} customerKey Identifier of metadata item
|
|
837
848
|
* @returns {void}
|
|
838
849
|
*/
|
|
839
|
-
static async postDeleteTasks(
|
|
850
|
+
static async postDeleteTasks(customerKey) {
|
|
840
851
|
// delete local copy: retrieve/cred/bu/dataExtension/...json
|
|
841
852
|
const jsonFile = File.normalizePath([
|
|
842
853
|
this.properties.directories.retrieve,
|
|
843
|
-
buObject.credential,
|
|
844
|
-
buObject.businessUnit,
|
|
854
|
+
this.buObject.credential,
|
|
855
|
+
this.buObject.businessUnit,
|
|
845
856
|
this.definition.type,
|
|
846
857
|
`${customerKey}.${this.definition.type}-meta.json`,
|
|
847
858
|
]);
|
|
@@ -850,8 +861,8 @@ class DataExtension extends MetadataType {
|
|
|
850
861
|
const mdFile = File.normalizePath([
|
|
851
862
|
this.properties.directories.docs,
|
|
852
863
|
'dataExtension',
|
|
853
|
-
buObject.credential,
|
|
854
|
-
buObject.businessUnit,
|
|
864
|
+
this.buObject.credential,
|
|
865
|
+
this.buObject.businessUnit,
|
|
855
866
|
`${customerKey}.${this.definition.type}.md`,
|
|
856
867
|
]);
|
|
857
868
|
await File.remove(mdFile);
|
|
@@ -860,11 +871,10 @@ class DataExtension extends MetadataType {
|
|
|
860
871
|
/**
|
|
861
872
|
* Retrieves folder metadata into local filesystem. Also creates a uniquePath attribute for each folder.
|
|
862
873
|
*
|
|
863
|
-
* @param {TYPE.BuObject} buObject properties for auth
|
|
864
874
|
* @returns {Promise.<{metadata: TYPE.DataExtensionMap, type: string}>} Promise
|
|
865
875
|
*/
|
|
866
|
-
static async retrieveForCache(
|
|
867
|
-
return this.retrieve(null, ['ObjectID', 'CustomerKey', 'Name'], buObject, null, null);
|
|
876
|
+
static async retrieveForCache() {
|
|
877
|
+
return this.retrieve(null, ['ObjectID', 'CustomerKey', 'Name'], this.buObject, null, null);
|
|
868
878
|
}
|
|
869
879
|
/**
|
|
870
880
|
* Retrieves dataExtension metadata in template format.
|
|
@@ -978,7 +988,6 @@ class DataExtension extends MetadataType {
|
|
|
978
988
|
}
|
|
979
989
|
}
|
|
980
990
|
}
|
|
981
|
-
|
|
982
991
|
/**
|
|
983
992
|
* parses retrieved Metadata before saving
|
|
984
993
|
*
|
|
@@ -1028,7 +1037,7 @@ class DataExtension extends MetadataType {
|
|
|
1028
1037
|
* @returns {Promise.<TYPE.DataExtensionMap>} keyField => metadata map
|
|
1029
1038
|
*/
|
|
1030
1039
|
static async _retrieveAll(additionalFields, options) {
|
|
1031
|
-
const { metadata } = await super.retrieveSOAP(null,
|
|
1040
|
+
const { metadata } = await super.retrieveSOAP(null, options, additionalFields);
|
|
1032
1041
|
for (const key in metadata) {
|
|
1033
1042
|
// some system data extensions do not have CategoryID which throws errors in other places. These do not need to be parsed
|
|
1034
1043
|
if (metadata[key].CategoryID) {
|
|
@@ -15,11 +15,10 @@ class DataExtensionField extends MetadataType {
|
|
|
15
15
|
*
|
|
16
16
|
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
17
17
|
* @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true
|
|
18
|
-
* @param {TYPE.BuObject} buObject properties for auth
|
|
19
18
|
* @returns {Promise.<{metadata: TYPE.DataExtensionFieldMap, type: string}>} Promise of items
|
|
20
19
|
*/
|
|
21
|
-
static async retrieve(retrieveDir, additionalFields
|
|
22
|
-
return super.retrieveSOAP(retrieveDir,
|
|
20
|
+
static async retrieve(retrieveDir, additionalFields) {
|
|
21
|
+
return super.retrieveSOAP(retrieveDir, null, additionalFields);
|
|
23
22
|
}
|
|
24
23
|
/**
|
|
25
24
|
* Retrieves all records for caching
|
|
@@ -29,7 +28,7 @@ class DataExtensionField extends MetadataType {
|
|
|
29
28
|
* @returns {Promise.<{metadata: TYPE.DataExtensionFieldMap, type: string}>} Promise of items
|
|
30
29
|
*/
|
|
31
30
|
static async retrieveForCache(requestParams, additionalFields) {
|
|
32
|
-
return super.retrieveSOAP(null,
|
|
31
|
+
return super.retrieveSOAP(null, requestParams, additionalFields);
|
|
33
32
|
}
|
|
34
33
|
/**
|
|
35
34
|
* helper for {@link DataExtension._retrieveFieldsForSingleDe} that sorts the fields into an array
|
|
@@ -242,8 +241,8 @@ class DataExtensionField extends MetadataType {
|
|
|
242
241
|
}
|
|
243
242
|
}
|
|
244
243
|
|
|
245
|
-
Util.logger.
|
|
246
|
-
|
|
244
|
+
Util.logger.info(
|
|
245
|
+
` - Found ${deployColumns.length} added/updated Fields for ${deKey}${
|
|
247
246
|
deployColumns.length ? ': ' : ''
|
|
248
247
|
}` + deployColumns.map((item) => item.Name).join(', ')
|
|
249
248
|
);
|
|
@@ -253,23 +252,21 @@ class DataExtensionField extends MetadataType {
|
|
|
253
252
|
/**
|
|
254
253
|
* Delete a metadata item from the specified business unit
|
|
255
254
|
*
|
|
256
|
-
* @param {TYPE.BuObject} buObject references credentials
|
|
257
255
|
* @param {string} customerKey Identifier of data extension
|
|
258
256
|
* @returns {Promise.<boolean>} deletion success status
|
|
259
257
|
*/
|
|
260
|
-
static deleteByKey(
|
|
261
|
-
return this.deleteByKeySOAP(
|
|
258
|
+
static deleteByKey(customerKey) {
|
|
259
|
+
return this.deleteByKeySOAP(customerKey, false);
|
|
262
260
|
}
|
|
263
261
|
|
|
264
262
|
/**
|
|
265
263
|
* Delete a data extension from the specified business unit
|
|
266
264
|
*
|
|
267
|
-
* @param {TYPE.BuObject} buObject references credentials
|
|
268
265
|
* @param {string} customerKey Identifier of metadata
|
|
269
266
|
* @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method
|
|
270
267
|
* @returns {boolean} deletion success flag
|
|
271
268
|
*/
|
|
272
|
-
static async deleteByKeySOAP(
|
|
269
|
+
static async deleteByKeySOAP(customerKey, handleOutside) {
|
|
273
270
|
const [deKey, fieldKey] = customerKey.split('.');
|
|
274
271
|
customerKey = `[${deKey}].[${fieldKey}]`;
|
|
275
272
|
|
|
@@ -309,7 +306,7 @@ class DataExtensionField extends MetadataType {
|
|
|
309
306
|
if (!handleOutside) {
|
|
310
307
|
Util.logger.info(`- deleted ${this.definition.type}: ${customerKey}`);
|
|
311
308
|
}
|
|
312
|
-
this.postDeleteTasks(
|
|
309
|
+
this.postDeleteTasks(customerKey);
|
|
313
310
|
return true;
|
|
314
311
|
} catch (ex) {
|
|
315
312
|
if (handleOutside) {
|
|
@@ -15,11 +15,10 @@ class DataExtensionTemplate extends MetadataType {
|
|
|
15
15
|
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
16
16
|
* @param {void} [_] unused parameter
|
|
17
17
|
* @param {void} [__] unused parameter
|
|
18
|
-
* @param {void} [___] unused parameter
|
|
19
18
|
* @param {string} [key] customer key of single item to retrieve
|
|
20
19
|
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
|
|
21
20
|
*/
|
|
22
|
-
static retrieve(retrieveDir, _, __,
|
|
21
|
+
static retrieve(retrieveDir, _, __, key) {
|
|
23
22
|
/** @type {TYPE.SoapRequestParams} */
|
|
24
23
|
let requestParams = null;
|
|
25
24
|
if (key) {
|
|
@@ -31,7 +30,7 @@ class DataExtensionTemplate extends MetadataType {
|
|
|
31
30
|
},
|
|
32
31
|
};
|
|
33
32
|
}
|
|
34
|
-
return super.retrieveSOAP(retrieveDir,
|
|
33
|
+
return super.retrieveSOAP(retrieveDir, requestParams);
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
36
|
|
|
@@ -19,11 +19,10 @@ class DataExtract extends MetadataType {
|
|
|
19
19
|
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
20
20
|
* @param {void} [_] unused parameter
|
|
21
21
|
* @param {void} [__] unused parameter
|
|
22
|
-
* @param {void} [___] unused parameter
|
|
23
22
|
* @param {string} [key] customer key of single item to retrieve
|
|
24
23
|
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
|
|
25
24
|
*/
|
|
26
|
-
static async retrieve(retrieveDir, _, __,
|
|
25
|
+
static async retrieve(retrieveDir, _, __, key) {
|
|
27
26
|
return super.retrieveREST(retrieveDir, '/automation/v1/dataextracts/', null, null, key);
|
|
28
27
|
}
|
|
29
28
|
/**
|
|
@@ -17,11 +17,10 @@ class DataExtractType extends MetadataType {
|
|
|
17
17
|
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
18
18
|
* @param {void} [_] unused parameter
|
|
19
19
|
* @param {void} [__] unused parameter
|
|
20
|
-
* @param {void} [___] unused parameter
|
|
21
20
|
* @param {string} [key] customer key of single item to retrieve
|
|
22
21
|
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
|
|
23
22
|
*/
|
|
24
|
-
static retrieve(retrieveDir, _, __,
|
|
23
|
+
static retrieve(retrieveDir, _, __, key) {
|
|
25
24
|
return super.retrieveREST(retrieveDir, '/automation/v1/dataextracttypes/', null, null, key);
|
|
26
25
|
}
|
|
27
26
|
/**
|
|
@@ -16,16 +16,15 @@ class Discovery extends MetadataType {
|
|
|
16
16
|
*
|
|
17
17
|
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
18
18
|
* @param {void} [_] not used
|
|
19
|
-
* @param {
|
|
20
|
-
* @param {void} [___] unused parameter
|
|
19
|
+
* @param {void} [__] unused parameter
|
|
21
20
|
* @param {string} [key] customer key of single item to retrieve
|
|
22
21
|
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise
|
|
23
22
|
*/
|
|
24
|
-
static async retrieve(retrieveDir, _,
|
|
23
|
+
static async retrieve(retrieveDir, _, __, key) {
|
|
25
24
|
if (key) {
|
|
26
25
|
Util.logger.error('Discovery.retrieve() does not support key parameter');
|
|
27
26
|
}
|
|
28
|
-
if (buObject.eid === buObject.mid) {
|
|
27
|
+
if (this.buObject.eid === this.buObject.mid) {
|
|
29
28
|
const res = await this.client.rest.getCollection(
|
|
30
29
|
Object.keys(this.definition.endPointMapping).map(
|
|
31
30
|
(endpoint) => this.definition.endPointMapping[endpoint]
|