mcdev 3.1.3 → 4.0.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 (134) hide show
  1. package/.eslintrc.json +67 -7
  2. package/.github/ISSUE_TEMPLATE/bug.yml +2 -1
  3. package/.github/PULL_REQUEST_TEMPLATE.md +5 -3
  4. package/.github/dependabot.yml +14 -0
  5. package/.github/workflows/code-analysis.yml +57 -0
  6. package/.husky/commit-msg +10 -0
  7. package/.husky/post-checkout +5 -0
  8. package/.husky/pre-commit +2 -1
  9. package/.prettierrc +8 -0
  10. package/.vscode/settings.json +1 -1
  11. package/LICENSE +2 -2
  12. package/README.md +134 -45
  13. package/boilerplate/config.json +5 -11
  14. package/boilerplate/files/.prettierrc +8 -0
  15. package/boilerplate/files/.vscode/extensions.json +0 -1
  16. package/boilerplate/files/.vscode/settings.json +28 -2
  17. package/boilerplate/files/README.md +2 -2
  18. package/boilerplate/forcedUpdates.json +10 -0
  19. package/boilerplate/npm-dependencies.json +5 -5
  20. package/docs/dist/documentation.md +2795 -1724
  21. package/jsconfig.json +1 -1
  22. package/lib/Builder.js +166 -75
  23. package/lib/Deployer.js +244 -96
  24. package/lib/MetadataTypeDefinitions.js +2 -0
  25. package/lib/MetadataTypeInfo.js +2 -0
  26. package/lib/Retriever.js +61 -84
  27. package/lib/cli.js +116 -11
  28. package/lib/index.js +241 -561
  29. package/lib/metadataTypes/AccountUser.js +101 -95
  30. package/lib/metadataTypes/Asset.js +677 -248
  31. package/lib/metadataTypes/AttributeGroup.js +23 -12
  32. package/lib/metadataTypes/Automation.js +451 -354
  33. package/lib/metadataTypes/Campaign.js +33 -93
  34. package/lib/metadataTypes/ContentArea.js +31 -11
  35. package/lib/metadataTypes/DataExtension.js +387 -372
  36. package/lib/metadataTypes/DataExtensionField.js +131 -54
  37. package/lib/metadataTypes/DataExtensionTemplate.js +22 -4
  38. package/lib/metadataTypes/DataExtract.js +61 -48
  39. package/lib/metadataTypes/DataExtractType.js +14 -8
  40. package/lib/metadataTypes/Discovery.js +21 -16
  41. package/lib/metadataTypes/Email.js +32 -12
  42. package/lib/metadataTypes/EmailSendDefinition.js +85 -80
  43. package/lib/metadataTypes/EventDefinition.js +61 -43
  44. package/lib/metadataTypes/FileTransfer.js +72 -52
  45. package/lib/metadataTypes/Filter.js +11 -4
  46. package/lib/metadataTypes/Folder.js +149 -117
  47. package/lib/metadataTypes/FtpLocation.js +14 -8
  48. package/lib/metadataTypes/ImportFile.js +61 -64
  49. package/lib/metadataTypes/Interaction.js +19 -4
  50. package/lib/metadataTypes/List.js +54 -13
  51. package/lib/metadataTypes/MetadataType.js +668 -454
  52. package/lib/metadataTypes/MobileCode.js +46 -0
  53. package/lib/metadataTypes/MobileKeyword.js +114 -0
  54. package/lib/metadataTypes/Query.js +204 -103
  55. package/lib/metadataTypes/Role.js +76 -61
  56. package/lib/metadataTypes/Script.js +145 -81
  57. package/lib/metadataTypes/SetDefinition.js +20 -8
  58. package/lib/metadataTypes/TriggeredSendDefinition.js +78 -58
  59. package/lib/metadataTypes/definitions/Asset.definition.js +21 -10
  60. package/lib/metadataTypes/definitions/AttributeGroup.definition.js +12 -0
  61. package/lib/metadataTypes/definitions/Automation.definition.js +10 -5
  62. package/lib/metadataTypes/definitions/Campaign.definition.js +44 -1
  63. package/lib/metadataTypes/definitions/DataExtension.definition.js +4 -0
  64. package/lib/metadataTypes/definitions/DataExtensionTemplate.definition.js +6 -0
  65. package/lib/metadataTypes/definitions/DataExtract.definition.js +18 -14
  66. package/lib/metadataTypes/definitions/Discovery.definition.js +12 -0
  67. package/lib/metadataTypes/definitions/EmailSendDefinition.definition.js +4 -0
  68. package/lib/metadataTypes/definitions/EventDefinition.definition.js +22 -0
  69. package/lib/metadataTypes/definitions/FileTransfer.definition.js +4 -0
  70. package/lib/metadataTypes/definitions/Filter.definition.js +4 -0
  71. package/lib/metadataTypes/definitions/Folder.definition.js +6 -0
  72. package/lib/metadataTypes/definitions/FtpLocation.definition.js +4 -0
  73. package/lib/metadataTypes/definitions/ImportFile.definition.js +10 -5
  74. package/lib/metadataTypes/definitions/Interaction.definition.js +4 -0
  75. package/lib/metadataTypes/definitions/MobileCode.definition.js +163 -0
  76. package/lib/metadataTypes/definitions/MobileKeyword.definition.js +253 -0
  77. package/lib/metadataTypes/definitions/Query.definition.js +4 -0
  78. package/lib/metadataTypes/definitions/Role.definition.js +5 -0
  79. package/lib/metadataTypes/definitions/Script.definition.js +4 -0
  80. package/lib/metadataTypes/definitions/SetDefinition.definition.js +28 -0
  81. package/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js +4 -0
  82. package/lib/retrieveChangelog.js +7 -6
  83. package/lib/util/auth.js +117 -0
  84. package/lib/util/businessUnit.js +55 -66
  85. package/lib/util/cache.js +194 -0
  86. package/lib/util/cli.js +90 -116
  87. package/lib/util/config.js +302 -0
  88. package/lib/util/devops.js +240 -50
  89. package/lib/util/file.js +120 -191
  90. package/lib/util/init.config.js +195 -69
  91. package/lib/util/init.git.js +45 -50
  92. package/lib/util/init.js +72 -59
  93. package/lib/util/init.npm.js +48 -39
  94. package/lib/util/util.js +280 -564
  95. package/package.json +44 -33
  96. package/test/dataExtension.test.js +152 -0
  97. package/test/mockRoot/.mcdev-auth.json +8 -0
  98. package/test/mockRoot/.mcdevrc.json +67 -0
  99. package/test/mockRoot/deploy/testInstance/testBU/dataExtension/childBU_dataextension_test.dataExtension-meta.json +39 -0
  100. package/test/mockRoot/deploy/testInstance/testBU/dataExtension/testDataExtension.dataExtension-meta.json +23 -0
  101. package/test/mockRoot/deploy/testInstance/testBU/query/testExistingQuery.query-meta.json +11 -0
  102. package/test/mockRoot/deploy/testInstance/testBU/query/testExistingQuery.query-meta.sql +4 -0
  103. package/test/mockRoot/deploy/testInstance/testBU/query/testQuery.query-meta.json +11 -0
  104. package/test/mockRoot/deploy/testInstance/testBU/query/testQuery.query-meta.sql +4 -0
  105. package/test/query.test.js +149 -0
  106. package/test/resourceFactory.js +142 -0
  107. package/test/resources/1111111/dataFolder/retrieve-response.xml +43 -0
  108. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/patch-response.json +18 -0
  109. package/test/resources/9999999/automation/v1/queries/get-response.json +24 -0
  110. package/test/resources/9999999/automation/v1/queries/post-response.json +18 -0
  111. package/test/resources/9999999/dataExtension/build-expected.json +51 -0
  112. package/test/resources/9999999/dataExtension/create-expected.json +23 -0
  113. package/test/resources/9999999/dataExtension/create-response.xml +54 -0
  114. package/test/resources/9999999/dataExtension/retrieve-expected.json +51 -0
  115. package/test/resources/9999999/dataExtension/retrieve-response.xml +47 -0
  116. package/test/resources/9999999/dataExtension/template-expected.json +51 -0
  117. package/test/resources/9999999/dataExtension/update-expected.json +55 -0
  118. package/test/resources/9999999/dataExtension/update-response.xml +52 -0
  119. package/test/resources/9999999/dataExtensionField/retrieve-response.xml +93 -0
  120. package/test/resources/9999999/dataExtensionTemplate/retrieve-response.xml +303 -0
  121. package/test/resources/9999999/dataFolder/retrieve-response.xml +65 -0
  122. package/test/resources/9999999/query/build-expected.json +8 -0
  123. package/test/resources/9999999/query/get-expected.json +11 -0
  124. package/test/resources/9999999/query/patch-expected.json +11 -0
  125. package/test/resources/9999999/query/post-expected.json +11 -0
  126. package/test/resources/9999999/query/template-expected.json +8 -0
  127. package/test/resources/auth.json +32 -0
  128. package/test/resources/rest404-response.json +5 -0
  129. package/test/resources/retrieve-response.xml +21 -0
  130. package/test/utils.js +107 -0
  131. package/types/mcdev.d.js +301 -0
  132. package/CHANGELOG.md +0 -126
  133. package/PULL_REQUEST_TEMPLATE.md +0 -19
  134. package/test/util/file.js +0 -51
