mcdev 5.0.2 → 5.1.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 (88) hide show
  1. package/.coverage-comment-template.svelte +177 -161
  2. package/.github/ISSUE_TEMPLATE/bug.yml +1 -0
  3. package/.github/dependabot.yml +8 -0
  4. package/.github/workflows/coverage-base-update.yml +6 -2
  5. package/.github/workflows/coverage-develop-branch.yml +7 -6
  6. package/.github/workflows/coverage-main-branch.yml +7 -6
  7. package/.github/workflows/coverage.yml +7 -2
  8. package/.husky/post-checkout +3 -2
  9. package/docs/dist/documentation.md +162 -47
  10. package/lib/Deployer.js +3 -3
  11. package/lib/cli.js +28 -0
  12. package/lib/index.js +173 -2
  13. package/lib/metadataTypes/Automation.js +400 -193
  14. package/lib/metadataTypes/DataExtension.js +5 -5
  15. package/lib/metadataTypes/MetadataType.js +42 -15
  16. package/lib/metadataTypes/Query.js +26 -0
  17. package/lib/metadataTypes/definitions/Asset.definition.js +1 -0
  18. package/lib/metadataTypes/definitions/Automation.definition.js +52 -6
  19. package/lib/metadataTypes/definitions/DataExtension.definition.js +1 -0
  20. package/lib/metadataTypes/definitions/DataExtract.definition.js +1 -0
  21. package/lib/metadataTypes/definitions/EmailSend.definition.js +1 -0
  22. package/lib/metadataTypes/definitions/Event.definition.js +1 -0
  23. package/lib/metadataTypes/definitions/Filter.definition.js +1 -0
  24. package/lib/metadataTypes/definitions/ImportFile.definition.js +1 -0
  25. package/lib/metadataTypes/definitions/MobileKeyword.definition.js +1 -0
  26. package/lib/metadataTypes/definitions/Query.definition.js +1 -0
  27. package/lib/metadataTypes/definitions/Role.definition.js +1 -0
  28. package/lib/metadataTypes/definitions/TriggeredSend.definition.js +1 -0
  29. package/lib/metadataTypes/definitions/User.definition.js +1 -0
  30. package/lib/util/devops.js +13 -11
  31. package/lib/util/util.js +152 -129
  32. package/package.json +5 -5
  33. package/test/general.test.js +26 -0
  34. package/test/mockRoot/.mcdevrc.json +1 -1
  35. package/test/mockRoot/deploy/testInstance/testBU/automation/testExisting_automation.automation-meta.json +53 -0
  36. package/test/mockRoot/deploy/testInstance/testBU/automation/testNew_automation.automation-meta.json +46 -0
  37. package/test/mockRoot/deploy/testInstance/testBU/query/{testExistingQuery.query-meta.json → testExisting_query.query-meta.json} +2 -2
  38. package/test/mockRoot/deploy/testInstance/testBU/query/{testNewQuery.query-meta.json → testNew_query.query-meta.json} +2 -2
  39. package/test/resourceFactory.js +64 -21
  40. package/test/resources/9999999/automation/build-expected.json +58 -0
  41. package/test/resources/9999999/automation/create-expected.json +46 -0
  42. package/test/resources/9999999/automation/create-testNew_automation-expected.md +28 -0
  43. package/test/resources/9999999/automation/delete-response.xml +40 -0
  44. package/test/resources/9999999/automation/retrieve-expected.json +58 -0
  45. package/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md +30 -0
  46. package/test/resources/9999999/automation/template-expected.json +58 -0
  47. package/test/resources/9999999/automation/update-expected.json +46 -0
  48. package/test/resources/9999999/automation/update-testExisting_automation-expected.md +28 -0
  49. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json +85 -0
  50. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/patch-response.json +85 -0
  51. package/test/resources/9999999/automation/v1/automations/a8afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json +85 -0
  52. package/test/resources/9999999/automation/v1/automations/post-response.json +85 -0
  53. package/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/get-response.json +38 -0
  54. package/test/resources/9999999/automation/v1/dataextracts/get-response.json +20 -0
  55. package/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/get-response.json +18 -0
  56. package/test/resources/9999999/automation/v1/filetransfers/get-response.json +15 -0
  57. package/test/resources/9999999/automation/v1/imports/get-response.json +38 -0
  58. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/actions/start/post-response.txt +1 -0
  59. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/get-response.json +2 -2
  60. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/patch-response.json +2 -2
  61. package/test/resources/9999999/automation/v1/queries/get-response.json +4 -4
  62. package/test/resources/9999999/automation/v1/queries/post-response.json +2 -2
  63. package/test/resources/9999999/automation/v1/scripts/get-response.json +17 -0
  64. package/test/resources/9999999/dataFolder/retrieve-ContentType=automations-response.xml +48 -0
  65. package/test/resources/9999999/dataFolder/retrieve-ContentType=queryactivity-response.xml +48 -0
  66. package/test/resources/9999999/dataFolder/retrieve-response.xml +22 -0
  67. package/test/resources/9999999/emailSendDefinition/retrieve-response.xml +85 -0
  68. package/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/get-response.json +21 -0
  69. package/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/post-response.json +0 -0
  70. package/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/get-response.json +30 -0
  71. package/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation-response.xml +30 -0
  72. package/test/resources/9999999/program/retrieve-CustomerKey=testNew_automation-response.xml +30 -0
  73. package/test/resources/9999999/program/retrieve-Name=testExisting_automation-response.xml +31 -0
  74. package/test/resources/9999999/program/retrieve-response.xml +32 -0
  75. package/test/resources/9999999/query/build-expected.json +2 -2
  76. package/test/resources/9999999/query/get-expected.json +2 -2
  77. package/test/resources/9999999/query/get2-expected.json +2 -2
  78. package/test/resources/9999999/query/patch-expected.json +2 -2
  79. package/test/resources/9999999/query/post-expected.json +2 -2
  80. package/test/resources/9999999/query/template-expected.json +2 -2
  81. package/test/type.automation.test.js +259 -0
  82. package/test/type.dataExtension.test.js +3 -0
  83. package/test/type.query.test.js +39 -26
  84. package/test/type.user.test.js +17 -3
  85. package/test/utils.js +7 -6
  86. package/.coverage-comment-template.md +0 -20
  87. /package/test/mockRoot/deploy/testInstance/testBU/query/{testExistingQuery.query-meta.sql → testExisting_query.query-meta.sql} +0 -0
  88. /package/test/mockRoot/deploy/testInstance/testBU/query/{testNewQuery.query-meta.sql → testNew_query.query-meta.sql} +0 -0
