mcdev 5.2.0 → 5.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 (106) hide show
  1. package/.fork/custom-commands.json +12 -0
  2. package/.github/ISSUE_TEMPLATE/bug.yml +1 -0
  3. package/.github/PULL_REQUEST_TEMPLATE/pr_template_release.md +19 -0
  4. package/docs/dist/documentation.md +400 -9
  5. package/lib/MetadataTypeDefinitions.js +1 -0
  6. package/lib/MetadataTypeInfo.js +1 -0
  7. package/lib/cli.js +6 -1
  8. package/lib/index.js +4 -1
  9. package/lib/metadataTypes/AttributeSet.js +118 -11
  10. package/lib/metadataTypes/Automation.js +99 -70
  11. package/lib/metadataTypes/DataExtension.js +463 -66
  12. package/lib/metadataTypes/DataExtensionField.js +30 -13
  13. package/lib/metadataTypes/Journey.js +8 -1
  14. package/lib/metadataTypes/MetadataType.js +63 -5
  15. package/lib/metadataTypes/MobileKeyword.js +1 -1
  16. package/lib/metadataTypes/TransactionalEmail.js +94 -17
  17. package/lib/metadataTypes/TransactionalMessage.js +3 -2
  18. package/lib/metadataTypes/Verification.js +230 -0
  19. package/lib/metadataTypes/definitions/AttributeGroup.definition.js +2 -2
  20. package/lib/metadataTypes/definitions/AttributeSet.definition.js +74 -21
  21. package/lib/metadataTypes/definitions/Automation.definition.js +1 -0
  22. package/lib/metadataTypes/definitions/TransactionalEmail.definition.js +19 -1
  23. package/lib/metadataTypes/definitions/Verification.definition.js +88 -0
  24. package/package.json +6 -6
  25. package/test/mockRoot/.mcdevrc.json +1 -1
  26. package/test/mockRoot/deploy/testInstance/_ParentBU_/dataExtension/testExisting_dataExtensionShared.dataExtension-meta.json +59 -0
  27. package/test/mockRoot/deploy/testInstance/_ParentBU_/dataExtension/testNew_dataExtensionShared.dataExtension-meta.json +23 -0
  28. package/test/mockRoot/deploy/testInstance/testBU/automation/testNew_automation.automation-meta.json +4 -0
  29. package/test/mockRoot/deploy/testInstance/testBU/dataExtension/testExisting_dataExtension.dataExtension-meta.json +1 -0
  30. package/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json +3 -4
  31. package/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testNew_temail.transactionalEmail-meta.json +1 -6
  32. package/test/mockRoot/deploy/testInstance/testBU/verification/testExisting_39f6a488-20eb-4ba0-b0b9.verification-meta.json +11 -0
  33. package/test/mockRoot/deploy/testInstance/testBU/verification/testNew_39f6a488-20eb-4ba0-b0b9.verification-meta.json +11 -0
  34. package/test/resources/1111111/data/v1/customobjectdata/key/testExisting_dataExtensionShared/rowset/get-response.json +13 -0
  35. package/test/resources/1111111/dataExtension/create-expected.json +23 -0
  36. package/test/resources/1111111/dataExtension/create-response.xml +59 -0
  37. package/test/resources/1111111/dataExtension/retrieve-expected.json +55 -0
  38. package/test/resources/1111111/dataExtension/retrieve-expected.md +18 -0
  39. package/test/resources/1111111/dataExtension/retrieve-response.xml +27 -1
  40. package/test/resources/1111111/dataExtension/update-expected.json +55 -0
  41. package/test/resources/1111111/dataExtension/update-response.xml +57 -0
  42. package/test/resources/1111111/dataExtensionField/retrieve-CustomerKey=[testExisting_dataExtensionShared].[TriggerUpdate_randomNumber_]-response.xml +45 -0
  43. package/test/resources/1111111/dataExtensionField/retrieve-DataExtension.CustomerKey=testExisting_dataExtensionShared-response.xml +98 -0
  44. package/test/resources/1111111/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_dataExtensionSharedORDataExtension.CustomerKey=testExisting_dataExtensionShared-response.xml +98 -0
  45. package/test/resources/1111111/dataExtensionField/retrieve-response.xml +98 -0
  46. package/test/resources/1111111/dataExtensionTemplate/retrieve-response.xml +303 -0
  47. package/test/resources/1111111/dataFolder/retrieve-ContentType=synchronizeddataextensionORContentType=shared_salesforcedataextensionORContentType=shared_dataextensionORContentType=shared_dataORContentType=salesforcedataextensionORContentType=dataextensionORContentType=hidden-response.xml +387 -0
  48. package/test/resources/1111111/dataFolder/retrieve-response.xml +353 -9
  49. package/test/resources/9999999/attributeSet/retrieve-expected.json +89 -694
  50. package/test/resources/9999999/automation/build-expected.json +4 -0
  51. package/test/resources/9999999/automation/create-expected.json +4 -0
  52. package/test/resources/9999999/automation/create-testNew_automation-expected.md +1 -0
  53. package/test/resources/9999999/automation/retrieve-expected.json +4 -0
  54. package/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md +1 -0
  55. package/test/resources/9999999/automation/template-expected.json +4 -0
  56. package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json +7 -0
  57. package/test/resources/9999999/automation/v1/automations/post-response.json +7 -0
  58. package/test/resources/9999999/automation/v1/dataverifications/post-response.json +12 -0
  59. package/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/delete-response.json +0 -0
  60. package/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/get-response.json +12 -0
  61. package/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/patch-response.json +12 -0
  62. package/test/resources/9999999/dataExtension/build-expected.json +16 -0
  63. package/test/resources/9999999/dataExtension/delete-response.xml +42 -0
  64. package/test/resources/9999999/dataExtension/retrieve-expected.json +16 -0
  65. package/test/resources/9999999/dataExtension/retrieve-expected.md +3 -1
  66. package/test/resources/9999999/dataExtension/template-expected.json +16 -0
  67. package/test/resources/9999999/dataExtension/update-expected.json +17 -1
  68. package/test/resources/9999999/dataExtensionField/retrieve-CustomerKey=[testExisting_dataExtension].[LastName]-response.xml +44 -0
  69. package/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testExisting_dataExtension-response.xml +36 -1
  70. package/test/resources/9999999/dataExtensionField/retrieve-response.xml +36 -1
  71. package/test/resources/9999999/dataFolder/retrieve-ContentType=synchronizeddataextensionORContentType=shared_salesforcedataextensionORContentType=shared_dataextensionORContentType=shared_dataORContentType=salesforcedataextensionORContentType=dataextensionORContentType=hidden-response.xml +117 -0
  72. package/test/resources/9999999/hub/v1/contacts/schema/attributeGroups/get-response.json +43 -0
  73. package/test/resources/9999999/hub/v1/contacts/schema/setDefinitions/get-response.json +387 -0
  74. package/test/resources/9999999/interaction/v1/interactions/233d4413-922c-4568-85a5-e5cc77efc3be/delete-response.json +1 -0
  75. package/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/get-response.json +1 -1
  76. package/test/resources/9999999/messaging/v1/email/definitions/post-response.json +1 -1
  77. package/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/delete-response.json +6 -0
  78. package/test/resources/9999999/transactionalEmail/build-expected.json +3 -7
  79. package/test/resources/9999999/transactionalEmail/get-expected.json +3 -7
  80. package/test/resources/9999999/transactionalEmail/patch-expected.json +3 -7
  81. package/test/resources/9999999/transactionalEmail/post-expected.json +3 -7
  82. package/test/resources/9999999/transactionalEmail/template-expected.json +3 -7
  83. package/test/resources/9999999/verification/build-expected.json +11 -0
  84. package/test/resources/9999999/verification/get-expected.json +11 -0
  85. package/test/resources/9999999/verification/patch-expected.json +11 -0
  86. package/test/resources/9999999/verification/post-expected.json +11 -0
  87. package/test/resources/9999999/verification/template-expected.json +11 -0
  88. package/test/type.attributeGroup.test.js +4 -4
  89. package/test/type.attributeSet.test.js +5 -5
  90. package/test/type.automation.test.js +29 -23
  91. package/test/type.dataExtension.test.js +205 -45
  92. package/test/type.dataExtract.test.js +10 -3
  93. package/test/type.fileTransfer.test.js +10 -3
  94. package/test/type.importFile.test.js +10 -3
  95. package/test/type.journey.test.js +38 -11
  96. package/test/type.mobileKeyword.test.js +6 -4
  97. package/test/type.mobileMessage.test.js +6 -4
  98. package/test/type.query.test.js +8 -6
  99. package/test/type.script.test.js +6 -1
  100. package/test/type.transactionalEmail.test.js +12 -11
  101. package/test/type.transactionalPush.test.js +2 -4
  102. package/test/type.transactionalSMS.test.js +2 -4
  103. package/test/type.triggeredSend.test.js +6 -4
  104. package/test/type.verification.test.js +173 -0
  105. package/test/utils.js +7 -1
  106. package/types/mcdev.d.js +14 -0