@@ -1,55 +1,41 @@
1
1
  'use strict';
2
2
 
3
- const Util = require('../util/util');
4
-
5
- /**
6
- * @typedef {Object} DataExtensionFieldItem
7
- * @property {string} [ObjectID] id
8
- * @property {string} [CustomerKey] key in format [DEkey].[FieldName]
9
- * @property {Object} [DataExtension] -
10
- * @property {string} DataExtension.CustomerKey key of DE
11
- * @property {string} Name name of field
12
- * @property {string} [Name_new] custom attribute that is only used when trying to rename a field from Name to Name_new
13
- * @property {string} DefaultValue empty string for not set
14
- * @property {'true'|'false'} IsRequired -
15
- * @property {'true'|'false'} IsPrimaryKey -
16
- * @property {string} Ordinal 1, 2, 3, ...
17
- * @property {'Text'|'Number'|'Date'|'Boolean'|'Decimal'|'EmailAddress'|'Phone'|'Locale'} FieldType can only be set on create
18
- * @property {string} Scale the number of places after the decimal that the field can hold; example: "0","1", ...
19
- *
20
- * @typedef {Object.<string, DataExtensionFieldItem>} DataExtensionFieldMap
21
- */
22
-
3
+ const TYPE = require('../../types/mcdev.d');
23
4
  const MetadataType = require('./MetadataType');
