mcdev 7.4.2 → 7.4.3

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 (77) hide show
  1. package/.github/ISSUE_TEMPLATE/bug.yml +1 -0
  2. package/@types/lib/metadataTypes/DataExtract.d.ts.map +1 -1
  3. package/@types/lib/metadataTypes/Event.d.ts.map +1 -1
  4. package/@types/lib/metadataTypes/Journey.d.ts +13 -0
  5. package/@types/lib/metadataTypes/Journey.d.ts.map +1 -1
  6. package/@types/lib/metadataTypes/Script.d.ts +2 -2
  7. package/@types/lib/metadataTypes/SendClassification.d.ts +6 -0
  8. package/@types/lib/metadataTypes/SendClassification.d.ts.map +1 -1
  9. package/@types/lib/metadataTypes/SenderProfile.d.ts +49 -6
  10. package/@types/lib/metadataTypes/SenderProfile.d.ts.map +1 -1
  11. package/@types/lib/metadataTypes/User.d.ts +10 -2
  12. package/@types/lib/metadataTypes/User.d.ts.map +1 -1
  13. package/@types/lib/metadataTypes/Verification.d.ts.map +1 -1
  14. package/@types/lib/metadataTypes/definitions/Journey.definition.d.ts +13 -0
  15. package/@types/lib/metadataTypes/definitions/Script.definition.d.ts +2 -2
  16. package/@types/lib/metadataTypes/definitions/SenderProfile.definition.d.ts +42 -6
  17. package/@types/lib/util/validations.d.ts.map +1 -1
  18. package/boilerplate/files/.prettierrc +6 -0
  19. package/boilerplate/files/eslint.config.js +18 -0
  20. package/boilerplate/forcedUpdates.json +4 -0
  21. package/lib/metadataTypes/DataExtract.js +29 -0
  22. package/lib/metadataTypes/Event.js +30 -0
  23. package/lib/metadataTypes/Journey.js +79 -32
  24. package/lib/metadataTypes/SendClassification.js +47 -16
  25. package/lib/metadataTypes/SenderProfile.js +49 -0
  26. package/lib/metadataTypes/User.js +74 -40
  27. package/lib/metadataTypes/Verification.js +15 -0
  28. package/lib/metadataTypes/definitions/DataExtract.definition.js +1 -1
  29. package/lib/metadataTypes/definitions/Event.definition.js +1 -1
  30. package/lib/metadataTypes/definitions/Journey.definition.js +14 -0
  31. package/lib/metadataTypes/definitions/Script.definition.js +4 -2
  32. package/lib/metadataTypes/definitions/SendClassification.definition.js +1 -1
  33. package/lib/metadataTypes/definitions/SenderProfile.definition.js +54 -21
  34. package/lib/metadataTypes/definitions/Verification.definition.js +2 -2
  35. package/lib/util/validations.js +3 -2
  36. package/package.json +1 -1
  37. package/test/general.test.js +21 -21
  38. package/test/mockRoot/.mcdevrc.json +1 -1
  39. package/test/resources/9999999/accountUser/retrieve-response.xml +104 -0
  40. package/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/patch-response.json +2 -2
  41. package/test/resources/9999999/automation/v1/dataextracts/post-response.json +2 -2
  42. package/test/resources/9999999/dataExtract/get-expected.json +2 -2
  43. package/test/resources/9999999/dataExtract/patch-expected.json +2 -2
  44. package/test/resources/9999999/dataExtract/post-expected.json +2 -2
  45. package/test/resources/9999999/event/get-expected.json +2 -2
  46. package/test/resources/9999999/interaction/v1/eventDefinitions/get-response.json +4 -4
  47. package/test/resources/9999999/journey/build-expected.json +1 -0
  48. package/test/resources/9999999/journey/get-multistep-expected.json +1 -0
  49. package/test/resources/9999999/journey/get-quicksend-expected.json +1 -0
  50. package/test/resources/9999999/journey/get-quicksend-rcb-id-expected.json +1 -0
  51. package/test/resources/9999999/journey/get-quicksend-rcb-key-expected.json +1 -0
  52. package/test/resources/9999999/journey/get-quicksend-rcb-name-expected.json +1 -0
  53. package/test/resources/9999999/journey/get-transactionalEmail-expected.json +1 -0
  54. package/test/resources/9999999/journey/template-expected.json +1 -0
  55. package/test/resources/9999999/sendClassification/retrieve-response.xml +4 -4
  56. package/test/resources/9999999/senderProfile/build-expected.json +1 -0
  57. package/test/resources/9999999/senderProfile/create-response.xml +1 -0
  58. package/test/resources/9999999/senderProfile/get-expected.json +4 -1
  59. package/test/resources/9999999/senderProfile/get-rcb-id-expected.json +3 -0
  60. package/test/resources/9999999/senderProfile/get-rcb-key-expected.json +3 -0
  61. package/test/resources/9999999/senderProfile/get-rcb-name-expected.json +3 -0
  62. package/test/resources/9999999/senderProfile/patch-expected.json +1 -0
  63. package/test/resources/9999999/senderProfile/post-expected.json +1 -0
  64. package/test/resources/9999999/senderProfile/retrieve-CustomerKey=Default-response.xml +5 -0
  65. package/test/resources/9999999/senderProfile/retrieve-response.xml +15 -0
  66. package/test/resources/9999999/senderProfile/template-expected.json +1 -0
  67. package/test/resources/9999999/senderProfile/update-response.xml +1 -0
  68. package/test/resources/9999999/verification/get-expected.json +1 -0
  69. package/test/resources/9999999/verification/patch-expected.json +1 -0
  70. package/test/resources/9999999/verification/post-expected.json +1 -0
  71. package/test/type.automation.test.js +4 -4
  72. package/test/type.dataExtract.test.js +4 -4
  73. package/test/type.event.test.js +6 -6
  74. package/test/type.journey.test.js +11 -11
  75. package/test/type.senderProfile.test.js +6 -6
  76. package/test/type.user.test.js +2 -2
  77. package/test/type.verification.test.js +3 -3
