mcdev 3.0.2 → 3.1.2

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 (44) hide show
  1. package/.eslintrc.json +1 -1
  2. package/.github/ISSUE_TEMPLATE/bug.yml +75 -0
  3. package/.github/PULL_REQUEST_TEMPLATE.md +3 -2
  4. package/.issuetracker +11 -3
  5. package/.vscode/settings.json +3 -3
  6. package/CHANGELOG.md +88 -0
  7. package/README.md +245 -141
  8. package/boilerplate/config.json +3 -2
  9. package/docs/dist/documentation.md +818 -352
  10. package/lib/Deployer.js +4 -1
  11. package/lib/MetadataTypeDefinitions.js +1 -0
  12. package/lib/MetadataTypeInfo.js +1 -0
  13. package/lib/Retriever.js +30 -14
  14. package/lib/cli.js +295 -0
  15. package/lib/index.js +774 -1019
  16. package/lib/metadataTypes/AccountUser.js +389 -0
  17. package/lib/metadataTypes/Asset.js +8 -7
  18. package/lib/metadataTypes/Automation.js +121 -56
  19. package/lib/metadataTypes/DataExtension.js +167 -121
  20. package/lib/metadataTypes/DataExtensionField.js +134 -4
  21. package/lib/metadataTypes/DataExtract.js +9 -5
  22. package/lib/metadataTypes/EventDefinition.js +9 -5
  23. package/lib/metadataTypes/FileTransfer.js +9 -5
  24. package/lib/metadataTypes/Folder.js +66 -69
  25. package/lib/metadataTypes/ImportFile.js +13 -12
  26. package/lib/metadataTypes/MetadataType.js +138 -77
  27. package/lib/metadataTypes/Query.js +2 -3
  28. package/lib/metadataTypes/Role.js +13 -8
  29. package/lib/metadataTypes/Script.js +2 -2
  30. package/lib/metadataTypes/definitions/AccountUser.definition.js +227 -0
  31. package/lib/metadataTypes/definitions/Asset.definition.js +1 -0
  32. package/lib/metadataTypes/definitions/DataExtension.definition.js +1 -1
  33. package/lib/metadataTypes/definitions/DataExtensionField.definition.js +1 -1
  34. package/lib/metadataTypes/definitions/Folder.definition.js +1 -1
  35. package/lib/metadataTypes/definitions/ImportFile.definition.js +2 -1
  36. package/lib/metadataTypes/definitions/Script.definition.js +5 -5
  37. package/lib/retrieveChangelog.js +96 -0
  38. package/lib/util/cli.js +4 -6
  39. package/lib/util/init.git.js +2 -1
  40. package/lib/util/util.js +20 -3
  41. package/package.json +19 -23
  42. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -30
  43. package/img/README.md/troubleshoot-nodejs-postinstall.jpg +0 -0
  44. package/postinstall.js +0 -41
