mcdev 7.5.0 → 7.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/.github/ISSUE_TEMPLATE/bug.yml +2 -0
  2. package/@types/lib/index.d.ts +12 -8
  3. package/@types/lib/index.d.ts.map +1 -1
  4. package/@types/lib/metadataTypes/AttributeSet.d.ts.map +1 -1
  5. package/@types/lib/metadataTypes/Automation.d.ts +14 -0
  6. package/@types/lib/metadataTypes/Automation.d.ts.map +1 -1
  7. package/@types/lib/metadataTypes/DataExtension.d.ts +3 -1
  8. package/@types/lib/metadataTypes/DataExtension.d.ts.map +1 -1
  9. package/@types/lib/metadataTypes/Event.d.ts +2 -2
  10. package/@types/lib/metadataTypes/Event.d.ts.map +1 -1
  11. package/@types/lib/metadataTypes/Journey.d.ts +17 -0
  12. package/@types/lib/metadataTypes/Journey.d.ts.map +1 -1
  13. package/@types/lib/metadataTypes/MetadataType.d.ts +8 -4
  14. package/@types/lib/metadataTypes/MetadataType.d.ts.map +1 -1
  15. package/@types/lib/metadataTypes/Query.d.ts +7 -0
  16. package/@types/lib/metadataTypes/Query.d.ts.map +1 -1
  17. package/@types/lib/metadataTypes/TransactionalEmail.d.ts +1 -0
  18. package/@types/lib/metadataTypes/TransactionalEmail.d.ts.map +1 -1
  19. package/@types/lib/metadataTypes/TriggeredSend.d.ts +0 -8
  20. package/@types/lib/metadataTypes/TriggeredSend.d.ts.map +1 -1
  21. package/@types/lib/metadataTypes/definitions/Journey.definition.d.ts +1 -0
  22. package/@types/lib/metadataTypes/definitions/TransactionalEmail.definition.d.ts +1 -0
  23. package/@types/lib/util/replaceContentBlockReference.d.ts.map +1 -1
  24. package/@types/lib/util/util.d.ts.map +1 -1
  25. package/@types/types/mcdev.d.d.ts +20 -8
  26. package/@types/types/mcdev.d.d.ts.map +1 -1
  27. package/lib/cli.js +13 -2
  28. package/lib/index.js +46 -45
  29. package/lib/metadataTypes/Automation.js +28 -0
  30. package/lib/metadataTypes/Event.js +4 -1
  31. package/lib/metadataTypes/Journey.js +472 -94
  32. package/lib/metadataTypes/MetadataType.js +12 -6
  33. package/lib/metadataTypes/TriggeredSend.js +46 -15
  34. package/lib/metadataTypes/definitions/Automation.definition.js +1 -0
  35. package/lib/metadataTypes/definitions/Journey.definition.js +1 -0
  36. package/lib/metadataTypes/definitions/TransactionalEmail.definition.js +1 -0
  37. package/package.json +15 -15
  38. package/test/general.test.js +5 -5
  39. package/test/mockRoot/.mcdevrc.json +1 -1
  40. package/test/resources/9999999/dataFolder/retrieve-ContentTypeINcontextual_suppression_list,hidden,list,mysubs,publication,suppression_list,triggered_send,triggered_send_journeybuilder-response.xml +385 -0
  41. package/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/get-response.json +461 -0
  42. package/test/resources/9999999/interaction/v1/interactions/dsfdsafdsa-922c-4568-85a5-e5cc77efc3be/delete-response.txt +1 -0
  43. package/test/resources/9999999/interaction/v1/interactions/transactional/pause/post-response.json +3 -0
  44. package/test/resources/9999999/interaction/v1/interactions/transactional/resume/post-response.json +3 -0
  45. package/test/resources/9999999/triggeredSendDefinition/retrieve-CustomerKey=testExisting_triggeredSend-response.xml +72 -0
  46. package/test/resources/9999999/triggeredSendDefinition/retrieve-CustomerKey=testExisting_triggeredSend_rcb-response.xml +72 -0
  47. package/test/resources/9999999/triggeredSendDefinition/retrieve-TriggeredSendStatusINNew,Active,Inactive,Moved,Canceled-response.xml +1 -1
  48. package/test/resources/9999999/triggeredSendDefinition/retrieve-TriggeredSendStatusINdummy,Active-response.xml +118 -0
  49. package/test/type.automation.test.js +13 -13
  50. package/test/type.journey.test.js +79 -5
  51. package/test/type.query.test.js +2 -2
  52. package/test/type.triggeredSend.test.js +68 -1
  53. package/types/mcdev.d.js +2 -1
