mcdev 3.1.3 → 4.0.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.
- package/.eslintrc.json +67 -7
- package/.github/ISSUE_TEMPLATE/bug.yml +2 -1
- package/.github/PULL_REQUEST_TEMPLATE.md +5 -3
- package/.github/dependabot.yml +14 -0
- package/.github/workflows/code-analysis.yml +57 -0
- package/.husky/commit-msg +10 -0
- package/.husky/post-checkout +5 -0
- package/.husky/pre-commit +2 -1
- package/.prettierrc +8 -0
- package/.vscode/settings.json +1 -1
- package/LICENSE +2 -2
- package/README.md +134 -45
- package/boilerplate/config.json +5 -11
- package/boilerplate/files/.prettierrc +8 -0
- package/boilerplate/files/.vscode/extensions.json +0 -1
- package/boilerplate/files/.vscode/settings.json +30 -2
- package/boilerplate/files/README.md +2 -2
- package/boilerplate/forcedUpdates.json +10 -0
- package/boilerplate/npm-dependencies.json +5 -5
- package/docs/dist/documentation.md +2807 -1730
- package/jsconfig.json +1 -1
- package/lib/Builder.js +171 -74
- package/lib/Deployer.js +244 -96
- package/lib/MetadataTypeDefinitions.js +2 -0
- package/lib/MetadataTypeInfo.js +2 -0
- package/lib/Retriever.js +61 -84
- package/lib/cli.js +116 -11
- package/lib/index.js +241 -561
- package/lib/metadataTypes/AccountUser.js +117 -103
- package/lib/metadataTypes/Asset.js +705 -255
- package/lib/metadataTypes/AttributeGroup.js +23 -12
- package/lib/metadataTypes/Automation.js +489 -392
- package/lib/metadataTypes/Campaign.js +33 -93
- package/lib/metadataTypes/ContentArea.js +31 -11
- package/lib/metadataTypes/DataExtension.js +387 -372
- package/lib/metadataTypes/DataExtensionField.js +131 -54
- package/lib/metadataTypes/DataExtensionTemplate.js +22 -4
- package/lib/metadataTypes/DataExtract.js +61 -48
- package/lib/metadataTypes/DataExtractType.js +14 -8
- package/lib/metadataTypes/Discovery.js +21 -16
- package/lib/metadataTypes/Email.js +32 -12
- package/lib/metadataTypes/EmailSendDefinition.js +85 -80
- package/lib/metadataTypes/EventDefinition.js +61 -43
- package/lib/metadataTypes/FileTransfer.js +72 -52
- package/lib/metadataTypes/Filter.js +11 -4
- package/lib/metadataTypes/Folder.js +149 -117
- package/lib/metadataTypes/FtpLocation.js +14 -8
- package/lib/metadataTypes/ImportFile.js +61 -64
- package/lib/metadataTypes/Interaction.js +19 -4
- package/lib/metadataTypes/List.js +54 -13
- package/lib/metadataTypes/MetadataType.js +664 -454
- package/lib/metadataTypes/MobileCode.js +46 -0
- package/lib/metadataTypes/MobileKeyword.js +114 -0
- package/lib/metadataTypes/Query.js +206 -105
- package/lib/metadataTypes/Role.js +76 -61
- package/lib/metadataTypes/Script.js +147 -83
- package/lib/metadataTypes/SetDefinition.js +20 -8
- package/lib/metadataTypes/TriggeredSendDefinition.js +78 -58
- package/lib/metadataTypes/definitions/Asset.definition.js +21 -10
- package/lib/metadataTypes/definitions/AttributeGroup.definition.js +12 -0
- package/lib/metadataTypes/definitions/Automation.definition.js +10 -5
- package/lib/metadataTypes/definitions/Campaign.definition.js +44 -1
- package/lib/metadataTypes/definitions/DataExtension.definition.js +4 -0
- package/lib/metadataTypes/definitions/DataExtensionTemplate.definition.js +6 -0
- package/lib/metadataTypes/definitions/DataExtract.definition.js +18 -14
- package/lib/metadataTypes/definitions/Discovery.definition.js +12 -0
- package/lib/metadataTypes/definitions/EmailSendDefinition.definition.js +4 -0
- package/lib/metadataTypes/definitions/EventDefinition.definition.js +22 -0
- package/lib/metadataTypes/definitions/FileTransfer.definition.js +4 -0
- package/lib/metadataTypes/definitions/Filter.definition.js +4 -0
- package/lib/metadataTypes/definitions/Folder.definition.js +6 -0
- package/lib/metadataTypes/definitions/FtpLocation.definition.js +4 -0
- package/lib/metadataTypes/definitions/ImportFile.definition.js +10 -5
- package/lib/metadataTypes/definitions/Interaction.definition.js +4 -0
- package/lib/metadataTypes/definitions/MobileCode.definition.js +163 -0
- package/lib/metadataTypes/definitions/MobileKeyword.definition.js +253 -0
- package/lib/metadataTypes/definitions/Query.definition.js +4 -0
- package/lib/metadataTypes/definitions/Role.definition.js +5 -0
- package/lib/metadataTypes/definitions/Script.definition.js +4 -0
- package/lib/metadataTypes/definitions/SetDefinition.definition.js +28 -0
- package/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js +4 -0
- package/lib/retrieveChangelog.js +7 -6
- package/lib/util/auth.js +117 -0
- package/lib/util/businessUnit.js +55 -66
- package/lib/util/cache.js +194 -0
- package/lib/util/cli.js +90 -116
- package/lib/util/config.js +302 -0
- package/lib/util/devops.js +250 -50
- package/lib/util/file.js +141 -201
- package/lib/util/init.config.js +208 -75
- package/lib/util/init.git.js +45 -50
- package/lib/util/init.js +72 -59
- package/lib/util/init.npm.js +48 -39
- package/lib/util/util.js +280 -564
- package/package.json +45 -34
- package/test/dataExtension.test.js +152 -0
- package/test/mockRoot/.mcdev-auth.json +8 -0
- package/test/mockRoot/.mcdevrc.json +67 -0
- package/test/mockRoot/deploy/testInstance/testBU/dataExtension/childBU_dataextension_test.dataExtension-meta.json +39 -0
- package/test/mockRoot/deploy/testInstance/testBU/dataExtension/testDataExtension.dataExtension-meta.json +23 -0
- package/test/mockRoot/deploy/testInstance/testBU/query/testExistingQuery.query-meta.json +11 -0
- package/test/mockRoot/deploy/testInstance/testBU/query/testExistingQuery.query-meta.sql +4 -0
- package/test/mockRoot/deploy/testInstance/testBU/query/testQuery.query-meta.json +11 -0
- package/test/mockRoot/deploy/testInstance/testBU/query/testQuery.query-meta.sql +4 -0
- package/test/query.test.js +149 -0
- package/test/resourceFactory.js +142 -0
- package/test/resources/1111111/dataFolder/retrieve-response.xml +43 -0
- package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/patch-response.json +18 -0
- package/test/resources/9999999/automation/v1/queries/get-response.json +24 -0
- package/test/resources/9999999/automation/v1/queries/post-response.json +18 -0
- package/test/resources/9999999/dataExtension/build-expected.json +51 -0
- package/test/resources/9999999/dataExtension/create-expected.json +23 -0
- package/test/resources/9999999/dataExtension/create-response.xml +54 -0
- package/test/resources/9999999/dataExtension/retrieve-expected.json +51 -0
- package/test/resources/9999999/dataExtension/retrieve-response.xml +47 -0
- package/test/resources/9999999/dataExtension/template-expected.json +51 -0
- package/test/resources/9999999/dataExtension/update-expected.json +55 -0
- package/test/resources/9999999/dataExtension/update-response.xml +52 -0
- package/test/resources/9999999/dataExtensionField/retrieve-response.xml +93 -0
- package/test/resources/9999999/dataExtensionTemplate/retrieve-response.xml +303 -0
- package/test/resources/9999999/dataFolder/retrieve-response.xml +65 -0
- package/test/resources/9999999/query/build-expected.json +8 -0
- package/test/resources/9999999/query/get-expected.json +11 -0
- package/test/resources/9999999/query/patch-expected.json +11 -0
- package/test/resources/9999999/query/post-expected.json +11 -0
- package/test/resources/9999999/query/template-expected.json +8 -0
- package/test/resources/auth.json +32 -0
- package/test/resources/rest404-response.json +5 -0
- package/test/resources/retrieve-response.xml +21 -0
- package/test/utils.js +107 -0
- package/types/mcdev.d.js +301 -0
- package/CHANGELOG.md +0 -126
- package/PULL_REQUEST_TEMPLATE.md +0 -19
- package/test/util/file.js +0 -51
|
@@ -1,55 +1,41 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
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 {
|
|
35
|
-
* @returns {Promise
|
|
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.
|
|
22
|
+
return super.retrieveSOAP(retrieveDir, buObject, null, additionalFields);
|
|
39
23
|
}
|
|
40
24
|
/**
|
|
41
25
|
* Retrieves all records for caching
|
|
42
|
-
*
|
|
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
|
|
29
|
+
* @returns {Promise.<{metadata: TYPE.DataExtensionFieldMap, type: string}>} Promise of items
|
|
45
30
|
*/
|
|
46
|
-
static async retrieveForCache(
|
|
47
|
-
return super.
|
|
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
|
-
*
|
|
52
|
-
* @
|
|
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
|
-
*
|
|
66
|
-
* @param {DataExtensionFieldItem}
|
|
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
|
-
*
|
|
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
|
|
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
|
|
118
|
+
/** @type {Object.<string, TYPE.DataExtensionFieldItem>} */
|
|
130
119
|
const existingFieldByName = {};
|
|
131
120
|
|
|
132
|
-
Object.keys(fieldsObj)
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
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 =
|
|
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.
|
|
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
|
-
*
|
|
13
|
-
* @
|
|
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
|
-
|
|
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
|
-
*
|
|
16
|
-
* @
|
|
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
|
-
*
|
|
31
|
+
*
|
|
32
|
+
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
|
|
24
33
|
*/
|
|
25
34
|
static async retrieveForCache() {
|
|
26
|
-
return super.retrieveREST(null, '/automation/v1/dataextracts/'
|
|
35
|
+
return super.retrieveREST(null, '/automation/v1/dataextracts/');
|
|
27
36
|
}
|
|
28
37
|
|
|
29
38
|
/**
|
|
30
39
|
* Retrieve a specific dataExtract Definition by Name
|
|
31
|
-
*
|
|
32
|
-
* @param {
|
|
33
|
-
* @param {
|
|
34
|
-
* @
|
|
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
|
|
38
|
-
|
|
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
|
|
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.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const originalKey = extended
|
|
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
|
|
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
|
|
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
|
|
85
|
+
} "${name}": ${JSON.stringify(res)}`
|
|
80
86
|
);
|
|
81
87
|
}
|
|
82
88
|
}
|
|
83
89
|
|
|
84
90
|
/**
|
|
85
91
|
* manages post retrieve steps
|
|
86
|
-
*
|
|
87
|
-
* @
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
117
|
-
* @
|
|
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 =
|
|
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
|
-
*
|
|
133
|
-
* @
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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
|
-
*
|
|
15
|
-
* @
|
|
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
|
-
*
|
|
29
|
+
*
|
|
30
|
+
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
|
|
23
31
|
*/
|
|
24
32
|
static retrieveForCache() {
|
|
25
|
-
return super.retrieveREST(null, '/automation/v1/dataextracttypes/'
|
|
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;
|