@@ -854,8 +854,21 @@ class Journey extends MetadataType {
854
854
  }
855
855
  // delivery profile
856
856
  if (triggeredSend.deliveryProfileId) {
857
- // remove it because we cannot resolve it and it should be set by selecting the sendClassification
858
- delete triggeredSend.deliveryProfileId;
857
+ try {
858
+ triggeredSend.r__deliveryProfile_key = cache.searchForField(
859
+ 'deliveryProfile',
860
+ triggeredSend.deliveryProfileId,
861
+ 'ObjectID',
862
+ 'key'
863
+ );
864
+ delete triggeredSend.deliveryProfileId;
865
+ } catch {
866
+ Util.logger.warn(
867
+ ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${
868
+ metadata[this.definition.keyField]
869
+ }): Dependent deliveryProfile was not found. Please note that this can only be resolved if you have at least ONE Send Classification set up on the target BU that uses this Delivery Profile.`
870
+ );
871
+ }
859
872
  }
860
873
  // message priority
861
874
  if (triggeredSend.priority) {
@@ -1150,6 +1163,8 @@ class Journey extends MetadataType {
1150
1163
  delete activity.metaData.highThroughput.r__dataExtension_key;
1151
1164
  }
1152
1165
 
1166
+ this._preDeployTasks_activities(metadata);
1167
+
1153
1168
  break;
1154
1169
  }
1155
1170
  default: {
@@ -1306,6 +1321,25 @@ class Journey extends MetadataType {
1306
1321
  );
1307
1322
  delete triggeredSend.r__sendClassification_key;
1308
1323
  }
1324
+ // delivery profile
1325
+ if (triggeredSend.r__deliveryProfile_key) {
1326
+ // remove it because we cannot resolve it and it should be set by selecting the sendClassification
1327
+ try {
1328
+ triggeredSend.deliveryProfileId = cache.searchForField(
1329
+ 'deliveryProfile',
1330
+ triggeredSend.r__deliveryProfile_key,
1331
+ 'key',
1332
+ 'ObjectID'
1333
+ );
1334
+ delete triggeredSend.r__deliveryProfile_key;
1335
+ } catch (ex) {
1336
+ Util.logger.error(
1337
+ `Could not find the ID for Delivery Profile '${triggeredSend.r__deliveryProfile_key}'. Please note that this can only be resolved if you have at least ONE Send Classification set up on the target BU that uses a Delivery Profile with this key.`
1338
+ );
1339
+ throw ex;
1340
+ }
1341
+ }
1342
+
1309
1343
  // message priority
1310
1344
  if (triggeredSend.c__priority) {
1311
1345
  triggeredSend.priority =
@@ -1824,41 +1858,54 @@ class Journey extends MetadataType {
1824
1858
  }).start();
1825
1859
  const transactionalKeyArr = (await Promise.all(resultsTransactional)).filter(Boolean);
1826
1860
  spinner.success('done.');
1827
- executedKeyArr.push(...transactionalKeyArr);
1828
1861
 
1829
- Util.logger.info('Retrieving relevant journeys');
1830
- const retriever = new Retriever(this.properties, this.buObject);
1862
+ // if all publish actions failed, we don't need to re-retrieve anything here
1863
+ if (transactionalKeyArr.length) {
1864
+ executedKeyArr.push(...transactionalKeyArr);
1831
1865
 
1832
- try {
1833
- const updatedJourneyRetrieve = await retriever.retrieve(
1834
- ['journey'],
1835
- transactionalKeyArr
1836
- );
1866
+ Util.logger.info('Retrieving relevant journeys');
1867
+ const retriever = new Retriever(this.properties, this.buObject);
1837
1868
 
1838
- /** @type {MetadataTypeItem[]} */
1839
- const updatedJourneys = Object.values(updatedJourneyRetrieve?.journey[0]);
1840
- if (updatedJourneys) {
1841
- const updatedTransactionalEmails = [];
1842
- for (const journey of updatedJourneys) {
1843
- updatedTransactionalEmails.push(
1844
- journey.activities?.[0]?.configurationArguments
1845
- ?.r__transactionalEmail_key
1846
- );
1847
- }
1848
- if (updatedTransactionalEmails.filter(Boolean).length) {
1849
- Util.logger.info('Retrieving relevant transactionalEmails');
1850
- await retriever.retrieve(
1851
- ['transactionalEmail'],
1852
- updatedTransactionalEmails.filter(Boolean)
1853
- );
1854
- } else {
1855
- Util.logger.error(
1856
- `Could not find transactional Emails for the published journeys`
1857
- );
1869
+ try {
1870
+ const updatedJourneyRetrieve = await retriever.retrieve(
1871
+ ['journey'],
1872
+ transactionalKeyArr
1873
+ );
1874
+
1875
+ /** @type {MetadataTypeItem[]} */
1876
+ const updatedJourneys =
1877
+ updatedJourneyRetrieve?.journey?.length > 1
1878
+ ? Object.values(
1879
+ updatedJourneyRetrieve?.journey.reduce(
1880
+ (previousValue, currentValue) =>
1881
+ Object.assign(previousValue, currentValue),
1882
+ {}
1883
+ )
1884
+ )
1885
+ : Object.values(updatedJourneyRetrieve?.journey[0]);
1886
+ if (updatedJourneys) {
1887
+ const updatedTransactionalEmails = [];
1888
+ for (const journey of updatedJourneys) {
1889
+ updatedTransactionalEmails.push(
1890
+ journey.activities?.[0]?.configurationArguments
1891
+ ?.r__transactionalEmail_key
1892
+ );
1893
+ }
1894
+ if (updatedTransactionalEmails.filter(Boolean).length) {
1895
+ Util.logger.info('Retrieving relevant transactionalEmails');
1896
+ await retriever.retrieve(
1897
+ ['transactionalEmail'],
1898
+ updatedTransactionalEmails.filter(Boolean)
1899
+ );
1900
+ } else {
1901
+ Util.logger.error(
1902
+ `Could not find transactional Emails for the published journeys`
1903
+ );
1904
+ }
1858
1905
  }
1906
+ } catch (ex) {
1907
+ Util.logger.errorStack(ex, 'retrieve failed');
1859
1908
  }
1860
- } catch (ex) {
1861
- Util.logger.errorStack(ex, 'retrieve failed');
1862
1909
  }
1863
1910
  }
1864
1911
  Util.logger.info(
@@ -47,6 +47,20 @@ class SendClassification extends MetadataType {
47
47
  return super.retrieveSOAP(retrieveDir, requestParams, key);
48
48
  }
49
49
 
50
+ /**
51
+ * Retrieves event definition metadata for caching
52
+ *
53
+ * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata
54
+ */
55
+ static async retrieveForCache() {
56
+ const typeMap = await this.retrieve(null);
57
+ for (const item of Object.values(typeMap.metadata)) {
58
+ // run postRetrieveTasks to cross-update deliveryProfile cache
59
+ this.postRetrieveTasks(item);
60
+ }
61
+ return typeMap;
62
+ }
63
+
50
64
  /**
51
65
  * Updates a single item
52
66
  *
@@ -100,13 +114,15 @@ class SendClassification extends MetadataType {
100
114
  };
101
115
  delete metadata.r__senderProfile_key;
102
116
 
117
+ const dpId = cache.searchForField(
118
+ 'deliveryProfile',
119
+ metadata.r__deliveryProfile_key,
120
+ 'key',
121
+ 'ObjectID'
122
+ );
103
123
  metadata.DeliveryProfile = {
104
- CustomerKey: cache.searchForField(
105
- 'deliveryProfile',
106
- metadata.r__deliveryProfile_key,
107
- 'key',
108
- 'key'
109
- ),
124
+ ObjectID: dpId,
125
+ CustomerKey: metadata.r__deliveryProfile_key,
110
126
  };
111
127
  delete metadata.r__deliveryProfile_key;
112
128
 
@@ -126,16 +142,21 @@ class SendClassification extends MetadataType {
126
142
  );
127
143
  delete metadata.SendClassificationType;
128
144
 
129
- try {
130
- metadata.r__senderProfile_key = cache.searchForField(
131
- 'senderProfile',
132
- metadata.SenderProfile.ObjectID,
133
- 'ObjectID',
134
- 'CustomerKey'
135
- );
136
- delete metadata.SenderProfile;
137
- } catch (ex) {
138
- Util.logger.warn(` - ${this.definition.type} ${metadata.CustomerKey}: ${ex.message}`);
145
+ if (cache.getCache().senderProfile) {
146
+ // when sendClassification was only cached it can happen that we don't have the senderProfile cache yet
147
+ try {
148
+ metadata.r__senderProfile_key = cache.searchForField(
149
+ 'senderProfile',
150
+ metadata.SenderProfile.ObjectID,
151
+ 'ObjectID',
152
+ 'CustomerKey'
153
+ );
154
+ delete metadata.SenderProfile;
155
+ } catch (ex) {
156
+ Util.logger.warn(
157
+ ` - ${this.definition.type} ${metadata.CustomerKey}: ${ex.message}`
158
+ );
159
+ }
139
160
  }
140
161
  try {
141
162
  metadata.r__deliveryProfile_key = cache.searchForField(
@@ -144,6 +165,16 @@ class SendClassification extends MetadataType {
144
165
  'key',
145
166
  'key'
146
167
  );
168
+ // add ObjectID to deliveryProfile cache because it cannot be retrieved any other way and this way we can resolve it in journeys
169
+ const dp = cache.getByKey('deliveryProfile', metadata.DeliveryProfile.CustomerKey);
170
+ if (dp) {
171
+ dp.ObjectID = metadata.DeliveryProfile.ObjectID;
172
+ } else {
173
+ Util.logger.debug(
174
+ ` - ${this.definition.type} ${metadata.CustomerKey}: Could not find deliveryProfile ${metadata.DeliveryProfile.CustomerKey} in cache`
175
+ );
176
+ }
177
+
147
178
  delete metadata.DeliveryProfile;
148
179
  } catch (ex) {
149
180
  Util.logger.warn(` - ${this.definition.type} ${metadata.CustomerKey}: ${ex.message}`);
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  import MetadataType from './MetadataType.js';
4
+ import cache from '../util/cache.js';
4
5
  import { Util } from '../util/util.js';
5
6
  import ReplaceCbReference from '../util/replaceContentBlockReference.js';
6
7
 
@@ -77,6 +78,50 @@ class SenderProfile extends MetadataType {
77
78
  return super.deleteByKeySOAP(customerKey);
78
79
  }
79
80
 
81
+ /**
82
+ * manages post retrieve steps
83
+ *
84
+ * @param {MetadataTypeItem} metadata a single item
85
+ * @returns {MetadataTypeItem} a single item
86
+ */
87
+ static postRetrieveTasks(metadata) {
88
+ // makes or easier reading
89
+ if (metadata.Client) {
90
+ try {
91
+ metadata.createdBy = cache.searchForField(
92
+ 'user',
93
+ metadata.Client.CreatedBy,
94
+ 'AccountUserID',
95
+ 'Name'
96
+ );
97
+ } catch (ex) {
98
+ Util.logger.verbose(
99
+ ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${
100
+ metadata[this.definition.keyField]
101
+ }): ${ex.message}.`
102
+ );
103
+ }
104
+
105
+ try {
106
+ metadata.modifiedBy = cache.searchForField(
107
+ 'user',
108
+ metadata.Client.ModifiedBy,
109
+ 'AccountUserID',
110
+ 'Name'
111
+ );
112
+ } catch (ex) {
113
+ Util.logger.verbose(
114
+ ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${
115
+ metadata[this.definition.keyField]
116
+ }): ${ex.message}.`
117
+ );
118
+ }
119
+
120
+ delete metadata.Client;
121
+ }
122
+ return metadata;
123
+ }
124
+
80
125
  /**
81
126
  * prepares a single item for deployment
82
127
  *
@@ -84,6 +129,10 @@ class SenderProfile extends MetadataType {
84
129
  * @returns {Promise.<MetadataTypeItem>} Promise
85
130
  */
86
131
  static async preDeployTasks(metadata) {
132
+ // cleanup
133
+ delete metadata.createdBy;
134
+ delete metadata.modifiedBy;
135
+
87
136
  if (
88
137
  metadata.UseDefaultRMMRules &&
89
138
  (metadata.AutoForwardToEmailAddress !== '' || metadata.AutoForwardToName !== '')
@@ -33,6 +33,7 @@ import cache from '../util/cache.js';
33
33
  */
34
34
  class User extends MetadataType {
35
35
  static userBUassignments;
36
+ static userIdBuMap;
36
37
 
37
38
  /**
38
39
  * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata
@@ -44,7 +45,8 @@ class User extends MetadataType {
44
45
  * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata
45
46
  */
46
47
  static async retrieve(retrieveDir, _, __, key) {
47
- if (this.buObject.eid !== this.buObject.mid) {
48
+ if (retrieveDir && this.buObject.eid !== this.buObject.mid) {
49
+ // only skip if this was not for caching
48
50
  Util.logger.info(' - Skipping User retrieval on non-parent BU');
49
51
  return;
50
52
  }
@@ -217,6 +219,22 @@ class User extends MetadataType {
217
219
  return metadata;
218
220
  }
219
221
 
222
+ /**
223
+ * MetadataType upsert, after retrieving from target and comparing to check if create or update operation is needed.
224
+ *
225
+ * @param {MetadataTypeMap} metadataMap metadata mapped by their keyField
226
+ * @param {string} deployDir directory where deploy metadata are saved
227
+ * @param {boolean} [runUpsertSequentially] when a type has self-dependencies creates need to run one at a time and created/changed keys need to be cached to ensure following creates/updates have thoses keys available
228
+ * @returns {Promise.<MetadataTypeMap>} keyField => metadata map
229
+ */
230
+ static async upsert(metadataMap, deployDir, runUpsertSequentially = false) {
231
+ if (typeof this.userIdBuMap !== 'object' || Object.keys(this.userIdBuMap).length === 0) {
232
+ this.cacheBusinessUnitAssignments();
233
+ }
234
+
235
+ return super.upsert(metadataMap, deployDir, runUpsertSequentially);
236
+ }
237
+
220
238
  /**
221
239
  * helper for {@link MetadataType.upsert}
222
240
  *
@@ -256,6 +274,7 @@ class User extends MetadataType {
256
274
  }
257
275
 
258
276
  /**
277
+ * helper for {@link createOrUpdate}
259
278
  *
260
279
  * @private
261
280
  * @param {MetadataTypeItem} metadata single metadata itme
@@ -313,7 +332,7 @@ class User extends MetadataType {
313
332
  }
314
333
 
315
334
  /**
316
- * create/update business unit assignments
335
+ * create/update business unit assignments. helper for {@link postDeployTasks}
317
336
  *
318
337
  * @private
319
338
  * @param {UserDocumentMap} upsertResults metadata mapped by their keyField
@@ -589,7 +608,6 @@ class User extends MetadataType {
589
608
  * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata
590
609
  */
591
610
  static async _retrieve(retrieveDir, key) {
592
- this.userIdBuMap = {};
593
611
  /** @type {SoapRequestParams} */
594
612
  const requestParams = {
595
613
  QueryAllAccounts: true,
@@ -693,50 +711,18 @@ class User extends MetadataType {
693
711
  }
694
712
 
695
713
  const metadata = this.parseResponseBody(resultsBulk);
696
- // get BUs that each users have access to
697
- if (resultsBulk?.Results?.length > 0) {
714
+ if (retrieveDir) {
698
715
  if (!singleRetrieve) {
699
716
  Util.logger.info(
700
717
  Util.getGrayMsg(` - found ${resultsBulk?.Results.length} users`)
701
718
  );
702
719
  }
703
- // split array resultsBulk?.Results into chunks to avoid not getting all roles
704
- const chunkSize = 100;
705
- this.userIdBuMap = {};
706
- Util.logger.info(` - Caching dependent Metadata: Business Unit assignments`);
707
- for (let i = 0; i < resultsBulk?.Results?.length; i += chunkSize) {
708
- if (i > 0) {
709
- Util.logger.info(
710
- Util.getGrayMsg(` - Requesting next batch (retrieved BUs for ${i} users)`)
711
- );
712
- }
713
- const chunk = resultsBulk?.Results?.slice(i, i + chunkSize);
714
- const resultsBatch = (
715
- await this.client.soap.retrieveBulk(
716
- 'AccountUserAccount',
717
- ['AccountUser.AccountUserID', 'Account.ID'],
718
- {
719
- filter: {
720
- leftOperand: 'AccountUser.AccountUserID',
721
- operator: chunk.length > 1 ? 'IN' : 'equals', // API does not allow IN for single item
722
- rightOperand: chunk.map((item) => item.AccountUserID),
723
- },
724
- }
725
- )
726
- ).Results;
727
- for (const item of resultsBatch) {
728
- this.userIdBuMap[item.AccountUser.AccountUserID] ||= [];
729
- // push to array if not already in array
730
- if (
731
- !this.userIdBuMap[item.AccountUser.AccountUserID].includes(item.Account.ID)
732
- ) {
733
- this.userIdBuMap[item.AccountUser.AccountUserID].push(item.Account.ID);
734
- }
735
- }
720
+ if (resultsBulk?.Results?.length > 0) {
721
+ // get BUs that each users have access to
722
+ // split array resultsBulk?.Results into chunks to avoid not getting all roles
723
+ await this.cacheBusinessUnitAssignments(resultsBulk.Results);
736
724
  }
737
- }
738
725
 
739
- if (retrieveDir) {
740
726
  const savedMetadata = await this.saveResults(metadata, retrieveDir, null);
741
727
  Util.logger.info(
742
728
  `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` +
@@ -771,6 +757,54 @@ class User extends MetadataType {
771
757
  return { metadata: metadata, type: this.definition.type };
772
758
  }
773
759
 
760
+ /**
761
+ * helper for {@link retrieveSOAP} and {@link upsert}; populates userIdBuMap
762
+ *
763
+ * @param {MetadataTypeItem[]} [metadataList] -
764
+ * @returns {Promise.<void>} -
765
+ */
766
+ static async cacheBusinessUnitAssignments(metadataList) {
767
+ if (!metadataList) {
768
+ // if run via upsert() then we won't have the metadataList with AccountUserID anywhere but in cache
769
+ const cacheUsers = cache.getCache().user;
770
+ metadataList = cacheUsers ? Object.values(cacheUsers) : [];
771
+ }
772
+ const chunkSize = 100;
773
+ this.userIdBuMap = {};
774
+ Util.logger.info(` - Caching dependent Metadata: Business Unit assignments`);
775
+ for (let i = 0; i < metadataList?.length; i += chunkSize) {
776
+ if (i > 0) {
777
+ Util.logger.info(
778
+ Util.getGrayMsg(` - Requesting next batch (retrieved BUs for ${i} users)`)
779
+ );
780
+ }
781
+ const accountUserIDList = metadataList
782
+ .map((item) => item.AccountUserID)
783
+ .filter(Boolean);
784
+ const chunk = accountUserIDList?.slice(i, i + chunkSize);
785
+ const resultsBatch = (
786
+ await this.client.soap.retrieveBulk(
787
+ 'AccountUserAccount',
788
+ ['AccountUser.AccountUserID', 'Account.ID'],
789
+ {
790
+ filter: {
791
+ leftOperand: 'AccountUser.AccountUserID',
792
+ operator: chunk.length > 1 ? 'IN' : 'equals', // API does not allow IN for single item
793
+ rightOperand: chunk,
794
+ },
795
+ }
796
+ )
797
+ ).Results;
798
+ for (const item of resultsBatch) {
799
+ this.userIdBuMap[item.AccountUser.AccountUserID] ||= [];
800
+ // push to array if not already in array
801
+ if (!this.userIdBuMap[item.AccountUser.AccountUserID].includes(item.Account.ID)) {
802
+ this.userIdBuMap[item.AccountUser.AccountUserID].push(item.Account.ID);
803
+ }
804
+ }
805
+ }
806
+ }
807
+
774
808
  /**
775
809
  * helper for {@link User.retrieveSOAP}
776
810
  *
@@ -217,6 +217,21 @@ class Verification extends MetadataType {
217
217
  * @returns {VerificationItem} Array with one metadata object and one sql string
218
218
  */
219
219
  static postRetrieveTasks(metadata) {
220
+ try {
221
+ // @ts-expect-error
222
+ metadata.createdBy = cache.searchForField(
223
+ 'user',
224
+ metadata.createdBy,
225
+ 'AccountUserID',
226
+ 'Name'
227
+ );
228
+ } catch (ex) {
229
+ Util.logger.verbose(
230
+ ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${
231
+ metadata[this.definition.keyField]
232
+ }): ${ex.message}.`
233
+ );
234
+ }
220
235
  try {
221
236
  metadata.r__dataExtension_key = cache.searchForField(
222
237
  'dataExtension',
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  bodyIteratorField: 'items',
3
- dependencies: ['dataExtractType'],
3
+ dependencies: ['dataExtractType', 'user'],
4
4
  dependencyGraph: null, // dataExtractType cannot be deployed
5
5
  hasExtended: true,
6
6
  idField: 'dataExtractDefinitionId',
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  bodyIteratorField: 'items',
3
- dependencies: ['dataExtension'],
3
+ dependencies: ['dataExtension', 'user'],
4
4
  dependencyGraph: { dataExtension: ['r__dataExtension_key'] },
5
5
  hasExtended: false,
6
6
  idField: 'id',
@@ -9,6 +9,7 @@ export default {
9
9
  'folder-journey',
10
10
  'triggeredSend', // for EMAILV2-activity
11
11
  'dataExtension', // for transactionalEmails: EMAILV2-activity
12
+ 'deliveryProfile',
12
13
  'event', // for Multistep and Quicksend journeys
13
14
  'mobileMessage', // for SMSSYNC-activity
14
15
  'mobileCode', // for SMSSYNC-activity
@@ -27,6 +28,7 @@ export default {
27
28
  'activities.metaData.highThroughput.r__dataExtension_key',
28
29
  'activities.configurationArguments.triggeredSend.r__dataExtension_key.domainExclusions',
29
30
  ],
31
+ deliveryProfile: ['activities.configurationArguments.triggeredSend.r__deliveryProfile_key'],
30
32
  list: [
31
33
  'activities.configurationArguments.triggeredSend.r__list_PathName.publicationList',
32
34
  'activities.configurationArguments.triggeredSend.r__list_PathName.suppressionLists',
@@ -303,6 +305,12 @@ export default {
303
305
  retrieving: true,
304
306
  template: true,
305
307
  },
308
+ 'activities[].configurationArguments.triggeredSend.deliveryProfileId': {
309
+ isCreateable: true,
310
+ isUpdateable: true,
311
+ retrieving: true,
312
+ template: true,
313
+ },
306
314
  'activities[].configurationArguments.triggeredSend.r__senderProfile_key': {
307
315
  isCreateable: false,
308
316
  isUpdateable: false,
@@ -315,6 +323,12 @@ export default {
315
323
  retrieving: true,
316
324
  template: true,
317
325
  },
326
+ 'activities[].configurationArguments.triggeredSend.r__deliveryProfile_key': {
327
+ isCreateable: false,
328
+ isUpdateable: false,
329
+ retrieving: true,
330
+ template: true,
331
+ },
318
332
  'activities[].configurationArguments.triggeredSend.r__sendClassification_key': {
319
333
  isCreateable: false,
320
334
  isUpdateable: false,
@@ -10,9 +10,9 @@ export default {
10
10
  nameField: 'name',
11
11
  folderIdField: 'categoryId',
12
12
  createdDateField: 'createdDate',
13
- createdNameField: 'createdBy',
13
+ createdNameField: null,
14
14
  lastmodDateField: 'modifiedDate',
15
- lastmodNameField: 'modifiedBy',
15
+ lastmodNameField: null,
16
16
  restPagination: true,
17
17
  type: 'script',
18
18
  typeDescription: 'Execute more complex tasks via SSJS or AMPScript.',
@@ -26,6 +26,7 @@ export default {
26
26
  template: true,
27
27
  },
28
28
  createdBy: {
29
+ // not existing in rest api
29
30
  isCreateable: false,
30
31
  isUpdateable: false,
31
32
  retrieving: false,
@@ -56,6 +57,7 @@ export default {
56
57
  template: true,
57
58
  },
58
59
  modifiedBy: {
60
+ // not existing in rest api
59
61
  isCreateable: false,
60
62
  isUpdateable: false,
61
63
  retrieving: false,
@@ -104,7 +104,7 @@ export default {
104
104
  'DeliveryProfile.ObjectID': {
105
105
  isCreateable: false,
106
106
  isUpdateable: false,
107
- retrieving: false,
107
+ retrieving: true,
108
108
  template: false,
109
109
  },
110
110
  HonorPublicationListOptOutsForTransactionalSends: {