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
package/lib/Deployer.js CHANGED
@@ -238,38 +238,44 @@ class Deployer {
238
238
  Object.keys(this.metadata)
239
239
  );
240
240
  }
241
- const foundDeployTypes = Object.keys(this.metadata).map((item) =>
242
- item === 'asset' && Util.includesStartsWith(typeArr, item)
243
- ? typeArr[Util.includesStartsWithIndex(typeArr, item)]
244
- : item
245
- );
241
+ const foundDeployTypes = Object.keys(this.metadata)
242
+ .map((type) =>
243
+ type === 'asset' && Util.includesStartsWith(typeArr, type)
244
+ ? typeArr[Util.includesStartsWithIndex(typeArr, type)]
245
+ : type
246
+ )
247
+ // remove empty types
248
+ .filter((type) => Object.keys(this.metadata[type]).length);
249
+ if (!foundDeployTypes.length) {
250
+ throw new Error('No metadata found for deployment');
251
+ }
246
252
  const deployOrder = Util.getMetadataHierachy(foundDeployTypes);
247
253
  // build cache, including all metadata types which will be deployed (Avoids retrieve later)
248
- for (const metadataType of deployOrder) {
249
- const [type, subType] = metadataType.split('-');
254
+ for (const metadataType in deployOrder) {
255
+ const type = metadataType;
256
+ const subTypeArr = deployOrder[metadataType];
250
257
  // add metadata & client to metadata process class instead of passing cache/mapping every time
251
258
  MetadataTypeInfo[type].client = auth.getSDK(this.buObject);
252
259
  MetadataTypeInfo[type].properties = this.properties;
253
260
  MetadataTypeInfo[type].buObject = this.buObject;
254
- Util.logger.info('Caching dependent Metadata: ' + metadataType);
255
- const result = await MetadataTypeInfo[type].retrieveForCache(this.buObject, subType);
261
+ Util.logger.info(`Caching dependent Metadata: ${metadataType}`);
262
+ Util.logSubtypes(subTypeArr);
263
+ const result = await MetadataTypeInfo[type].retrieveForCache(null, subTypeArr);
256
264
  cache.setMetadata(type, result.metadata);
257
265
  }
258
266
  /** @type {TYPE.MultiMetadataTypeMap} */
259
267
  const multiMetadataTypeMap = {};
260
268
  // deploy metadata files, extending cache once deploys
261
- for (const metadataType of deployOrder) {
262
- // TODO rewrite to allow deploying only a specific sub-type
263
- // const [type, subType] = metadataType.split('-');
264
- const type = metadataType.split('-')[0];
269
+ for (const metadataType in deployOrder) {
270
+ // TODO rewrite to allow deploying only a specific sub-type; currently, subtypes are ignored when executing deploy
271
+ const type = metadataType;
265
272
  if (this.metadata[type]) {
266
273
  Util.logger.info('Deploying: ' + metadataType);
267
274
 
268
275
  const result = await MetadataTypeInfo[type].deploy(
269
276
  this.metadata[type],
270
277
  this.deployDir,
271
- this.retrieveDir,
272
- this.buObject
278
+ this.retrieveDir
273
279
  );
274
280
  multiMetadataTypeMap[type] = result;
275
281
  cache.mergeMetadata(type, result);
package/lib/Retriever.js CHANGED
@@ -59,16 +59,12 @@ class Retriever {
59
59
  // assuming TypeKeyCombo was provided
60
60
  typeKeyMap = namesOrKeys;
61
61
  }
62
- // defined colors for optionally printing the keys we filtered by
63
- const color = {
64
- reset: '\x1B[0m',
65
- dim: '\x1B[2m',
66
- };
67
62
  // ensure we know which real dependencies we have to ensure we cache those completely
68
63
  const dependencies = this._getTypeDependencies(metadataTypes);
69
-
70
- for (const metadataType of Util.getMetadataHierachy(metadataTypes)) {
71
- const [type, subType] = metadataType.split('-');
64
+ const deployOrder = Util.getMetadataHierachy(metadataTypes);
65
+ for (const metadataType in deployOrder) {
66
+ const type = metadataType;
67
+ const subTypeArr = deployOrder[metadataType];
72
68
  // if types were added by getMetadataHierachy() for caching, make sure the key-list is set to [null] for them which will retrieve all
73
69
  typeKeyMap[metadataType] = typeKeyMap[metadataType] || [null];
74
70
  // add client to metadata process class instead of passing every time
@@ -78,26 +74,36 @@ class Retriever {
78
74
  try {
79
75
  let result;
80
76
  if (!metadataTypes.includes(type) && !metadataTypes.includes(metadataType)) {
77
+ // type not in list of types to retrieve, but is a dependency of one of them
81
78
  if (changelogOnly && type !== 'folder') {
82
79
  // no extra caching needed for list view except for folders
83
80
  continue;
84
81
  }
85
82
  Util.logger.info(`Caching dependent Metadata: ${metadataType}`);
86
- result = await MetadataTypeInfo[type].retrieveForCache(this.buObject, subType);
83
+ Util.logSubtypes(subTypeArr);
84
+ result = await MetadataTypeInfo[type].retrieveForCache(null, subTypeArr);
87
85
  } else if (templateVariables) {
86
+ // type is in list of types to retrieve and we have template variables
88
87
  Util.logger.info(`Retrieving as Template: ${metadataType}`);
89
-
88
+ if (subTypeArr?.length > 1) {
89
+ Util.logger.warn(
90
+ `retrieveAsTemplate only works with one subtype, ignoring all but first subtype from your list: ${subTypeArr.join(
91
+ ', '
92
+ )}`
93
+ );
94
+ }
90
95
  result = await Promise.all(
91
96
  typeKeyMap[metadataType].map((name) =>
92
97
  MetadataTypeInfo[type].retrieveAsTemplate(
93
98
  this.templateDir,
94
99
  name,
95
100
  templateVariables,
96
- subType
101
+ subTypeArr?.[0]
97
102
  )
98
103
  )
99
104
  );
100
105
  } else {
106
+ // type is in list of types to retrieve and we don't have template variables
101
107
  let cacheResult = null;
102
108
  if (
103
109
  (typeKeyMap[metadataType].length > 1 ||
@@ -106,28 +112,26 @@ class Retriever {
106
112
  ) {
107
113
  // if we have a key-list and the type is a dependency, we need to cache the whole type
108
114
  Util.logger.info(`Caching dependent Metadata: ${metadataType}`);
115
+ Util.logSubtypes(subTypeArr);
109
116
  cacheResult = await MetadataTypeInfo[type].retrieveForCache(
110
- this.buObject,
111
- subType
117
+ null,
118
+ subTypeArr
112
119
  );
113
120
  }
114
121
  Util.logger.info(
115
122
  `Retrieving: ${metadataType}` +
116
123
  (typeKeyMap[metadataType][0] === null
117
124
  ? ''
118
- : ` ${color.dim}(Keys: ${typeKeyMap[metadataType].join(', ')})${
119
- color.reset
120
- }`)
125
+ : Util.getKeysString(typeKeyMap[metadataType]))
121
126
  );
122
127
  result = await (changelogOnly
123
- ? MetadataTypeInfo[type].retrieveChangelog(this.buObject, null, subType)
128
+ ? MetadataTypeInfo[type].retrieveChangelog(null, subTypeArr)
124
129
  : Promise.all(
125
130
  typeKeyMap[metadataType].map((key) =>
126
131
  MetadataTypeInfo[type].retrieve(
127
132
  this.savePath,
128
133
  null,
129
- this.buObject,
130
- subType,
134
+ subTypeArr,
131
135
  key
132
136
  )
133
137
  )
package/lib/cli.js CHANGED
@@ -84,6 +84,15 @@ yargs
84
84
  Mcdev.initProject(argv.credentialsName);
85
85
  },
86
86
  })
87
+ .command({
88
+ command: 'join',
89
+ desc: `clones an existing project from git`,
90
+ handler: (argv) => {
91
+ Mcdev.setSkipInteraction(argv.skipInteraction);
92
+ Mcdev.setLoggingLevel(argv);
93
+ Mcdev.joinProject();
94
+ },
95
+ })
87
96
  .command({
88
97
  command: 'reloadBUs [credentialsName]',
89
98
  aliases: ['rb'],
@@ -221,9 +230,7 @@ yargs
221
230
  handler: (argv) => {
222
231
  Mcdev.setSkipInteraction(argv.skipInteraction);
223
232
  Mcdev.setLoggingLevel(argv);
224
- const keyArr = csvToArray(argv.KEY);
225
-
226
- Mcdev.buildTemplate(argv.BU, argv.TYPE, keyArr, argv.MARKET);
233
+ Mcdev.buildTemplate(argv.BU, argv.TYPE, csvToArray(argv.KEY), argv.MARKET);
227
234
  },
228
235
  })
229
236
  .command({
@@ -345,9 +352,32 @@ yargs
345
352
  handler: (argv) => {
346
353
  Mcdev.setSkipInteraction(argv.skipInteraction);
347
354
  Mcdev.setLoggingLevel(argv);
348
- const keyArr = csvToArray(argv.KEY);
349
-
350
- Mcdev.getFilesToCommit(argv.BU, argv.TYPE, keyArr);
355
+ Mcdev.getFilesToCommit(argv.BU, argv.TYPE, csvToArray(argv.KEY));
356
+ },
357
+ })
358
+ .command({
359
+ command: 'refresh <BU> [TYPE] [KEY]',
360
+ aliases: ['re'],
361
+ desc: 'ensures that updates are properly published',
362
+ builder: (yargs) => {
363
+ yargs
364
+ .positional('BU', {
365
+ type: 'string',
366
+ describe: 'the business unit to execute the refresh on',
367
+ })
368
+ .positional('TYPE', {
369
+ type: 'string',
370
+ describe: 'metadata type',
371
+ })
372
+ .positional('KEY', {
373
+ type: 'string',
374
+ describe: 'key(s) of the metadata component(s)',
375
+ });
376
+ },
377
+ handler: (argv) => {
378
+ Mcdev.setSkipInteraction(argv.skipInteraction);
379
+ Mcdev.setLoggingLevel(argv);
380
+ Mcdev.refresh(argv.BU, argv.TYPE, csvToArray(argv.KEY));
351
381
  },
352
382
  })
353
383
  .command({
package/lib/index.js CHANGED
@@ -147,7 +147,7 @@ class Mcdev {
147
147
  if (
148
148
  properties.credentials &&
149
149
  (!properties.credentials[cred] ||
150
- (bu !== '*' && properties.credentials[cred].businessUnits[bu]))
150
+ (bu !== '*' && !properties.credentials[cred].businessUnits[bu]))
151
151
  ) {
152
152
  const buObject = await Cli.getCredentialObject(
153
153
  properties,
@@ -220,7 +220,7 @@ class Mcdev {
220
220
  for (const selectedType of Array.isArray(selectedTypesArr)
221
221
  ? selectedTypesArr
222
222
  : Object.keys(selectedTypesArr)) {
223
- const [type, subType] = selectedType ? selectedType.split('-') : [];
223
+ const [type, subType] = Util.getTypeAndSubType(selectedType);
224
224
  const removePathArr = [properties.directories.retrieve, cred, bu, type];
225
225
  if (
226
226
  type &&
@@ -293,6 +293,15 @@ class Mcdev {
293
293
  const properties = await config.getProperties(!!credentialsName, true);
294
294
  await Init.initProject(properties, credentialsName);
295
295
  }
296
+ /**
297
+ * Clones an existing project from git repository and installs it
298
+ *
299
+ * @returns {Promise.<void>} -
300
+ */
301
+ static async joinProject() {
302
+ Util.logger.info('mcdev:: Joining an existing project');
303
+ await Init.joinProject();
304
+ }
296
305
 
297
306
  /**
298
307
  * Refreshes BU names and ID's from MC instance
@@ -338,7 +347,8 @@ class Mcdev {
338
347
  );
339
348
  if (buObject !== null) {
340
349
  MetadataTypeInfo[type].properties = properties;
341
- MetadataTypeInfo[type].document(buObject);
350
+ MetadataTypeInfo[type].buObject = buObject;
351
+ MetadataTypeInfo[type].document();
342
352
  }
343
353
  } catch (ex) {
344
354
  Util.logger.error('mcdev.document ' + ex.message);
@@ -350,25 +360,59 @@ class Mcdev {
350
360
  }
351
361
 
352
362
  /**
353
- * Creates docs for supported metadata types in Markdown and/or HTML format
363
+ * deletes metadata from MC instance by key
354
364
  *
355
365
  * @param {string} businessUnit references credentials from properties.json
356
366
  * @param {string} type supported metadata type
357
- * @param {string} customerKey Identifier of data extension
367
+ * @param {string} customerKey Identifier of metadata
358
368
  * @returns {Promise.<void>} -
359
369
  */
360
370
  static async deleteByKey(businessUnit, type, customerKey) {
361
371
  Util.logger.info('mcdev:: delete');
372
+ if (!Util._isValidType(type)) {
373
+ return;
374
+ }
362
375
  const properties = await config.getProperties();
363
376
  if (!(await config.checkProperties(properties))) {
364
377
  return null;
365
378
  }
366
379
  const buObject = await Cli.getCredentialObject(properties, businessUnit);
367
380
  if (buObject !== null) {
368
- if ('string' !== typeof type) {
369
- Util.logger.error('mcdev.delete failed: Bad metadata type passed in');
381
+ try {
382
+ MetadataTypeInfo[type].client = auth.getSDK(buObject);
383
+ } catch (ex) {
384
+ Util.logger.error(ex.message);
370
385
  return;
371
386
  }
387
+ try {
388
+ MetadataTypeInfo[type].properties = properties;
389
+ MetadataTypeInfo[type].buObject = buObject;
390
+ await MetadataTypeInfo[type].deleteByKey(customerKey);
391
+ } catch (ex) {
392
+ Util.logger.errorStack(ex, ` - Deleting ${type} failed`);
393
+ }
394
+ }
395
+ }
396
+ /**
397
+ * ensures triggered sends are restarted to ensure they pick up on changes of the underlying emails
398
+ *
399
+ * @param {string} businessUnit references credentials from properties.json
400
+ * @param {string} type references credentials from properties.json
401
+ * @param {string[]} [keyArr] metadata keys
402
+ * @returns {Promise.<void>} -
403
+ */
404
+ static async refresh(businessUnit, type, keyArr) {
405
+ Util.logger.info('mcdev:: refresh');
406
+ if (!type || !Util._isValidType(type, true)) {
407
+ type = 'triggeredSendDefinition';
408
+ Util.logger.info(' - setting type to ' + type);
409
+ }
410
+ const properties = await config.getProperties();
411
+ if (!(await config.checkProperties(properties))) {
412
+ return null;
413
+ }
414
+ const buObject = await Cli.getCredentialObject(properties, businessUnit);
415
+ if (buObject !== null) {
372
416
  try {
373
417
  MetadataTypeInfo[type].client = auth.getSDK(buObject);
374
418
  } catch (ex) {
@@ -376,10 +420,12 @@ class Mcdev {
376
420
  return;
377
421
  }
378
422
  try {
423
+ cache.initCache(buObject);
379
424
  MetadataTypeInfo[type].properties = properties;
380
- MetadataTypeInfo[type].deleteByKey(buObject, customerKey);
425
+ MetadataTypeInfo[type].buObject = buObject;
426
+ await MetadataTypeInfo[type].refresh(keyArr);
381
427
  } catch (ex) {
382
- Util.logger.error('mcdev.delete ' + ex.message);
428
+ Util.logger.errorStack(ex, 'mcdev.refresh ' + ex.message);
383
429
  }
384
430
  }
385
431
  }
@@ -472,7 +518,7 @@ class Mcdev {
472
518
  if (!Util._isValidType(selectedType)) {
473
519
  return;
474
520
  }
475
- const [type, subType] = selectedType ? selectedType.split('-') : [];
521
+ const [type, subType] = Util.getTypeAndSubType(selectedType);
476
522
 
477
523
  let retrieveTypesArr;
478
524
  if (
@@ -16,37 +16,34 @@ class AccountUser extends MetadataType {
16
16
  *
17
17
  * @param {string} retrieveDir Directory where retrieved metadata directory will be saved
18
18
  * @param {void} _ unused parameter
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 of metadata
23
22
  */
24
- static async retrieve(retrieveDir, _, buObject, ___, key) {
25
- if (buObject.eid !== buObject.mid) {
23
+ static async retrieve(retrieveDir, _, __, key) {
24
+ if (this.buObject.eid !== this.buObject.mid) {
26
25
  Util.logger.info(' - Skipping User retrieval on non-parent BU');
27
26
  return;
28
27
  }
29
- return this._retrieve(retrieveDir, buObject, key);
28
+ return this._retrieve(retrieveDir, key);
30
29
  }
31
30
  /**
32
31
  * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata
33
32
  *
34
- * @param {TYPE.BuObject} buObject properties for auth
35
33
  * @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
36
34
  */
37
- static async retrieveChangelog(buObject) {
38
- return this._retrieve(null, buObject, null);
35
+ static async retrieveChangelog() {
36
+ return this._retrieve();
39
37
  }
40
38
  /**
41
39
  * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata
42
40
  *
43
41
  * @private
44
42
  * @param {string} retrieveDir Directory where retrieved metadata directory will be saved
45
- * @param {TYPE.BuObject} buObject properties for auth
46
43
  * @param {string} [key] customer key of single item to retrieve
47
44
  * @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
48
45
  */
49
- static async _retrieve(retrieveDir, buObject, key) {
46
+ static async _retrieve(retrieveDir, key) {
50
47
  Util.logger.info(' - Caching dependent Metadata: AccountUserAccount');
51
48
 
52
49
  // get BUs that each users have access to
@@ -113,7 +110,7 @@ class AccountUser extends MetadataType {
113
110
  };
114
111
  }
115
112
  Util.logger.info(` - Loading ${this.definition.type}. This might take a while...`);
116
- return super.retrieveSOAP(retrieveDir, buObject, requestParams);
113
+ return super.retrieveSOAP(retrieveDir, requestParams);
117
114
  }
118
115
  /**
119
116
  *
@@ -175,24 +172,21 @@ class AccountUser extends MetadataType {
175
172
  /**
176
173
  * helper to print bu names
177
174
  *
178
- * @param {TYPE.BuObject} buObject needed for eid
179
- * @param {string} buObject.eid needed to check for parent bu
180
175
  * @param {number} id bu id
181
176
  * @returns {string} "bu name (bu id)""
182
177
  */
183
- static getBuName(buObject, id) {
184
- const name = buObject.eid == id ? '_ParentBU_' : this.buIdName[id];
178
+ static getBuName(id) {
179
+ const name = this.buObject.eid == id ? '_ParentBU_' : this.buIdName[id];
185
180
  return `<nobr>${name} (${id})</nobr>`;
186
181
  }
187
182
  /**
188
183
  * Creates markdown documentation of all roles
189
184
  *
190
- * @param {TYPE.BuObject} buObject properties for auth
191
185
  * @param {TYPE.MetadataTypeMap} [metadata] user list
192
186
  * @returns {Promise.<void>} -
193
187
  */
194
- static async document(buObject, metadata) {
195
- if (buObject.eid !== buObject.mid) {
188
+ static async document(metadata) {
189
+ if (this.buObject.eid !== this.buObject.mid) {
196
190
  Util.logger.error(
197
191
  `Users can only be retrieved & documented for the ${Util.parentBuName}`
198
192
  );
@@ -204,7 +198,7 @@ class AccountUser extends MetadataType {
204
198
  metadata = this.readBUMetadataForType(
205
199
  File.normalizePath([
206
200
  this.properties.directories.retrieve,
207
- buObject.credential,
201
+ this.buObject.credential,
208
202
  Util.parentBuName,
209
203
  ]),
210
204
  true
@@ -252,12 +246,12 @@ class AccountUser extends MetadataType {
252
246
  if (user.AssociatedBusinessUnits__c) {
253
247
  associatedBus = user.AssociatedBusinessUnits__c.map((item) => {
254
248
  this.buIdName[item.ID] = item.Name;
255
- return this.getBuName(buObject, item.ID);
249
+ return this.getBuName(item.ID);
256
250
  })
257
251
  .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
258
252
  .join(',<br> ');
259
253
  }
260
- const defaultBUName = this.getBuName(buObject, user.DefaultBusinessUnit);
254
+ const defaultBUName = this.getBuName(user.DefaultBusinessUnit);
261
255
  users.push({
262
256
  TYPE: user.type__c,
263
257
  UserID: user.UserID,
@@ -297,7 +291,7 @@ class AccountUser extends MetadataType {
297
291
  ['Modified Date', 'ModifiedDate'],
298
292
  ['Created Date', 'CreatedDate'],
299
293
  ];
300
- let output = `# User Overview - ${buObject.credential}`;
294
+ let output = `# User Overview - ${this.buObject.credential}`;
301
295
  output += this._generateDocMd(
302
296
  users.filter((user) => user.TYPE === 'User' && user.ActiveFlag === '✓'),
303
297
  'User',
@@ -316,7 +310,7 @@ class AccountUser extends MetadataType {
316
310
  const docPath = File.normalizePath([this.properties.directories.docs, 'user']);
317
311
 
318
312
  try {
319
- const filename = buObject.credential;
313
+ const filename = this.buObject.credential;
320
314
  // write to disk
321
315
  await File.writeToFile(docPath, filename + '.accountUsers', 'md', output);
322
316
  Util.logger.info(`Created ${File.normalizePath([docPath, filename])}.accountUsers.md`);
@@ -19,17 +19,16 @@ class Asset extends MetadataType {
19
19
  *
20
20
  * @param {string} retrieveDir Directory where retrieved metadata directory will be saved
21
21
  * @param {void} _ -
22
- * @param {void} __ -
23
- * @param {TYPE.AssetSubType} [selectedSubType] optionally limit to a single subtype
22
+ * @param {TYPE.AssetSubType[]} [subTypeArr] optionally limit to a single subtype
24
23
  * @param {string} [key] customer key
25
24
  * @returns {Promise.<{metadata: TYPE.AssetMap, type: string}>} Promise
26
25
  */
27
- static async retrieve(retrieveDir, _, __, selectedSubType, key) {
26
+ static async retrieve(retrieveDir, _, subTypeArr, key) {
28
27
  const items = [];
29
- const subTypes = selectedSubType ? [selectedSubType] : this._getSubTypes();
28
+ subTypeArr = subTypeArr || this._getSubTypes();
30
29
  await File.initPrettier();
31
30
  // loop through subtypes and return results of each subType for caching (saving is handled per subtype)
32
- for (const subType of subTypes) {
31
+ for (const subType of subTypeArr) {
33
32
  // each subtype contains multiple different specific types (images contains jpg and png for example)
34
33
  // we use await here to limit the risk of too many concurrent api requests at time
35
34
  items.push(
@@ -46,7 +45,8 @@ class Asset extends MetadataType {
46
45
  const metadata = this.parseResponseBody({ items: items });
47
46
  if (retrieveDir) {
48
47
  Util.logger.info(
49
- `Downloaded: ${this.definition.type} (${Object.keys(metadata).length})`
48
+ `Downloaded: ${this.definition.type} (${Object.keys(metadata).length})` +
49
+ Util.getKeysString(key)
50
50
  );
51
51
  }
52
52
  return { metadata: metadata, type: this.definition.type };
@@ -55,12 +55,12 @@ class Asset extends MetadataType {
55
55
  /**
56
56
  * Retrieves asset metadata for caching
57
57
  *
58
- * @param {void} _ -
59
- * @param {string} [selectedSubType] optionally limit to a single subtype
58
+ * @param {void} _ unused
59
+ * @param {string[]} [subTypeArr] optionally limit to a single subtype
60
60
  * @returns {Promise.<{metadata: TYPE.AssetMap, type: string}>} Promise
61
61
  */
62
- static retrieveForCache(_, selectedSubType) {
63
- return this.retrieve(null, null, null, selectedSubType);
62
+ static retrieveForCache(_, subTypeArr) {
63
+ return this.retrieve(null, null, subTypeArr);
64
64
  }
65
65
 
66
66
  /**
@@ -507,10 +507,9 @@ class Asset extends MetadataType {
507
507
  *
508
508
  * @param {TYPE.AssetItem} metadata a single asset
509
509
  * @param {string} deployDir directory of deploy files
510
- * @param {TYPE.BuObject} buObject buObject properties for auth
511
510
  * @returns {Promise.<TYPE.AssetItem>} Promise
512
511
  */
513
- static async preDeployTasks(metadata, deployDir, buObject) {
512
+ static async preDeployTasks(metadata, deployDir) {
514
513
  // additonalattributes fail where the value is "" so we need to remove them from deploy
515
514
  if (metadata?.data?.email?.attributes?.length > 0) {
516
515
  metadata.data.email.attributes = metadata.data.email.attributes.filter(
@@ -519,10 +518,7 @@ class Asset extends MetadataType {
519
518
  }
520
519
 
521
520
  // folder
522
- metadata.category = {
523
- id: cache.searchForField('folder', metadata.r__folder_Path, 'Path', 'ID'),
524
- };
525
- delete metadata.r__folder_Path;
521
+ this.setFolderId(metadata);
526
522
 
527
523
  // restore asset type id which is needed for deploy
528
524
  metadata.assetType.id = this.definition.typeMapping[metadata.assetType.name];
@@ -538,13 +534,13 @@ class Asset extends MetadataType {
538
534
 
539
535
  // only execute #3 if we are deploying / copying from one BU to another, not while using mcdev as a developer tool
540
536
  if (
541
- buObject.mid &&
542
- metadata.memberId !== buObject.mid &&
543
- !metadata[this.definition.keyField].endsWith(buObject.mid)
537
+ this.buObject.mid &&
538
+ metadata.memberId !== this.buObject.mid &&
539
+ !metadata[this.definition.keyField].endsWith(this.buObject.mid)
544
540
  ) {
545
541
  // #3 make sure customer key is unique by suffixing it with target MID (unless we are deploying to the same MID)
546
542
  // check if this suffixed with the source MID
547
- const suffix = '-' + buObject.mid;
543
+ const suffix = '-' + this.buObject.mid;
548
544
  // for customer key max is 36 chars
549
545
  metadata[this.definition.keyField] =
550
546
  metadata[this.definition.keyField].slice(0, Math.max(0, 36 - suffix.length)) +
@@ -610,7 +606,7 @@ class Asset extends MetadataType {
610
606
  *
611
607
  * @private
612
608
  * @param {TYPE.AssetItem} metadata a single asset
613
- * @returns {TYPE.AssetSubType} subtype
609
+ * @returns {TYPE.AssetSubType | void} subtype
614
610
  */
615
611
  static _getSubtype(metadata) {
616
612
  for (const sub in this.definition.extendedSubTypes) {
@@ -790,6 +786,17 @@ class Asset extends MetadataType {
790
786
  );
791
787
  }
792
788
  }
789
+ /**
790
+ * Asset-specific script that retrieves the folder ID from cache and updates the given metadata with it before deploy
791
+ *
792
+ * @param {TYPE.MetadataTypeItem} metadata a single item
793
+ */
794
+ static setFolderId(metadata) {
795
+ metadata.category = {
796
+ id: cache.searchForField('folder', metadata.r__folder_Path, 'Path', 'ID'),
797
+ };
798
+ delete metadata.r__folder_Path;
799
+ }
793
800
 
794
801
  /**
795
802
  * helper for {@link preDeployTasks} that loads extracted code content back into JSON
@@ -15,11 +15,10 @@ class AttributeGroup 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
  return super.retrieveREST(
24
23
  retrieveDir,
25
24
  '/hub/v1/contacts/schema/attributeGroups',