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.
Files changed (95) hide show
  1. package/.github/ISSUE_TEMPLATE/bug.yml +2 -0
  2. package/.github/PULL_REQUEST_TEMPLATE.md +1 -2
  3. package/.github/pr-labeler.yml +3 -0
  4. package/.github/workflows/close_issues_on_merge.yml +18 -0
  5. package/.github/workflows/pr-labeler.yml +19 -0
  6. package/LICENSE +1 -1
  7. package/README.md +1 -1
  8. package/docs/dist/documentation.md +700 -281
  9. package/lib/Deployer.js +21 -15
  10. package/lib/Retriever.js +23 -19
  11. package/lib/cli.js +36 -6
  12. package/lib/index.js +56 -10
  13. package/lib/metadataTypes/AccountUser.js +17 -23
  14. package/lib/metadataTypes/Asset.js +28 -21
  15. package/lib/metadataTypes/AttributeGroup.js +1 -2
  16. package/lib/metadataTypes/Automation.js +75 -37
  17. package/lib/metadataTypes/Campaign.js +4 -3
  18. package/lib/metadataTypes/ContentArea.js +2 -3
  19. package/lib/metadataTypes/DataExtension.js +56 -47
  20. package/lib/metadataTypes/DataExtensionField.js +9 -12
  21. package/lib/metadataTypes/DataExtensionTemplate.js +2 -3
  22. package/lib/metadataTypes/DataExtract.js +1 -2
  23. package/lib/metadataTypes/DataExtractType.js +1 -2
  24. package/lib/metadataTypes/Discovery.js +3 -4
  25. package/lib/metadataTypes/Email.js +20 -6
  26. package/lib/metadataTypes/EmailSendDefinition.js +5 -8
  27. package/lib/metadataTypes/EventDefinition.js +29 -2
  28. package/lib/metadataTypes/FileTransfer.js +1 -2
  29. package/lib/metadataTypes/Filter.js +1 -2
  30. package/lib/metadataTypes/Folder.js +12 -14
  31. package/lib/metadataTypes/FtpLocation.js +1 -2
  32. package/lib/metadataTypes/ImportFile.js +1 -2
  33. package/lib/metadataTypes/Interaction.js +678 -12
  34. package/lib/metadataTypes/List.js +36 -33
  35. package/lib/metadataTypes/MetadataType.js +170 -124
  36. package/lib/metadataTypes/MobileCode.js +1 -2
  37. package/lib/metadataTypes/MobileKeyword.js +1 -2
  38. package/lib/metadataTypes/Query.js +15 -6
  39. package/lib/metadataTypes/Role.js +10 -11
  40. package/lib/metadataTypes/Script.js +2 -5
  41. package/lib/metadataTypes/SetDefinition.js +1 -2
  42. package/lib/metadataTypes/TransactionalMessage.js +25 -32
  43. package/lib/metadataTypes/TransactionalSMS.js +3 -4
  44. package/lib/metadataTypes/TriggeredSendDefinition.js +232 -56
  45. package/lib/metadataTypes/definitions/Asset.definition.js +1 -1
  46. package/lib/metadataTypes/definitions/Automation.definition.js +1 -1
  47. package/lib/metadataTypes/definitions/DataExtension.definition.js +10 -1
  48. package/lib/metadataTypes/definitions/Email.definition.js +1 -1
  49. package/lib/metadataTypes/definitions/EmailSendDefinition.definition.js +1 -1
  50. package/lib/metadataTypes/definitions/EventDefinition.definition.js +40 -1
  51. package/lib/metadataTypes/definitions/Folder.definition.js +31 -0
  52. package/lib/metadataTypes/definitions/ImportFile.definition.js +1 -1
  53. package/lib/metadataTypes/definitions/Interaction.definition.js +47 -26
  54. package/lib/metadataTypes/definitions/List.definition.js +1 -1
  55. package/lib/metadataTypes/definitions/Query.definition.js +1 -1
  56. package/lib/metadataTypes/definitions/Script.definition.js +1 -1
  57. package/lib/metadataTypes/definitions/TransactionalEmail.definition.js +2 -1
  58. package/lib/metadataTypes/definitions/TransactionalPush.definition.js +2 -1
  59. package/lib/metadataTypes/definitions/TransactionalSMS.definition.js +2 -1
  60. package/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js +10 -2
  61. package/lib/util/auth.js +10 -2
  62. package/lib/util/cli.js +4 -1
  63. package/lib/util/file.js +7 -3
  64. package/lib/util/init.js +62 -0
  65. package/lib/util/util.js +131 -11
  66. package/package.json +22 -9
  67. package/test/dataExtension.test.js +10 -10
  68. package/test/interaction.test.js +123 -0
  69. package/test/mockRoot/.mcdevrc.json +1 -1
  70. package/test/mockRoot/deploy/testInstance/testBU/interaction/testExisting_interaction.interaction-meta.json +266 -0
  71. package/test/mockRoot/deploy/testInstance/testBU/interaction/testNew_interaction.interaction-meta.json +266 -0
  72. package/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json +0 -3
  73. package/test/query.test.js +8 -8
  74. package/test/resourceFactory.js +12 -7
  75. package/test/resources/1111111/dataExtension/retrieve-response.xml +26 -0
  76. package/test/resources/9999999/data/v1/customobjectdata/key/childBU_dataextension_test/rowset/get-response.json +13 -0
  77. package/test/resources/9999999/dataFolder/retrieve-response.xml +22 -0
  78. package/test/resources/9999999/eventDefinition/get-expected.json +34 -0
  79. package/test/resources/9999999/interaction/build-expected.json +260 -0
  80. package/test/resources/9999999/interaction/get-expected.json +264 -0
  81. package/test/resources/9999999/interaction/post-expected.json +264 -0
  82. package/test/resources/9999999/interaction/put-expected.json +264 -0
  83. package/test/resources/9999999/interaction/template-expected.json +260 -0
  84. package/test/resources/9999999/interaction/v1/EventDefinitions/get-response.json +43 -0
  85. package/test/resources/9999999/interaction/v1/interactions/get-response.json +222 -3
  86. package/test/resources/9999999/interaction/v1/interactions/post-response.json +280 -0
  87. package/test/resources/9999999/interaction/v1/interactions/put-response.json +280 -0
  88. package/test/resources/9999999/messaging/v1/email/definitions/post-response.json +1 -1
  89. package/test/resources/9999999/query/post-expected.sql +1 -1
  90. package/test/resources/9999999/transactionalEmail/post-expected.json +1 -1
  91. package/test/transactionalEmail.test.js +7 -7
  92. package/test/transactionalPush.test.js +7 -7
  93. package/test/transactionalSMS.test.js +7 -7
  94. package/test/utils.js +50 -0
  95. 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, _, __, ___, key) {
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
- this.client.rest.get('/automation/v1/automations/' + a.ObjectID)
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(this.buObject, savedMetadata);
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
- try {
249
- metadata.categoryId = cache.searchForField(
250
- 'folder',
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(buObject, metadata) {
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, _, __, ___, key) {
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(`Downloaded: campaignAssets (${campaignAssets.flat().length})`);
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, _, __, ___, key) {
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, null, requestParams);
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, _, buObject) {
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 de-fields to properly handle add/update/delete of fields
33
- await this._attachFields(targetMetadata);
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, buObject, _, key) {
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(buObjectParentBu, [
364
- 'shared_data',
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(buObject, savedMetadata);
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(buObject, additionalFields) {
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
- metadata.CategoryID = cache.searchForField('folder', metadata.r__folder_Path, 'Path', 'ID');
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(buObject, metadata) {
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(buObject, customerKey) {
829
- return super.deleteByKeySOAP(buObject, customerKey, false);
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(buObject, customerKey) {
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(buObject) {
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, null, options, additionalFields);
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, buObject) {
22
- return super.retrieveSOAP(retrieveDir, buObject, null, additionalFields);
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, null, requestParams, additionalFields);
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.debug(
246
- `${deployColumns.length} Fields added/updated for [${deKey}]${
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(buObject, customerKey) {
261
- return this.deleteByKeySOAP(buObject, customerKey, false);
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(buObject, customerKey, handleOutside) {
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(buObject, customerKey);
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, _, __, ___, key) {
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, null, requestParams);
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, _, __, ___, key) {
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, _, __, ___, key) {
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 {TYPE.BuObject} buObject properties for auth
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, _, buObject, ___, key) {
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]