@@ -458,7 +458,7 @@ describe('type: query', () => {
458
458
  // check number of API calls
459
459
  assert.equal(
460
460
  testUtils.getAPIHistoryLength(),
461
- 33,
461
+ 34,
462
462
  'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
463
463
  );
464
464
  return;
@@ -498,7 +498,7 @@ describe('type: query', () => {
498
498
  // check number of API calls
499
499
  assert.equal(
500
500
  testUtils.getAPIHistoryLength(),
501
- 35,
501
+ 36,
502
502
  'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
503
503
  );
504
504
  return;
@@ -656,13 +656,15 @@ describe('type: query', () => {
656
656
  describe('Delete ================', () => {
657
657
  it('Should delete the item', async () => {
658
658
  // WHEN
659
- const result = await handler.deleteByKey('testInstance/testBU', 'query', [
660
- 'testExisting_query',
661
- ]);
659
+ const isDeleted = await handler.deleteByKey(
660
+ 'testInstance/testBU',
661
+ 'query',
662
+ 'testExisting_query'
663
+ );
662
664
  // THEN
663
665
  assert.equal(process.exitCode, false, 'delete should not have thrown an error');
664
666
 
665
- assert.equal(result, true, 'should have deleted the item');
667
+ assert.equal(isDeleted, true, 'should have deleted the item');
666
668
  return;
667
669
  });
668
670
  });
@@ -358,7 +358,12 @@ describe('type: script', () => {
358
358
  assert.equal(
359
359
  fileList[1].split('\\').join('/'),
360
360
  'retrieve/testInstance/testBU/script/testExisting_script.script-meta.ssjs',
361
- 'wrong JSON path'
361
+ 'wrong SSJS path'
362
+ );
363
+ assert.equal(
364
+ fileList[2].split('\\').join('/'),
365
+ 'retrieve/testInstance/testBU/script/testExisting_script.script-meta.html',
366
+ 'wrong HTML path'
362
367
  );
363
368
  return;
364
369
  });
@@ -142,17 +142,18 @@ describe('type: transactionalEmail', () => {
142
142
  });
143
143
  });
144
144
  describe('Delete ================', () => {
145
- // TODO: add this test
146
- it('Should delete the item'); // , async () => {
147
- // // WHEN
148
- // const result = await handler.deleteByKey('testInstance/testBU', 'mobileKeyword', [
149
- // 'testExisting_keyword',
150
- // ]);
151
- // // THEN
152
- // assert.equal(process.exitCode, false, 'delete should not have thrown an error');
145
+ it('Should delete the item', async () => {
146
+ // WHEN
147
+ const isDeleted = await handler.deleteByKey(
148
+ 'testInstance/testBU',
149
+ 'transactionalEmail',
150
+ 'testExisting_temail'
151
+ );
152
+ // THEN
153
+ assert.equal(process.exitCode, false, 'delete should not have thrown an error');
153
154
 
154
- // assert.equal(result, true, 'should have deleted the item');
155
- // return;
156
- // });
155
+ assert.equal(isDeleted, true, 'should have deleted the item');
156
+ return;
157
+ });
157
158
  });
158
159
  });
@@ -146,13 +146,11 @@ describe('type: transactionalPush', () => {
146
146
  // TODO: add this test
147
147
  it('Should delete the item'); // , async () => {
148
148
  // // WHEN
149
- // const result = await handler.deleteByKey('testInstance/testBU', 'mobileKeyword', [
150
- // 'testExisting_keyword',
151
- // ]);
149
+ // const isDeleted = await handler.deleteByKey('testInstance/testBU', 'mobileKeyword', 'testExisting_keyword');
152
150
  // // THEN
153
151
  // assert.equal(process.exitCode, false, 'delete should not have thrown an error');
154
152
 
155
- // assert.equal(result, true, 'should have deleted the item');
153
+ // assert.equal(isDeleted, true, 'should have deleted the item');
156
154
  // return;
157
155
  // });
158
156
  });
@@ -176,13 +176,11 @@ describe('type: transactionalSMS', () => {
176
176
  // TODO: add this test
177
177
  it('Should delete the item'); // , async () => {
178
178
  // // WHEN
179
- // const result = await handler.deleteByKey('testInstance/testBU', 'mobileKeyword', [
180
- // 'testExisting_keyword',
181
- // ]);
179
+ // const isDeleted = await handler.deleteByKey('testInstance/testBU', 'mobileKeyword', 'testExisting_keyword');
182
180
  // // THEN
183
181
  // assert.equal(process.exitCode, false, 'delete should not have thrown an error');
184
182
 
185
- // assert.equal(result, true, 'should have deleted the item');
183
+ // assert.equal(isDeleted, true, 'should have deleted the item');
186
184
  // return;
187
185
  // });
188
186
  });
@@ -130,13 +130,15 @@ describe('type: triggeredSend', () => {
130
130
  describe('Delete ================', () => {
131
131
  it('Should delete the item', async () => {
132
132
  // WHEN
133
- const result = await handler.deleteByKey('testInstance/testBU', 'triggeredSend', [
134
- 'testExisting_triggeredSend',
135
- ]);
133
+ const isDeleted = await handler.deleteByKey(
134
+ 'testInstance/testBU',
135
+ 'triggeredSend',
136
+ 'testExisting_triggeredSend'
137
+ );
136
138
  // THEN
137
139
  assert.equal(process.exitCode, false, 'delete should not have thrown an error');
138
140
 
139
- assert.equal(result, true, 'should have deleted the item');
141
+ assert.equal(isDeleted, true, 'should have deleted the item');
140
142
  return;
141
143
  });
142
144
  });
@@ -0,0 +1,173 @@
1
+ const chai = require('chai');
2
+ const chaiFiles = require('chai-files');
3
+ const assert = chai.assert;
4
+ chai.use(chaiFiles);
5
+ const cache = require('../lib/util/cache');
6
+ const testUtils = require('./utils');
7
+ const handler = require('../lib/index');
8
+
9
+ describe('type: verification', () => {
10
+ beforeEach(() => {
11
+ testUtils.mockSetup();
12
+ });
13
+ afterEach(() => {
14
+ testUtils.mockReset();
15
+ });
16
+
17
+ describe('Retrieve ================', () => {
18
+ it('Should retrieve a verification', async () => {
19
+ // WHEN
20
+ const retrieved = await handler.retrieve('testInstance/testBU', ['verification']);
21
+ // THEN
22
+ assert.equal(process.exitCode, false, 'retrieve should not have thrown an error');
23
+ // get results from cache
24
+ const result = cache.getCache();
25
+ assert.equal(
26
+ result.verification ? Object.keys(result.verification).length : 0,
27
+ 1,
28
+ 'only one verification expected'
29
+ );
30
+ assert.equal(
31
+ retrieved['testInstance/testBU']?.verification
32
+ ? Object.keys(retrieved['testInstance/testBU']?.verification).length
33
+ : 0,
34
+ 1,
35
+ 'one verifications to be retrieved'
36
+ );
37
+
38
+ assert.deepEqual(
39
+ await testUtils.getActualJson(
40
+ 'testExisting_39f6a488-20eb-4ba0-b0b9',
41
+ 'verification'
42
+ ),
43
+ await testUtils.getExpectedJson('9999999', 'verification', 'get'),
44
+ 'returned JSON was not equal expected'
45
+ );
46
+ assert.equal(
47
+ testUtils.getAPIHistoryLength(),
48
+ 9,
49
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
50
+ );
51
+ return;
52
+ });
53
+ });
54
+ describe('Deploy ================', () => {
55
+ beforeEach(() => {
56
+ testUtils.mockSetup(true);
57
+ });
58
+ it('Should create & upsert a verification', async () => {
59
+ // WHEN
60
+
61
+ const deployed = await handler.deploy('testInstance/testBU', ['verification']);
62
+ // THEN
63
+ assert.equal(process.exitCode, false, 'deploy should not have thrown an error');
64
+ // get results from cache
65
+ const result = cache.getCache();
66
+ assert.equal(
67
+ result.verification ? Object.keys(result.verification).length : 0,
68
+ 2,
69
+ 'two verifications expected'
70
+ );
71
+ assert.equal(
72
+ deployed['testInstance/testBU']?.verification
73
+ ? Object.keys(deployed['testInstance/testBU']?.verification).length
74
+ : 0,
75
+ 2,
76
+ 'two verifications to be deployed'
77
+ );
78
+ // confirm created item
79
+ assert.deepEqual(
80
+ await testUtils.getActualJson('testNew_RANDOM_NEW_GUID', 'verification'),
81
+ await testUtils.getExpectedJson('9999999', 'verification', 'post'),
82
+ 'returned new-JSON was not equal expected for insert verification'
83
+ );
84
+ // confirm updated item
85
+ assert.deepEqual(
86
+ await testUtils.getActualJson(
87
+ 'testExisting_39f6a488-20eb-4ba0-b0b9',
88
+ 'verification'
89
+ ),
90
+ await testUtils.getExpectedJson('9999999', 'verification', 'patch'),
91
+ 'returned existing-JSON was not equal expected for update verification'
92
+ );
93
+ // check number of API calls
94
+ assert.equal(
95
+ testUtils.getAPIHistoryLength(),
96
+ 11,
97
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
98
+ );
99
+ return;
100
+ });
101
+ });
102
+ describe('Templating ================', () => {
103
+ it('Should create a verification template via buildTemplate and build it', async () => {
104
+ // download first before we test buildTemplate
105
+ await handler.retrieve('testInstance/testBU', ['verification']);
106
+ // buildTemplate
107
+ const result = await handler.buildTemplate(
108
+ 'testInstance/testBU',
109
+ 'verification',
110
+ ['testExisting_39f6a488-20eb-4ba0-b0b9'],
111
+ 'testSourceMarket'
112
+ );
113
+ assert.equal(process.exitCode, false, 'buildTemplate should not have thrown an error');
114
+ assert.equal(
115
+ result.verification ? Object.keys(result.verification).length : 0,
116
+ 1,
117
+ 'only one verification expected'
118
+ );
119
+ assert.deepEqual(
120
+ await testUtils.getActualTemplateJson(
121
+ 'testExisting_39f6a488-20eb-4ba0-b0b9',
122
+ 'verification'
123
+ ),
124
+ await testUtils.getExpectedJson('9999999', 'verification', 'template'),
125
+ 'returned template JSON was not equal expected'
126
+ );
127
+ // buildDefinition
128
+ await handler.buildDefinition(
129
+ 'testInstance/testBU',
130
+ 'verification',
131
+ 'testExisting_39f6a488-20eb-4ba0-b0b9',
132
+ 'testTargetMarket'
133
+ );
134
+ assert.equal(
135
+ process.exitCode,
136
+ false,
137
+ 'buildDefinition should not have thrown an error'
138
+ );
139
+ assert.deepEqual(
140
+ await testUtils.getActualDeployJson(
141
+ 'testTemplated_39f6a488-20eb-4ba0-b0b9',
142
+ 'verification'
143
+ ),
144
+ await testUtils.getExpectedJson('9999999', 'verification', 'build'),
145
+ 'returned deployment JSON was not equal expected'
146
+ );
147
+ assert.equal(
148
+ testUtils.getAPIHistoryLength(),
149
+ 9,
150
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
151
+ );
152
+ return;
153
+ });
154
+ });
155
+ describe('Delete ================', () => {
156
+ it('Should delete the item', async () => {
157
+ // WHEN
158
+ const isDeleted = await handler.deleteByKey(
159
+ 'testInstance/testBU',
160
+ 'verification',
161
+ 'testExisting_39f6a488-20eb-4ba0-b0b9'
162
+ );
163
+ // THEN
164
+ assert.equal(
165
+ process.exitCode,
166
+ 0,
167
+ 'deleteByKey should have thrown an error due to lack of support'
168
+ );
169
+ assert.equal(isDeleted, true, 'deleteByKey should have returned true for success');
170
+ return;
171
+ });
172
+ });
173
+ });
package/test/utils.js CHANGED
@@ -208,7 +208,13 @@ exports.getAPIHistory = () => apimock.history;
208
208
  function getAPIHistoryDebug() {
209
209
  const historyArr = Object.values(apimock.history)
210
210
  .flat()
211
- .map((item) => ({ url: item.url, data: item.data }));
211
+ .map((item) => {
212
+ const log = { method: item.method, url: item.url };
213
+ if (item.data) {
214
+ log.body = item.data;
215
+ }
216
+ return log;
217
+ });
212
218
  return historyArr;
213
219
  }
214
220
  exports.getAPIHistoryDebug = getAPIHistoryDebug;
package/types/mcdev.d.js CHANGED
@@ -251,6 +251,20 @@ const SDK = require('sfmc-sdk');
251
251
  * @property {string} r__folder_Path folder path
252
252
  * @property {string} [categoryId] holds folder ID, replaced with r__folder_Path during retrieve
253
253
  */
254
+ /**
255
+ * @typedef {object} VerificationItem
256
+ * @property {string} dataVerificationDefinitionId ID / Key
257
+ * @property {'IsEqualTo'|'IsLessThan'|'IsGreaterThan'|'IsOutsideRange'|'IsInsideRange'|'IsNotEqualTo'|'IsNotLessThan'|'IsNotGreaterThan'|'IsNotOutsideRange'|'IsNotInsideRange'} verificationType key
258
+ * @property {number} value1 used for all verificationTypes; lower value for IsOutsideRange, IsInsideRange, IsNotOutsideRange, IsNotInsideRange
259
+ * @property {number} value2 only used for IsOutsideRange, IsInsideRange, IsNotOutsideRange, IsNotInsideRange; otherwise set to 0
260
+ * @property {boolean} shouldStopOnFailure flag to stop automation if verification fails
261
+ * @property {boolean} shouldEmailOnFailure flag to send email if verification fails
262
+ * @property {string} notificationEmailAddress email address to send notification to; empty string if shouldEmailOnFailure=false
263
+ * @property {string} notificationEmailMessage email message to send; empty string if shouldEmailOnFailure=false
264
+ * @property {number} createdBy user id of creator
265
+ * @property {string} r__dataExtension_CustomerKey key of target data extension
266
+ */
267
+
254
268
  /**
255
269
  * @typedef {Object.<string, AutomationItem>} AutomationMap
256
270
  * @typedef {{metadata:AutomationMap,type:string}} AutomationMapObj