5
+ const Util = require('../util/util');
24
6
 
25
7
  /**
26
8
  * DataExtensionField MetadataType
9
+ *
27
10
  * @augments MetadataType
28
11
  */
29
12
  class DataExtensionField extends MetadataType {
30
13
  /**
31
14
  * Retrieves all records and saves it to disk
15
+ *
32
16
  * @param {string} retrieveDir Directory where retrieved metadata directory will be saved
33
17
  * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true
34
- * @param {Object} buObject properties for auth
35
- * @returns {Promise<{metadata:DataExtensionFieldMap,type:string}>} Promise of items
18
+ * @param {TYPE.BuObject} buObject properties for auth
19
+ * @returns {Promise.<{metadata: TYPE.DataExtensionFieldMap, type: string}>} Promise of items
36
20
  */
37
21
  static async retrieve(retrieveDir, additionalFields, buObject) {
38
- return super.retrieveSOAPgeneric(retrieveDir, buObject, null, additionalFields);
22
+ return super.retrieveSOAP(retrieveDir, buObject, null, additionalFields);
39
23
  }
40
24
  /**
41
25
  * Retrieves all records for caching
42
- * @param {Object} [options] required for the specific request (filter for example)
26
+ *
27
+ * @param {TYPE.SoapRequestParams} [requestParams] required for the specific request (filter for example)
43
28
  * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true
44
- * @returns {Promise<{metadata:DataExtensionFieldMap,type:string}>} Promise of items
29
+ * @returns {Promise.<{metadata: TYPE.DataExtensionFieldMap, type: string}>} Promise of items
45
30
  */
46
- static async retrieveForCache(options, additionalFields) {
47
- return super.retrieveSOAPgeneric(null, null, options, additionalFields);
31
+ static async retrieveForCache(requestParams, additionalFields) {
32
+ return super.retrieveSOAP(null, null, requestParams, additionalFields);
48
33
  }
49
34
  /**
50
35
  * helper for DataExtension.js that sorts the fields into an array
51
- * @param {DataExtensionFieldMap} fieldsObj customerKey-based list of fields for one dataExtension
52
- * @returns {DataExtensionFieldItem[]} sorted array of field objects
36
+ *
37
+ * @param {TYPE.DataExtensionFieldMap} fieldsObj customerKey-based list of fields for one dataExtension
38
+ * @returns {TYPE.DataExtensionFieldItem[]} sorted array of field objects
53
39
  */
54
40
  static convertToSortedArray(fieldsObj) {
55
41
  return (
@@ -62,8 +48,9 @@ class DataExtensionField extends MetadataType {
62
48
 
63
49
  /**
64
50
  * sorting method to ensure `Ordinal` is respected
65
- * @param {DataExtensionFieldItem} a -
66
- * @param {DataExtensionFieldItem} b -
51
+ *
52
+ * @param {TYPE.DataExtensionFieldItem} a -
53
+ * @param {TYPE.DataExtensionFieldItem} b -
67
54
  * @returns {boolean} sorting based on Ordinal
68
55
  */
69
56
  static sortDeFields(a, b) {
@@ -71,9 +58,10 @@ class DataExtensionField extends MetadataType {
71
58
  }
72
59
  /**
73
60
  * manages post retrieve steps
74
- * @param {DataExtensionFieldItem} metadata a single item
61
+ *
62
+ * @param {TYPE.DataExtensionFieldItem} metadata a single item
75
63
  * @param {boolean} forDataExtension when used by DataExtension class we remove more fields
76
- * @returns {DataExtensionFieldItem} metadata
64
+ * @returns {TYPE.DataExtensionFieldItem} metadata
77
65
  */
78
66
  static postRetrieveTasks(metadata, forDataExtension) {
79
67
  return this._parseMetadata(metadata, forDataExtension);
@@ -81,10 +69,11 @@ class DataExtensionField extends MetadataType {
81
69
 
82
70
  /**
83
71
  * parses retrieved Metadata before saving
72
+ *
84
73
  * @private
85
- * @param {DataExtensionFieldItem} metadata a single record
74
+ * @param {TYPE.DataExtensionFieldItem} metadata a single record
86
75
  * @param {boolean} forDataExtension when used by DataExtension class we remove more fields
87
- * @returns {DataExtensionFieldItem} parsed metadata definition
76
+ * @returns {TYPE.DataExtensionFieldItem} parsed metadata definition
88
77
  */
89
78
  static _parseMetadata(metadata, forDataExtension) {
90
79
  if (forDataExtension) {
@@ -106,9 +95,9 @@ class DataExtensionField extends MetadataType {
106
95
  * Mofifies passed deployColumns for update by mapping ObjectID to their target column's values.
107
96
  * Removes FieldType field if its the same in deploy and target column, because it results in an error even if its of the same type
108
97
  *
109
- * @param {DataExtensionFieldItem[]} deployColumns Columns of data extension that will be deployed
98
+ * @param {TYPE.DataExtensionFieldItem[]} deployColumns Columns of data extension that will be deployed
110
99
  * @param {string} deKey external/customer key of Data Extension
111
- * @returns {Object<string,DataExtensionFieldItem>} existing fields by their original name to allow re-adding FieldType after update
100
+ * @returns {Object.<string, TYPE.DataExtensionFieldItem>} existing fields by their original name to allow re-adding FieldType after update
112
101
  */
113
102
  static async prepareDeployColumnsOnUpdate(deployColumns, deKey) {
114
103
  // retrieve existing fields to enable updating them
@@ -126,12 +115,12 @@ class DataExtensionField extends MetadataType {
126
115
  const fieldsObj = response.metadata;
127
116
 
128
117
  // ensure fields can be updated properly by their adding ObjectId based on Name-matching
129
- /** @type {Object<string,DataExtensionFieldItem>} */
118
+ /** @type {Object.<string, TYPE.DataExtensionFieldItem>} */
130
119
  const existingFieldByName = {};
131
120
 
132
- Object.keys(fieldsObj).forEach((key) => {
121
+ for (const key of Object.keys(fieldsObj)) {
133
122
  existingFieldByName[fieldsObj[key].Name] = fieldsObj[key];
134
- });
123
+ }
135
124
  for (let i = deployColumns.length - 1; i >= 0; i--) {
136
125
  const item = deployColumns[i];
137
126
  const itemOld = existingFieldByName[item.Name];
@@ -141,7 +130,7 @@ class DataExtensionField extends MetadataType {
141
130
  // Updating to a new FieldType will result in an error; warn & afterwards remove it
142
131
  if (itemOld.FieldType !== item.FieldType) {
143
132
  Util.logger.warn(
144
- `- The Field Type of an existing field cannot be changed. Keeping the original value for [${deKey}].[${item.Name}]: '${itemOld.FieldType}'`
133
+ ` - The Field Type of an existing field cannot be changed. Keeping the original value for [${deKey}].[${item.Name}]: '${itemOld.FieldType}'`
145
134
  );
146
135
  item.FieldType = itemOld.FieldType;
147
136
  }
@@ -153,13 +142,13 @@ class DataExtensionField extends MetadataType {
153
142
 
154
143
  if (itemOld.MaxLength > item.MaxLength) {
155
144
  Util.logger.warn(
156
- `- The length of an existing field cannot be decreased. Keeping the original value for [${deKey}].[${item.Name}]: '${itemOld.MaxLength}'`
145
+ ` - The length of an existing field cannot be decreased. Keeping the original value for [${deKey}].[${item.Name}]: '${itemOld.MaxLength}'`
157
146
  );
158
147
  item.MaxLength = itemOld.MaxLength;
159
148
  }
160
149
  if (Util.isFalse(itemOld.IsRequired) && Util.isTrue(item.IsRequired)) {
161
150
  Util.logger.warn(
162
- `- A field cannot be changed to be required on update after it was created to allow nulls: [${deKey}].[${item.Name}]`
151
+ ` - A field cannot be changed to be required on update after it was created to allow nulls: [${deKey}].[${item.Name}]`
163
152
  );
164
153
  item.IsRequired = itemOld.IsRequired;
165
154
  }
@@ -169,17 +158,17 @@ class DataExtensionField extends MetadataType {
169
158
  item.Name = item.Name_new;
170
159
  delete item.Name_new;
171
160
  Util.logger.warn(
172
- `Found 'Name_new' value '${item.Name_new}' for ${deKey}.${item.Name} - trying to rename.`
161
+ ` - Found 'Name_new' value '${item.Name_new}' for ${deKey}.${item.Name} - trying to rename.`
173
162
  );
174
163
  }
175
164
 
176
165
  // check if any changes were found
177
166
  let changeFound = false;
178
- Object.keys(item).forEach((key) => {
167
+ for (const key of Object.keys(item)) {
179
168
  if (item[key] !== itemOld[key]) {
180
169
  changeFound = true;
181
170
  }
182
- });
171
+ }
183
172
  if (!changeFound) {
184
173
  deployColumns.splice(i, 1);
185
174
  Util.logger.verbose(`no change - removed field [${deKey}].[${item.Name}]`);
@@ -192,13 +181,13 @@ class DataExtensionField extends MetadataType {
192
181
  // field is getting added ---
193
182
  if (Util.isTrue(item.IsRequired) && item.DefaultValue === '') {
194
183
  Util.logger.warn(
195
- `- Adding new fields to an existing table requires that these fields are either not-required (nullable) or have a default value set. Changing [${deKey}].[${item.Name}] to be not-required`
184
+ ` - Adding new fields to an existing table requires that these fields are either not-required (nullable) or have a default value set. Changing [${deKey}].[${item.Name}] to be not-required`
196
185
  );
197
- item.IsRequired = 'false';
186
+ item.IsRequired = false;
198
187
  }
199
188
  if (item.Name_new) {
200
189
  Util.logger.warn(
201
- `Found 'Name_new' value '${item.Name_new}' for ${deKey}.${item.Name} but could not find a corresponding DE field on the server - adding new field instead of updating.`
190
+ ` - Found 'Name_new' value '${item.Name_new}' for ${deKey}.${item.Name} but could not find a corresponding DE field on the server - adding new field instead of updating.`
202
191
  );
203
192
  delete item.Name_new;
204
193
  }
@@ -219,16 +208,104 @@ class DataExtensionField extends MetadataType {
219
208
  }
220
209
  }
221
210
  Util.logger.debug(
222
- `${deployColumns.length} Fields added/updated for [${deKey}]: ` +
223
- deployColumns.map((item) => item.Name).join(', ')
211
+ `${deployColumns.length} Fields added/updated for [${deKey}]${
212
+ deployColumns.length ? ': ' : ''
213
+ }` + deployColumns.map((item) => item.Name).join(', ')
214
+ );
215
+ return existingFieldByName;
216
+ }
217
+
218
+ /**
219
+ * Delete a metadata item from the specified business unit
220
+ *
221
+ * @param {TYPE.BuObject} buObject references credentials
222
+ * @param {string} customerKey Identifier of data extension
223
+ * @returns {Promise.<boolean>} deletion success status
224
+ */
225
+ static deleteByKey(buObject, customerKey) {
226
+ return this.deleteByKeySOAP(buObject, customerKey, false);
227
+ }
228
+
229
+ /**
230
+ * Delete a data extension from the specified business unit
231
+ *
232
+ * @param {TYPE.BuObject} buObject references credentials
233
+ * @param {string} customerKey Identifier of metadata
234
+ * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method
235
+ * @returns {boolean} deletion success flag
236
+ */
237
+ static async deleteByKeySOAP(buObject, customerKey, handleOutside) {
238
+ const [deKey, fieldKey] = customerKey.split('.');
239
+ customerKey = `[${deKey}].[${fieldKey}]`;
240
+
241
+ // get the object id
242
+ const response = await this.retrieveForCache(
243
+ {
244
+ filter: {
245
+ leftOperand: 'CustomerKey',
246
+ operator: 'equals',
247
+ rightOperand: customerKey,
248
+ },
249
+ },
250
+ ['Name', 'ObjectID']
251
+ );
252
+ const fieldObjectID = response.metadata[customerKey].ObjectID;
253
+ if (!fieldObjectID) {
254
+ Util.logger.error(`Could not find ${customerKey} on your BU`);
255
+ return false;
256
+ }
257
+
258
+ // normal code
259
+ const keyObj = {
260
+ CustomerKey: deKey,
261
+ Fields: {
262
+ Field: {
263
+ ObjectID: fieldObjectID,
264
+ },
265
+ },
266
+ };
267
+ try {
268
+ this.client.soap.delete(
269
+ 'DataExtension', // yes, not DataExtensionField
270
+ keyObj,
271
+ null
272
+ );
273
+
274
+ if (!handleOutside) {
275
+ Util.logger.info(`- deleted ${this.definition.type}: ${customerKey}`);
276
+ }
277
+ this.postDeleteTasks(buObject, customerKey);
278
+ return true;
279
+ } catch (ex) {
280
+ if (!handleOutside) {
281
+ const errorMsg = ex.results?.length
282
+ ? `${ex.results[0].StatusMessage} (Code ${ex.results[0].ErrorCode})`
283
+ : ex.message;
284
+ Util.logger.error(
285
+ `- error deleting ${this.definition.type} '${customerKey}': ${errorMsg}`
286
+ );
287
+ } else {
288
+ throw ex;
289
+ }
290
+
291
+ return false;
292
+ }
293
+ }
294
+ /**
295
+ * clean up after deleting a metadata item
296
+ *
297
+ * @param {string} customerKey Identifier of metadata item
298
+ * @returns {void}
299
+ */
300
+ static async postDeleteTasks(customerKey) {
301
+ // TODO actually clean up local dataextension json
302
+ Util.logger.warn(
303
+ ` - The dataExtension for ${customerKey} wasn't updated locally yet after removing this field.`
224
304
  );
225
- return deployColumns.length ? existingFieldByName : null;
226
305
  }
227
306
  }
228
307
 
229
308
  // Assign definition to static attributes
230
309
  DataExtensionField.definition = require('../MetadataTypeDefinitions').dataExtensionField;
231
- DataExtensionField.cache = {};
232
- DataExtensionField.client = undefined;
233
310
 
234
311
  module.exports = DataExtensionField;
@@ -1,19 +1,37 @@
1
1
  'use strict';
2
2
 
3
+ const TYPE = require('../../types/mcdev.d');
3
4
  const MetadataType = require('./MetadataType');
4
5
 
5
6
  /**
6
7
  * DataExtensionTemplate MetadataType
8
+ *
7
9
  * @augments MetadataType
8
10
  */
9
11
  class DataExtensionTemplate extends MetadataType {
10
12
  /**
11
13
  * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata
12
- * @param {String} retrieveDir Directory where retrieved metadata directory will be saved
13
- * @returns {Promise<Object>} Promise of metadata
14
+ *
15
+ * @param {string} retrieveDir Directory where retrieved metadata directory will be saved
16
+ * @param {void} [_] unused parameter
17
+ * @param {void} [__] unused parameter
18
+ * @param {void} [___] unused parameter
19
+ * @param {string} [key] customer key of single item to retrieve
20
+ * @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
14
21
  */
15
- static retrieve(retrieveDir) {
16
- return super.retrieveSOAPgeneric(retrieveDir);
22
+ static retrieve(retrieveDir, _, __, ___, key) {
23
+ /** @type {TYPE.SoapRequestParams} */
24
+ let requestParams = null;
25
+ if (key) {
26
+ requestParams = {
27
+ filter: {
28
+ leftOperand: 'CustomerKey',
29
+ operator: 'equals',
30
+ rightOperand: key,
31
+ },
32
+ };
33
+ }
34
+ return super.retrieveSOAP(retrieveDir, null, requestParams);
17
35
  }
18
36
  }
19
37
 
@@ -1,90 +1,97 @@
1
1
  'use strict';
2
2
 
3
+ const TYPE = require('../../types/mcdev.d');
3
4
  const MetadataType = require('./MetadataType');
4
5
  const Util = require('../util/util');
5
6
  const File = require('../util/file');
7
+ const cache = require('../util/cache');
6
8
 
7
9
  /**
8
10
  * DataExtract MetadataType
11
+ *
9
12
  * @augments MetadataType
10
13
  */
11
14
  class DataExtract extends MetadataType {
12
15
  /**
13
16
  * Retrieves Metadata of Data Extract Activity.
14
17
  * Endpoint /automation/v1/dataextracts/ returns all Data Extracts
15
- * @param {String} retrieveDir Directory where retrieved metadata directory will be saved
16
- * @returns {Promise<Object>} Promise of metadata
18
+ *
19
+ * @param {string} retrieveDir Directory where retrieved metadata directory will be saved
20
+ * @param {void} [_] unused parameter
21
+ * @param {void} [__] unused parameter
22
+ * @param {void} [___] unused parameter
23
+ * @param {string} [key] customer key of single item to retrieve
24
+ * @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
17
25
  */
18
- static async retrieve(retrieveDir) {
19
- return super.retrieveREST(retrieveDir, '/automation/v1/dataextracts/', null);
26
+ static async retrieve(retrieveDir, _, __, ___, key) {
27
+ return super.retrieveREST(retrieveDir, '/automation/v1/dataextracts/', null, null, key);
20
28
  }
21
29
  /**
22
30
  * Retrieves Metadata of Data Extract Activity for caching
23
- * @returns {Promise<Object>} Promise of metadata
31
+ *
32
+ * @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
24
33
  */
25
34
  static async retrieveForCache() {
26
- return super.retrieveREST(null, '/automation/v1/dataextracts/', null);
35
+ return super.retrieveREST(null, '/automation/v1/dataextracts/');
27
36
  }
28
37
 
29
38
  /**
30
39
  * Retrieve a specific dataExtract Definition by Name
31
- * @param {String} templateDir Directory where retrieved metadata directory will be saved
32
- * @param {String} name name of the metadata file
33
- * @param {Object} templateVariables variables to be replaced in the metadata
34
- * @returns {Promise<Object>} Promise of metadata
40
+ *
41
+ * @param {string} templateDir Directory where retrieved metadata directory will be saved
42
+ * @param {string} name name of the metadata file
43
+ * @param {TYPE.TemplateMap} templateVariables variables to be replaced in the metadata
44
+ * @returns {Promise.<TYPE.MetadataTypeItemObj>} Promise of metadata
35
45
  */
36
46
  static async retrieveAsTemplate(templateDir, name, templateVariables) {
37
- const options = {
38
- uri: '/automation/v1/dataextracts/?$filter=name%20eq%20' + name.split(' ').join('%20'),
39
- };
40
-
41
- const res = await this.client.RestClient.get(options);
42
- if (res.body && Array.isArray(res.body.items) && res.body.items.length) {
47
+ const res = await this.client.rest.get(
48
+ '/automation/v1/dataextracts/?$filter=name%20eq%20' + encodeURIComponent(name)
49
+ );
50
+ if (Array.isArray(res.items) && res.items.length) {
43
51
  // eq-operator returns a similar, not exact match and hence might return more than 1 entry
44
- const [metadata] = res.body.items.filter((item) => item.name === name);
52
+ const metadata = res.items.find((item) => item.name === name);
45
53
  if (!metadata) {
46
54
  Util.logger.error(`No ${this.definition.typeName} found with name "${name}"`);
47
55
  return;
48
56
  }
49
57
 
50
58
  // get full definition
51
- const extended = await this.client.RestClient.get({
52
- uri: '/automation/v1/dataextracts/' + metadata.id,
53
- });
54
- const originalKey = extended.body[this.definition.keyField];
59
+ const extended = await this.client.rest.get(
60
+ '/automation/v1/dataextracts/' + metadata[this.definition.idField]
61
+ );
62
+ const originalKey = extended[this.definition.keyField];
55
63
  const val = JSON.parse(
56
64
  Util.replaceByObject(
57
- JSON.stringify(this.parseMetadata(extended.body)),
65
+ JSON.stringify(this.parseMetadata(extended)),
58
66
  templateVariables
59
67
  )
60
68
  );
61
69
 
62
70
  // remove all fields listed in Definition for templating
63
71
  this.keepTemplateFields(val);
64
- File.writeJSONToFile(
72
+ await File.writeJSONToFile(
65
73
  [templateDir, this.definition.type].join('/'),
66
74
  originalKey + '.' + this.definition.type + '-meta',
67
75
  JSON.parse(Util.replaceByObject(JSON.stringify(val), templateVariables))
68
76
  );
69
- Util.logger.info(
70
- `Dataextracts.retrieveAsTemplate:: Written Metadata to filesystem (${name})`
71
- );
77
+ Util.logger.info(`- templated ${this.definition.type}: ${name}`);
72
78
  return { metadata: val, type: this.definition.type };
73
- } else if (res.body && res.body.items) {
79
+ } else if (res?.items) {
74
80
  Util.logger.error(`No ${this.definition.typeName} found with name "${name}"`);
75
81
  } else {
76
82
  throw new Error(
77
83
  `Encountered unknown error when retrieveing ${
78
84
  this.definition.typeName
79
- } "${name}": ${JSON.stringify(res.body)}`
85
+ } "${name}": ${JSON.stringify(res)}`
80
86
  );
81
87
  }
82
88
  }
83
89
 
84
90
  /**
85
91
  * manages post retrieve steps
86
- * @param {Object} fileTransfer a single fileTransfer
87
- * @returns {Object[]} metadata
92
+ *
93
+ * @param {TYPE.MetadataTypeItem} fileTransfer a single fileTransfer
94
+ * @returns {TYPE.MetadataTypeItem} metadata
88
95
  */
89
96
  static postRetrieveTasks(fileTransfer) {
90
97
  return this.parseMetadata(fileTransfer);
@@ -92,7 +99,8 @@ class DataExtract extends MetadataType {
92
99
 
93
100
  /**
94
101
  * Creates a single Data Extract
95
- * @param {Object} dataExtract a single Data Extract
102
+ *
103
+ * @param {TYPE.MetadataTypeItem} dataExtract a single Data Extract
96
104
  * @returns {Promise} Promise
97
105
  */
98
106
  static create(dataExtract) {
@@ -101,7 +109,8 @@ class DataExtract extends MetadataType {
101
109
 
102
110
  /**
103
111
  * Updates a single Data Extract
104
- * @param {Object} dataExtract a single Data Extract
112
+ *
113
+ * @param {TYPE.MetadataTypeItem} dataExtract a single Data Extract
105
114
  * @returns {Promise} Promise
106
115
  */
107
116
  static update(dataExtract) {
@@ -113,12 +122,12 @@ class DataExtract extends MetadataType {
113
122
 
114
123
  /**
115
124
  * prepares a dataExtract for deployment
116
- * @param {Object} metadata a single dataExtract activity definition
117
- * @returns {Object} metadata object
125
+ *
126
+ * @param {TYPE.MetadataTypeItem} metadata a single dataExtract activity definition
127
+ * @returns {TYPE.MetadataTypeItem} metadata object
118
128
  */
119
129
  static preDeployTasks(metadata) {
120
- metadata.dataExtractTypeId = Util.getFromCache(
121
- this.cache,
130
+ metadata.dataExtractTypeId = cache.searchForField(
122
131
  'dataExtractType',
123
132
  metadata.r__dataExtractType_name,
124
133
  'name',
@@ -129,25 +138,29 @@ class DataExtract extends MetadataType {
129
138
  }
130
139
  /**
131
140
  * parses retrieved Metadata before saving
132
- * @param {Object} metadata a single dataExtract activity definition
133
- * @returns {Array} Array with one metadata object and one sql string
141
+ *
142
+ * @param {TYPE.MetadataTypeItem} metadata a single dataExtract activity definition
143
+ * @returns {TYPE.MetadataTypeItem} Array with one metadata object and one sql string
134
144
  */
135
145
  static parseMetadata(metadata) {
136
- metadata.r__dataExtractType_name = Util.getFromCache(
137
- this.cache,
138
- 'dataExtractType',
139
- metadata.dataExtractTypeId,
140
- 'extractId',
141
- 'name'
142
- );
143
- delete metadata.dataExtractTypeId;
146
+ try {
147
+ metadata.r__dataExtractType_name = cache.searchForField(
148
+ 'dataExtractType',
149
+ metadata.dataExtractTypeId,
150
+ 'extractId',
151
+ 'name'
152
+ );
153
+ delete metadata.dataExtractTypeId;
154
+ } catch (ex) {
155
+ Util.logger.warn(
156
+ ` - ${this.definition.type} ${metadata[this.definition.keyField]}: ${ex.message}`
157
+ );
158
+ }
144
159
  return JSON.parse(JSON.stringify(metadata));
145
160
  }
146
161
  }
147
162
 
148
163
  // Assign definition to static attributes
149
164
  DataExtract.definition = require('../MetadataTypeDefinitions').dataExtract;
150
- DataExtract.cache = {};
151
- DataExtract.client = undefined;
152
165
 
153
166
  module.exports = DataExtract;
@@ -1,34 +1,40 @@
1
1
  'use strict';
2
2
 
3
+ const TYPE = require('../../types/mcdev.d');
3
4
  const MetadataType = require('./MetadataType');
4
5
 
5
6
  /**
6
7
  * DataExtractType MetadataType
7
8
  * Only for Caching No retrieve/upsert is required
8
9
  * as this is a configuration in the EID
10
+ *
9
11
  * @augments MetadataType
10
12
  */
11
13
  class DataExtractType extends MetadataType {
12
14
  /**
13
15
  * Retrieves Metadata of Data Extract Type.
14
- * @param {String} retrieveDir Directory where retrieved metadata directory will be saved
15
- * @returns {Promise<Object>} Promise of metadata
16
+ *
17
+ * @param {string} retrieveDir Directory where retrieved metadata directory will be saved
18
+ * @param {void} [_] unused parameter
19
+ * @param {void} [__] unused parameter
20
+ * @param {void} [___] unused parameter
21
+ * @param {string} [key] customer key of single item to retrieve
22
+ * @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
16
23
  */
17
- static retrieve(retrieveDir) {
18
- return super.retrieveREST(retrieveDir, '/automation/v1/dataextracttypes/', null);
24
+ static retrieve(retrieveDir, _, __, ___, key) {
25
+ return super.retrieveREST(retrieveDir, '/automation/v1/dataextracttypes/', null, null, key);
19
26
  }
20
27
  /**
21
28
  * Retrieves Metadata of Data Extract Type for caching.
22
- * @returns {Promise<Object>} Promise of metadata
29
+ *
30
+ * @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
23
31
  */
24
32
  static retrieveForCache() {
25
- return super.retrieveREST(null, '/automation/v1/dataextracttypes/', null);
33
+ return super.retrieveREST(null, '/automation/v1/dataextracttypes/');
26
34
  }
27
35
  }
28
36
 
29
37
  // Assign definition to static attributes
30
38
  DataExtractType.definition = require('../MetadataTypeDefinitions').dataExtractType;
31
- DataExtractType.cache = {};
32
- DataExtractType.client = undefined;
33
39
 
34
40
  module.exports = DataExtractType;