@@ -508,13 +508,15 @@ class MetadataType {
508
508
  /**
509
509
  * Abstract refresh method that needs to be implemented in child metadata type
510
510
  *
511
- * @returns {void}
511
+ * @param {string[]} [keyArr] metadata keys
512
+ * @param {boolean} [checkKey] whether to check if the key is valid
513
+ * @returns {Promise.<string[]>} Returns list of keys that were refreshed
512
514
  */
513
- static refresh() {
515
+ static async refresh(keyArr, checkKey = true) {
514
516
  Util.logger.error(
515
517
  ` ☇ skipping ${this.definition.type}: refresh is not supported yet for ${this.definition.type}`
516
518
  );
517
- return;
519
+ return [];
518
520
  }
519
521
 
520
522
  /**
@@ -631,9 +633,10 @@ class MetadataType {
631
633
  * Abstract execute method that needs to be implemented in child metadata type
632
634
  *
633
635
  * @param {string[]} keyArr customerkey of the metadata
636
+ * @param {MetadataTypeMapObj} [cache] metadata cache used by refresh to avoid recaching
634
637
  * @returns {Promise.<string[]>} Returns list of keys that were executed
635
638
  */
636
- static async execute(keyArr) {
639
+ static async execute(keyArr, cache) {
637
640
  Util.logger.error(
638
641
  ` ☇ skipping ${this.definition.type}: execute is not supported yet for ${this.definition.type}`
639
642
  );
@@ -644,9 +647,10 @@ class MetadataType {
644
647
  * Abstract pause method that needs to be implemented in child metadata type
645
648
  *
646
649
  * @param {string[]} keyArr customerkey of the metadata
650
+ * @param {MetadataTypeMapObj} [cache] metadata cache used by refresh to avoid recaching
647
651
  * @returns {Promise.<string[]>} Returns list of keys that were paused
648
652
  */
649
- static async pause(keyArr) {
653
+ static async pause(keyArr, cache) {
650
654
  Util.logger.error(
651
655
  ` ☇ skipping ${this.definition.type}: pause is not supported yet for ${this.definition.type}`
652
656
  );
@@ -2466,7 +2470,9 @@ class MetadataType {
2466
2470
  } else {
2467
2471
  const errorMsg = ex?.results?.length
2468
2472
  ? `${ex.results[0].StatusMessage} (Code ${ex.results[0].ErrorCode})`
2469
- : ex.message;
2473
+ : ex?.json?.Results?.length
2474
+ ? `${ex.json.Results[0].StatusMessage} (Code ${ex.json.Results[0].ErrorCode})`
2475
+ : ex.message;
2470
2476
  Util.logger.error(
2471
2477
  ` - Deleting ${this.definition.type} '${customerKey}' failed: ${errorMsg}`
2472
2478
  );
@@ -6,7 +6,10 @@ import cache from '../util/cache.js';
6
6
  import asset from './Asset.js';
7
7
  import folder from './Folder.js';
8
8
  import list from './List.js';
9
+ import sendClassification from './SendClassification.js';
10
+ import senderProfile from './SenderProfile.js';
9
11
  import ReplaceCbReference from '../util/replaceContentBlockReference.js';
12
+ import pLimit from 'p-limit';
10
13
 
11
14
  /**
12
15
  * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject
@@ -303,24 +306,32 @@ class TriggeredSend extends MetadataType {
303
306
  *
304
307
  * @param {string[]} [keyArr] metadata keys
305
308
  * @param {boolean} [checkKey] whether to check if the key is valid
306
- * @returns {Promise.<void>} -
309
+ * @returns {Promise.<string[]>} Returns list of keys that were refreshed
307
310
  */
308
311
  static async refresh(keyArr, checkKey = true) {
309
- console.time('Time'); // eslint-disable-line no-console
310
312
  if (!keyArr) {
311
313
  keyArr = await this.getKeysForValidTSDs((await this.findRefreshableItems()).metadata);
312
314
  checkKey = false;
313
315
  }
314
316
  // then executes pause, publish, start on them.
315
- const refreshList = [];
316
317
  Util.logger.info(`Refreshing ${keyArr.length} ${this.definition.typeName}...`);
317
318
  Util.logger.debug(`Refreshing keys: ${keyArr.join(', ')}`);
318
- for (const key of keyArr) {
319
- refreshList.push(this._refreshItem(key, checkKey));
320
- }
321
- const successCounter = (await Promise.all(refreshList)).filter(Boolean).length;
322
- Util.logger.info(`Refreshed ${successCounter} of ${keyArr.length}`);
323
- console.timeEnd('Time'); // eslint-disable-line no-console
319
+ const refreshedKeyArr = [];
320
+ const rateLimit = pLimit(10);
321
+ await Promise.all(
322
+ keyArr.map((key) =>
323
+ rateLimit(async () => {
324
+ const result = await this._refreshItem(key, checkKey);
325
+ if (result) {
326
+ refreshedKeyArr.push(key);
327
+ }
328
+ })
329
+ )
330
+ );
331
+ Util.logger.info(
332
+ `Refreshed ${refreshedKeyArr.length} of ${keyArr.length} ${this.definition.type}`
333
+ );
334
+ return refreshedKeyArr;
324
335
  }
325
336
 
326
337
  /**
@@ -347,7 +358,6 @@ class TriggeredSend extends MetadataType {
347
358
  static async findRefreshableItems(assetLoaded = false) {
348
359
  Util.logger.info('Finding refreshable items...');
349
360
  // cache dependencies to test for broken links
350
- // skip deprecated classic emails here, assuming they cannot be updated and hence are not relevant for {@link refresh}
351
361
  const requiredCache = {
352
362
  folder: [
353
363
  'hidden',
@@ -359,13 +369,31 @@ class TriggeredSend extends MetadataType {
359
369
  'triggered_send',
360
370
  'triggered_send_journeybuilder',
361
371
  ],
362
- asset: ['message'],
363
- list: null,
364
372
  };
373
+ for (const dep of this.definition.dependencies) {
374
+ if (dep === 'email') {
375
+ // skip deprecated classic emails here, assuming they cannot be updated and hence are not relevant for {@link refresh}
376
+ continue;
377
+ }
378
+ const [type, subtype] = dep.split('-');
379
+ if (requiredCache[type]) {
380
+ requiredCache[type].push(subtype);
381
+ } else {
382
+ requiredCache[type] = subtype ? [subtype] : null;
383
+ }
384
+ }
385
+ for (const [type, subTypeArr] of Object.entries(requiredCache)) {
386
+ if (Array.isArray(subTypeArr)) {
387
+ // make sure entries are unique
388
+ requiredCache[type] = [...new Set(subTypeArr)];
389
+ }
390
+ }
365
391
  const cacheTypes = {
366
392
  asset,
367
393
  folder,
368
394
  list,
395
+ sendClassification,
396
+ senderProfile,
369
397
  };
370
398
  for (const [type, subTypeArr] of Object.entries(requiredCache)) {
371
399
  if (type === 'asset' && assetLoaded) {
@@ -373,6 +401,9 @@ class TriggeredSend extends MetadataType {
373
401
  }
374
402
  Util.logger.info(` - Caching dependent Metadata: ${type}`);
375
403
  Util.logSubtypes(subTypeArr);
404
+ if (!cacheTypes[type]) {
405
+ throw new Error(`Cache type ${type} not implemented.`);
406
+ }
376
407
  cacheTypes[type].client = this.client;
377
408
  cacheTypes[type].buObject = this.buObject;
378
409
  cacheTypes[type].properties = this.properties;
@@ -452,7 +483,7 @@ class TriggeredSend extends MetadataType {
452
483
  throw new Error(test.Results[0].StatusMessage);
453
484
  }
454
485
  delete item.TriggeredSendStatus;
455
- Util.logger.info(` - paused ${this.definition.typeName}: ${key}`);
486
+ Util.logger.info(` - 🛑 paused ${this.definition.typeName}: ${key}`);
456
487
  } catch (ex) {
457
488
  const errorMsg = super.getSOAPErrorMsg(ex);
458
489
 
@@ -470,7 +501,7 @@ class TriggeredSend extends MetadataType {
470
501
  throw new Error(test.Results[0].StatusMessage);
471
502
  }
472
503
  delete item.RefreshContent;
473
- Util.logger.info(` - published ${this.definition.typeName}: ${key}`);
504
+ Util.logger.info(` - 🔃 published ${this.definition.typeName}: ${key}`);
474
505
  } catch (ex) {
475
506
  const errorMsg = super.getSOAPErrorMsg(ex);
476
507
  Util.logger.error(
@@ -487,7 +518,7 @@ class TriggeredSend extends MetadataType {
487
518
  throw new Error(test.Results[0].StatusMessage);
488
519
  }
489
520
  delete item.RefreshContent;
490
- Util.logger.info(` - started ${this.definition.typeName}: ${key}`);
521
+ Util.logger.info(` - started ${this.definition.typeName}: ${key}`);
491
522
  } catch (ex) {
492
523
  const errorMsg = super.getSOAPErrorMsg(ex);
493
524
  Util.logger.error(
@@ -27,6 +27,7 @@ export default {
27
27
  'dataExtract',
28
28
  'emailSend',
29
29
  'fileTransfer',
30
+ 'fileLocation',
30
31
  'folder-automations',
31
32
  'importFile',
32
33
  'query',
@@ -60,6 +60,7 @@ export default {
60
60
  lastmodNameField: null,
61
61
  restPagination: true,
62
62
  restPageSize: 500,
63
+ maxKeyLength: 200, // confirmed max length
63
64
  type: 'journey',
64
65
  typeDescription: 'Journey (internally called "Interaction").',
65
66
  typeRetrieveByDefault: true,
@@ -20,6 +20,7 @@ export default {
20
20
  lastmodNameField: null,
21
21
  restPagination: true,
22
22
  restPageSize: 100,
23
+ maxKeyLength: 36, // confirmed max length
23
24
  type: 'transactionalEmail',
24
25
  typeDescription: 'Lets you send immediate Email messages via API events',
25
26
  typeRetrieveByDefault: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcdev",
3
- "version": "7.5.0",
3
+ "version": "7.6.1",
4
4
  "description": "Accenture Salesforce Marketing Cloud DevTools",
5
5
  "author": "Accenture: joern.berkefeld, douglas.midgley, robert.zimmermann, maciej.barnas",
6
6
  "license": "MIT",
@@ -71,7 +71,7 @@
71
71
  "beauty-amp-core2": "0.4.9",
72
72
  "cli-progress": "3.12.0",
73
73
  "command-exists": "1.2.9",
74
- "conf": "13.0.1",
74
+ "conf": "13.1.0",
75
75
  "console.table": "0.10.0",
76
76
  "deep-equal": "2.2.3",
77
77
  "fs-extra": "11.2.0",
@@ -79,45 +79,45 @@
79
79
  "json-to-table": "4.2.1",
80
80
  "mustache": "4.2.0",
81
81
  "p-limit": "6.1.0",
82
- "prettier": "3.3.3",
82
+ "prettier": "3.4.2",
83
83
  "prettier-plugin-sql": "0.18.1",
84
84
  "semver": "7.6.3",
85
85
  "sfmc-sdk": "2.1.2",
86
86
  "simple-git": "3.27.0",
87
87
  "toposort": "2.0.2",
88
88
  "update-notifier": "7.3.1",
89
- "winston": "3.15.0",
89
+ "winston": "3.17.0",
90
90
  "yargs": "17.7.2",
91
91
  "yocto-spinner": "0.1.1"
92
92
  },
93
93
  "devDependencies": {
94
- "@eslint/js": "9.10.0",
94
+ "@eslint/js": "9.17.0",
95
95
  "@types/fs-extra": "11.0.4",
96
96
  "@types/inquirer": "9.0.7",
97
97
  "@types/mocha": "10.0.8",
98
- "@types/node": "22.9.0",
98
+ "@types/node": "22.10.2",
99
99
  "@types/yargs": "17.0.33",
100
100
  "assert": "2.1.0",
101
- "axios-mock-adapter": "2.1.0",
101
+ "axios-mock-adapter": "2.0.0",
102
102
  "c8": "10.0.0",
103
- "chai": "5.1.1",
103
+ "chai": "5.1.2",
104
104
  "chai-files": "1.4.0",
105
- "eslint": "9.10.0",
105
+ "eslint": "9.17.0",
106
106
  "eslint-config-prettier": "9.1.0",
107
107
  "eslint-config-ssjs": "2.0.0",
108
- "eslint-plugin-jsdoc": "50.5.0",
108
+ "eslint-plugin-jsdoc": "50.6.1",
109
109
  "eslint-plugin-mocha": "10.5.0",
110
110
  "eslint-plugin-prettier": "5.2.1",
111
- "eslint-plugin-unicorn": "56.0.0",
111
+ "eslint-plugin-unicorn": "56.0.1",
112
112
  "fast-xml-parser": "4.4.1",
113
- "globals": "15.12.0",
114
- "husky": "9.1.6",
113
+ "globals": "15.14.0",
114
+ "husky": "9.1.7",
115
115
  "lint-staged": "15.2.10",
116
- "mocha": "10.7.3",
116
+ "mocha": "11.0.1",
117
117
  "mock-fs": "5.3.0",
118
118
  "npm-run-all": "4.1.5",
119
119
  "prettier-eslint": "16.3.0",
120
- "typescript": "5.6.3"
120
+ "typescript": "5.7.2"
121
121
  },
122
122
  "optionalDependencies": {
123
123
  "fsevents": "*"
@@ -708,7 +708,7 @@ describe('GENERAL', () => {
708
708
  // download first before we test buildTemplate
709
709
  await handler.retrieve('testInstance/testBU', ['automation', 'query']);
710
710
 
711
- const expectedApiCallsRetrieve = 30;
711
+ const expectedApiCallsRetrieve = 31;
712
712
  assert.equal(
713
713
  testUtils.getAPIHistoryLength(),
714
714
  expectedApiCallsRetrieve,
@@ -813,7 +813,7 @@ describe('GENERAL', () => {
813
813
  });
814
814
 
815
815
  it('buildTemplate + buildDefinition for multiple types with keys and --retrieve', async () => {
816
- const expectedApiCallsRetrieve = 30;
816
+ const expectedApiCallsRetrieve = 31;
817
817
 
818
818
  // preparation
819
819
  const argvMetadata = [
@@ -1170,7 +1170,7 @@ describe('GENERAL', () => {
1170
1170
  // download first before we test buildTemplate
1171
1171
  await handler.retrieve('testInstance/testBU', ['automation', 'query']);
1172
1172
 
1173
- const expectedApiCallsRetrieve = 30;
1173
+ const expectedApiCallsRetrieve = 31;
1174
1174
  assert.equal(
1175
1175
  testUtils.getAPIHistoryLength(),
1176
1176
  expectedApiCallsRetrieve,
@@ -1362,7 +1362,7 @@ describe('GENERAL', () => {
1362
1362
  // download first before we test buildTemplate
1363
1363
  await handler.retrieve('testInstance/testBU', ['automation', 'query']);
1364
1364
 
1365
- const expectedApiCallsRetrieve = 30;
1365
+ const expectedApiCallsRetrieve = 31;
1366
1366
  assert.equal(
1367
1367
  testUtils.getAPIHistoryLength(),
1368
1368
  expectedApiCallsRetrieve,
@@ -1669,7 +1669,7 @@ describe('GENERAL', () => {
1669
1669
  // download first before we test buildTemplate
1670
1670
  await handler.retrieve('testInstance/testBU', ['automation', 'query']);
1671
1671
 
1672
- const expectedApiCallsRetrieve = 30;
1672
+ const expectedApiCallsRetrieve = 31;
1673
1673
  assert.equal(
1674
1674
  testUtils.getAPIHistoryLength(),
1675
1675
  expectedApiCallsRetrieve,
@@ -126,5 +126,5 @@
126
126
  "verification"
127
127
  ]
128
128
  },
129
- "version": "7.5.0"
129
+ "version": "7.6.1"
130
130
  }