package/lib/index.js CHANGED
@@ -59,6 +59,7 @@ class Mcdev {
59
59
  'json',
60
60
  'refresh',
61
61
  'skipInteraction',
62
+ 'noLogFile',
62
63
  ];
63
64
  for (const option of knownOptions) {
64
65
  if (argv[option] !== undefined) {
@@ -89,6 +90,7 @@ class Mcdev {
89
90
  * @returns {Promise.<TYPE.DeltaPkgItem[]>} list of changed items
90
91
  */
91
92
  static async createDeltaPkg(argv) {
93
+ Util.startLogger();
92
94
  Util.logger.info('Create Delta Package ::');
93
95
  const properties = await config.getProperties();
94
96
  if (!(await config.checkProperties(properties))) {
@@ -111,6 +113,7 @@ class Mcdev {
111
113
  * @returns {Promise} .
112
114
  */
113
115
  static async selectTypes() {
116
+ Util.startLogger();
114
117
  const properties = await config.getProperties();
115
118
  if (!(await config.checkProperties(properties))) {
116
119
  return null;
@@ -127,6 +130,7 @@ class Mcdev {
127
130
  * @returns {Promise.<boolean>} success flag
128
131
  */
129
132
  static async upgrade() {
133
+ Util.startLogger();
130
134
  const properties = await config.getProperties();
131
135
  if (!properties) {
132
136
  Util.logger.error('No config found. Please run mcdev init');
@@ -149,6 +153,7 @@ class Mcdev {
149
153
  * @returns {Promise.<object>} -
150
154
  */
151
155
  static async retrieve(businessUnit, selectedTypesArr, keys, changelogOnly) {
156
+ Util.startLogger();
152
157
  Util.logger.info('mcdev:: Retrieve');
153
158
  const properties = await config.getProperties();
154
159
  if (!(await config.checkProperties(properties))) {
@@ -176,7 +181,7 @@ class Mcdev {
176
181
  for (const bu in properties.credentials[cred].businessUnits) {
177
182
  await this._retrieveBU(cred, bu, selectedTypesArr, keys);
178
183
  counter_credBu++;
179
- Util.restartLogger();
184
+ Util.startLogger(true);
180
185
  }
181
186
  counter_credTotal += counter_credBu;
182
187
  Util.logger.info(`\n :: ${counter_credBu} BUs for ${cred}\n`);
@@ -210,7 +215,7 @@ class Mcdev {
210
215
  for (const bu in properties.credentials[cred].businessUnits) {
211
216
  await this._retrieveBU(cred, bu, selectedTypesArr, keys);
212
217
  counter_credBu++;
213
- Util.restartLogger();
218
+ Util.startLogger(true);
214
219
  }
215
220
  Util.logger.info(`\n :: ${counter_credBu} BUs for ${cred}\n`);
216
221
  } else {
@@ -351,6 +356,7 @@ class Mcdev {
351
356
  * @returns {Promise.<Object.<string,TYPE.MultiMetadataTypeMap>>} deployed metadata per BU (first key: bu name, second key: metadata type)
352
357
  */
353
358
  static async deploy(businessUnit, selectedTypesArr, keyArr, fromRetrieve = false) {
359
+ Util.startLogger();
354
360
  return Deployer.deploy(businessUnit, selectedTypesArr, keyArr, fromRetrieve);
355
361
  }
356
362
 
@@ -361,6 +367,7 @@ class Mcdev {
361
367
  * @returns {Promise.<void>} -
362
368
  */
363
369
  static async initProject(credentialsName) {
370
+ Util.startLogger();
364
371
  Util.logger.info('mcdev:: Setting up project');
365
372
  const properties = await config.getProperties(!!credentialsName, true);
366
373
  await Init.initProject(properties, credentialsName);
@@ -371,6 +378,7 @@ class Mcdev {
371
378
  * @returns {Promise.<void>} -
372
379
  */
373
380
  static async joinProject() {
381
+ Util.startLogger();
374
382
  Util.logger.info('mcdev:: Joining an existing project');
375
383
  await Init.joinProject();
376
384
  }
@@ -382,6 +390,7 @@ class Mcdev {
382
390
  * @returns {Promise.<void>} -
383
391
  */
384
392
  static async findBUs(credentialsName) {
393
+ Util.startLogger();
385
394
  Util.logger.info('mcdev:: Load BUs');
386
395
  const properties = await config.getProperties();
387
396
  if (!(await config.checkProperties(properties))) {
@@ -401,6 +410,7 @@ class Mcdev {
401
410
  * @returns {Promise.<void>} -
402
411
  */
403
412
  static async document(businessUnit, type) {
413
+ Util.startLogger();
404
414
  Util.logger.info('mcdev:: Document');
405
415
  const properties = await config.getProperties();
406
416
  if (!(await config.checkProperties(properties))) {
@@ -440,6 +450,7 @@ class Mcdev {
440
450
  * @returns {Promise.<boolean>} true if successful, false otherwise
441
451
  */
442
452
  static async deleteByKey(businessUnit, type, customerKey) {
453
+ Util.startLogger();
443
454
  Util.logger.info('mcdev:: delete');
444
455
  if (!Util._isValidType(type)) {
445
456
  return;
@@ -477,6 +488,7 @@ class Mcdev {
477
488
  * @returns {Promise.<void>} -
478
489
  */
479
490
  static async refresh(businessUnit, type, keyArr) {
491
+ Util.startLogger();
480
492
  Util.logger.info('mcdev:: refresh');
481
493
  if (!type || !Util._isValidType(type, true)) {
482
494
  type = 'triggeredSend';
@@ -512,6 +524,7 @@ class Mcdev {
512
524
  * @returns {Promise.<void>} -
513
525
  */
514
526
  static async badKeys(businessUnit) {
527
+ Util.startLogger();
515
528
  const properties = await config.getProperties();
516
529
  if (!(await config.checkProperties(properties))) {
517
530
  return null;
@@ -585,6 +598,7 @@ class Mcdev {
585
598
  * @returns {Promise.<TYPE.MultiMetadataTypeList>} -
586
599
  */
587
600
  static async retrieveAsTemplate(businessUnit, selectedType, name, market) {
601
+ Util.startLogger();
588
602
  Util.logger.info('mcdev:: Retrieve as Template');
589
603
  const properties = await config.getProperties();
590
604
  if (!(await config.checkProperties(properties))) {
@@ -626,6 +640,7 @@ class Mcdev {
626
640
  * @returns {Promise.<TYPE.MultiMetadataTypeList>} -
627
641
  */
628
642
  static async buildTemplate(businessUnit, selectedType, keyArr, market) {
643
+ Util.startLogger();
629
644
  Util.logger.info('mcdev:: Build Template from retrieved files');
630
645
  return Builder.buildTemplate(businessUnit, selectedType, keyArr, market);
631
646
  }
@@ -639,6 +654,7 @@ class Mcdev {
639
654
  * @returns {Promise.<void>} -
640
655
  */
641
656
  static async buildDefinition(businessUnit, selectedType, name, market) {
657
+ Util.startLogger();
642
658
  Util.logger.info('mcdev:: Build Definition from Template');
643
659
  return Builder.buildDefinition(businessUnit, selectedType, name, market);
644
660
  }
@@ -652,6 +668,7 @@ class Mcdev {
652
668
  * @returns {Promise.<void>} -
653
669
  */
654
670
  static async buildDefinitionBulk(listName, type, name) {
671
+ Util.startLogger();
655
672
  Util.logger.info('mcdev:: Build Definition from Template Bulk');
656
673
  return Builder.buildDefinitionBulk(listName, type, name);
657
674
  }
@@ -663,6 +680,7 @@ class Mcdev {
663
680
  * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext']
664
681
  */
665
682
  static async getFilesToCommit(businessUnit, selectedType, keyArr) {
683
+ Util.startLogger();
666
684
  Util.logger.info('mcdev:: getFilesToCommit');
667
685
  const properties = await config.getProperties();
668
686
  if (!(await config.checkProperties(properties))) {
@@ -682,6 +700,159 @@ class Mcdev {
682
700
  return DevOps.getFilesToCommit(properties, buObject, selectedType, keyArr);
683
701
  }
684
702
  }
703
+ /**
704
+ * Start an item (query)
705
+ *
706
+ * @param {string} businessUnit name of BU
707
+ * @param {TYPE.SupportedMetadataTypes[]} [selectedTypesArr] limit to given metadata types
708
+ * @param {string[]} keys customerkey of the metadata
709
+ * @returns {Promise.<boolean>} true if all started successfully, false if not
710
+ */
711
+ static async execute(businessUnit, selectedTypesArr, keys) {
712
+ Util.startLogger();
713
+ Util.logger.info('mcdev:: Execute');
714
+ const properties = await config.getProperties();
715
+ let counter_credBu = 0;
716
+ let counter_failed = 0;
717
+ if (!(await config.checkProperties(properties))) {
718
+ // return null here to avoid seeing 2 error messages for the same issue
719
+ return null;
720
+ }
721
+ if (Array.isArray(selectedTypesArr)) {
722
+ // types and keys can be provided but for each type all provided keys are applied as filter
723
+ for (const selectedType of Array.isArray(selectedTypesArr)
724
+ ? selectedTypesArr
725
+ : Object.keys(selectedTypesArr)) {
726
+ if (!Util._isValidType(selectedType)) {
727
+ return;
728
+ }
729
+ }
730
+ }
731
+ if (businessUnit === '*') {
732
+ Util.logger.info(
733
+ '\n :: Executing the entity on all BUs for all credentials'
734
+ );
735
+ let counter_credTotal = 0;
736
+ for (const cred in properties.credentials) {
737
+ Util.logger.info(`\n :: Executing the entity on all BUs for ${cred}`);
738
+
739
+ for (const bu in properties.credentials[cred].businessUnits) {
740
+ if (await this._executeBU(cred, bu, selectedTypesArr, keys)) {
741
+ counter_credBu++;
742
+ } else {
743
+ counter_failed++;
744
+ }
745
+ Util.startLogger(true);
746
+ }
747
+ counter_credTotal += counter_credBu;
748
+ Util.logger.info(
749
+ `\n :: Executed the entity on ${counter_credBu} BUs for ${cred}\n`
750
+ );
751
+ }
752
+ Util.logger.info(
753
+ `\n :: Executed the entity on ${counter_credTotal} BUs in total\n`
754
+ );
755
+ } else {
756
+ let [cred, bu] = businessUnit ? businessUnit.split('/') : [null, null];
757
+ // to allow all-BU via user selection we need to run this here already
758
+ if (
759
+ properties.credentials &&
760
+ (!properties.credentials[cred] ||
761
+ (bu !== '*' && !properties.credentials[cred].businessUnits[bu]))
762
+ ) {
763
+ const buObject = await Cli.getCredentialObject(
764
+ properties,
765
+ cred === null ? null : cred + '/' + bu,
766
+ null,
767
+ true
768
+ );
769
+ if (buObject === null) {
770
+ return;
771
+ } else {
772
+ cred = buObject.credential;
773
+ bu = buObject.businessUnit;
774
+ }
775
+ }
776
+ if (bu === '*' && properties.credentials && properties.credentials[cred]) {
777
+ Util.logger.info(`\n :: Executing the entity on all BUs for ${cred}`);
778
+ let counter_credBu = 0;
779
+ for (const bu in properties.credentials[cred].businessUnits) {
780
+ if (await this._executeBU(cred, bu, selectedTypesArr, keys)) {
781
+ counter_credBu++;
782
+ } else {
783
+ counter_failed++;
784
+ }
785
+ Util.startLogger(true);
786
+ }
787
+ Util.logger.info(
788
+ `\n :: Executed the entity on ${counter_credBu} BUs for ${cred}\n`
789
+ );
790
+ } else {
791
+ // execute the entity on one BU only
792
+ if (await this._executeBU(cred, bu, selectedTypesArr, keys)) {
793
+ counter_credBu++;
794
+ } else {
795
+ counter_failed++;
796
+ }
797
+ Util.logger.info(`\n :: Done\n`);
798
+ }
799
+ }
800
+ if (counter_credBu !== 0) {
801
+ Util.logger.info(`\n :: Executed query on ${counter_credBu} BUs\n`);
802
+ }
803
+ return counter_failed === 0 ? true : false;
804
+ }
805
+ /**
806
+ * helper for {@link execute}
807
+ *
808
+ * @param {string} cred name of Credential
809
+ * @param {string} bu name of BU
810
+ * @param {TYPE.SupportedMetadataTypes[]} [selectedTypesArr] limit execution to given metadata type
811
+ * @param {string[]} keyArr customerkey of the metadata
812
+ * @returns {Promise.<boolean>} true if all items were executed, false otherwise
813
+ */
814
+ static async _executeBU(cred, bu, selectedTypesArr, keyArr) {
815
+ const properties = await config.getProperties();
816
+ let counter_failed = 0;
817
+ const buObject = await Cli.getCredentialObject(
818
+ properties,
819
+ cred === null ? null : cred + '/' + bu,
820
+ null,
821
+ true
822
+ );
823
+ if (!keyArr || (Array.isArray(keyArr) && !keyArr.length)) {
824
+ throw new Error('No keys were provided');
825
+ }
826
+ if (!selectedTypesArr || (Array.isArray(selectedTypesArr) && !selectedTypesArr.length)) {
827
+ throw new Error('No type was provided');
828
+ }
829
+ if (buObject !== null) {
830
+ cache.initCache(buObject);
831
+ cred = buObject.credential;
832
+ bu = buObject.businessUnit;
833
+ }
834
+ Util.logger.info(
835
+ `\n :: Executing ${selectedTypesArr.join(', ')} on ${cred}/${bu}\n`
836
+ );
837
+ try {
838
+ // more than one type was provided, iterate types and execute items
839
+ for (const type of selectedTypesArr) {
840
+ try {
841
+ MetadataTypeInfo[type].client = auth.getSDK(buObject);
842
+ } catch (ex) {
843
+ Util.logger.error(ex.message);
844
+ return;
845
+ }
846
+ // result will be undefined (false) if execute is not supported for the type
847
+ if (!(await MetadataTypeInfo[type].execute(keyArr))) {
848
+ counter_failed++;
849
+ }
850
+ }
851
+ } catch (ex) {
852
+ Util.logger.errorStack(ex, 'mcdev.execute failed');
853
+ }
854
+ return counter_failed === 0 ? true : false;
855
+ }
685
856
  }
686
857
 
687
858
  module.exports = Mcdev;