@@ -92,14 +92,10 @@ class Automation extends MetadataType {
92
92
  * @returns {Promise<{metadata:AutomationMap,type:string}>} Promise of metadata
93
93
  */
94
94
  static async retrieve(retrieveDir) {
95
- const results = await new Promise((resolve) => {
96
- this.client.SoapClient.retrieve('Program', ['ObjectID'], (error, response) => {
97
- if (error) {
98
- throw new Error(error);
99
- } else {
100
- resolve(response.body.Results);
101
- }
102
- });
95
+ const results = await new Promise((resolve, reject) => {
96
+ this.client.SoapClient.retrieve('Program', ['ObjectID'], (ex, response) =>
97
+ ex ? reject(ex) : resolve(response.body.Results)
98
+ );
103
99
  });
104
100
  const details = (
105
101
  await Promise.all(
@@ -116,6 +112,60 @@ class Automation extends MetadataType {
116
112
  Util.logger.info(
117
113
  `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})`
118
114
  );
115
+ return { metadata: savedMetadata, type: this.definition.type };
116
+ }
117
+ /**
118
+ * Retrieves Metadata of Automation
119
+ * @returns {Promise<{metadata:AutomationMap,type:string}>} Promise of metadata
120
+ */
121
+ static async retrieveChangelog() {
122
+ const results = await new Promise((resolve, reject) => {
123
+ this.client.SoapClient.retrieve(
124
+ 'Program',
125
+ ['ObjectID'],
126
+
127
+ (ex, response) => (ex ? reject(ex) : resolve(response.body.Results))
128
+ );
129
+ });
130
+ const details = [];
131
+ (
132
+ await Promise.all(
133
+ results.map(async (a) => {
134
+ const options = {
135
+ filter: {
136
+ leftOperand: 'ProgramID',
137
+ operator: 'equals',
138
+ rightOperand: a.ObjectID,
139
+ },
140
+ };
141
+
142
+ return new Promise((resolve, reject) => {
143
+ this.client.SoapClient.retrieve(
144
+ 'Automation',
145
+ [
146
+ 'ProgramID',
147
+ 'Name',
148
+ 'CustomerKey',
149
+ 'LastSaveDate',
150
+ 'LastSavedBy',
151
+ 'CreatedBy',
152
+ 'CreatedDate',
153
+ ],
154
+ options,
155
+ (ex, response) => (ex ? reject(ex) : resolve(response.body.Results))
156
+ );
157
+ });
158
+ })
159
+ )
160
+ ).forEach((item) => {
161
+ details.push(...item);
162
+ });
163
+ details.map((item) => {
164
+ item.key = item.CustomerKey;
165
+ });
166
+
167
+ const parsed = this.parseResponseBody({ items: details });
168
+
119
169
  return { metadata: parsed, type: this.definition.type };
120
170
  }
121
171
 
@@ -152,10 +202,10 @@ class Automation extends MetadataType {
152
202
  * Retrieve a specific Automation Definition by Name
153
203
  * @param {string} templateDir Directory where retrieved metadata directory will be saved
154
204
  * @param {string} name name of the metadata file
155
- * @param {Util.TemplateMap} variables variables to be replaced in the metadata
205
+ * @param {Util.TemplateMap} templateVariables variables to be replaced in the metadata
156
206
  * @returns {Promise<{metadata:AutomationMap,type:string}>} Promise of metadata
157
207
  */
158
- static async retrieveAsTemplate(templateDir, name, variables) {
208
+ static async retrieveAsTemplate(templateDir, name, templateVariables) {
159
209
  const results = await new Promise((resolve) => {
160
210
  this.client.SoapClient.retrieve(
161
211
  'Program',
@@ -189,12 +239,14 @@ class Automation extends MetadataType {
189
239
  })
190
240
  ).body;
191
241
  let val = null;
242
+ let originalKey;
192
243
  // if parsing fails, we should just save what we get
193
244
  try {
194
245
  const parsedDetails = this.parseMetadata(details);
246
+ originalKey = parsedDetails[this.definition.keyField];
195
247
  if (parsedDetails !== null) {
196
248
  val = JSON.parse(
197
- Util.replaceByObject(JSON.stringify(parsedDetails), variables)
249
+ Util.replaceByObject(JSON.stringify(parsedDetails), templateVariables)
198
250
  );
199
251
  }
200
252
  } catch (ex) {
@@ -209,7 +261,7 @@ class Automation extends MetadataType {
209
261
  this.keepTemplateFields(val);
210
262
  File.writeJSONToFile(
211
263
  [templateDir, this.definition.type].join('/'),
212
- val[this.definition.keyField] + '.' + this.definition.type + '-meta',
264
+ originalKey + '.' + this.definition.type + '-meta',
213
265
  val
214
266
  );
215
267
  Util.logger.info(
@@ -315,9 +367,8 @@ class Automation extends MetadataType {
315
367
  delete metadata.schedule.scheduledTime;
316
368
  delete metadata.schedule.scheduledStatus;
317
369
  if (this.definition.timeZoneMapping[metadata.schedule.timezoneName]) {
318
- metadata.schedule.timezoneId = this.definition.timeZoneMapping[
319
- metadata.schedule.timezoneName
320
- ];
370
+ metadata.schedule.timezoneId =
371
+ this.definition.timeZoneMapping[metadata.schedule.timezoneName];
321
372
  } else {
322
373
  Util.logger.error(
323
374
  `Could not find timezone ${metadata.schedule.timezoneName} in definition.timeZoneMapping`
@@ -435,44 +486,56 @@ class Automation extends MetadataType {
435
486
  }
436
487
  if (schedule !== null) {
437
488
  try {
438
- await new Promise((resolve, reject) => {
439
- this.client.SoapClient.schedule(
440
- 'Automation',
441
- schedule,
442
- {
443
- Interaction: {
444
- ObjectID: metadata[key].id,
445
- },
446
- },
447
- 'start',
448
- null,
449
- (error, response) => {
450
- if (
451
- error ||
452
- (response.body.Results &&
453
- response.body.Results[0] &&
454
- response.body.Results[0].StatusCode &&
455
- response.body.Results[0].StatusCode === 'Error')
456
- ) {
457
- reject(error || response.body.Results[0].StatusMessage);
458
- } else {
459
- resolve(response.body.Results);
460
- }
461
- }
462
- );
463
- });
464
- const intervalString =
465
- (schedule._interval > 1 ? `${schedule._interval} ` : '') +
466
- (schedule.RecurrenceType === 'Daily'
467
- ? 'Day'
468
- : schedule.RecurrenceType.slice(0, -2) +
469
- (schedule._interval > 1 ? 's' : ''));
470
- Util.logger.warn(
471
- `Automation '${
472
- originalMetadata[key].name
473
- }' deployed Active: runs every ${intervalString} starting ${
474
- schedule._StartDateTime.split('T').join(' ').split('.')[0]
475
- } ${schedule._timezoneString}`
489
+ await Util.retryOnError(
490
+ `Retrying ${this.definition.type}`,
491
+ async () => {
492
+ await new Promise((resolve, reject) => {
493
+ this.client.SoapClient.schedule(
494
+ 'Automation',
495
+ schedule,
496
+ {
497
+ Interaction: {
498
+ ObjectID: metadata[key].id,
499
+ },
500
+ },
501
+ 'start',
502
+ null,
503
+ (error, response) => {
504
+ if (
505
+ error ||
506
+ (response.body.Results &&
507
+ response.body.Results[0] &&
508
+ response.body.Results[0].StatusCode &&
509
+ response.body.Results[0].StatusCode ===
510
+ 'Error')
511
+ ) {
512
+ reject(
513
+ error ||
514
+ response.body.Results[0].StatusMessage
515
+ );
516
+ } else {
517
+ resolve(response.body.Results);
518
+ }
519
+ }
520
+ );
521
+ });
522
+ const intervalString =
523
+ (schedule._interval > 1 ? `${schedule._interval} ` : '') +
524
+ (schedule.RecurrenceType === 'Daily'
525
+ ? 'Day'
526
+ : schedule.RecurrenceType.slice(0, -2) +
527
+ (schedule._interval > 1 ? 's' : ''));
528
+ Util.logger.warn(
529
+ `Automation '${
530
+ originalMetadata[key].name
531
+ }' deployed Active: runs every ${intervalString} starting ${
532
+ schedule._StartDateTime
533
+ .split('T')
534
+ .join(' ')
535
+ .split('.')[0]
536
+ } ${schedule._timezoneString}`
537
+ );
538
+ }
476
539
  );
477
540
  } catch (ex) {
478
541
  Util.logger.error(
@@ -684,9 +747,8 @@ class Automation extends MetadataType {
684
747
  }
685
748
 
686
749
  if (this.definition.timeZoneMapping[scheduleObject.timezoneName]) {
687
- scheduleObject.timezoneId = this.definition.timeZoneMapping[
688
- scheduleObject.timezoneName
689
- ];
750
+ scheduleObject.timezoneId =
751
+ this.definition.timeZoneMapping[scheduleObject.timezoneName];
690
752
  } else {
691
753
  Util.logger.error(
692
754
  `Could not find timezone ${scheduleObject.timezoneName} in definition.timeZoneMapping`
@@ -780,6 +842,9 @@ class Automation extends MetadataType {
780
842
  // Assign definition to static attributes
781
843
  Automation.definition = Definitions.automation;
782
844
  Automation.cache = {};
845
+ /**
846
+ * @type {Util.ET_Client}
847
+ */
783
848
  Automation.client = undefined;
784
849
 
785
850
  module.exports = Automation;