mcdev 8.3.1 → 9.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.
- package/.github/ISSUE_TEMPLATE/bug.yml +2 -0
- package/.github/workflows/close_issues_on_merge.yml +4 -0
- package/.github/workflows/code-test.yml +2 -2
- package/.github/workflows/coverage-base-update.yml +2 -2
- package/.github/workflows/coverage-develop-branch.yml +1 -1
- package/.github/workflows/coverage-main-branch.yml +1 -1
- package/.github/workflows/coverage.yml +2 -2
- package/.prettierrc +1 -1
- package/@types/lib/index.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Asset.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Automation.d.ts.map +1 -1
- package/@types/lib/metadataTypes/DataExtension.d.ts.map +1 -1
- package/@types/lib/metadataTypes/DataFilter.d.ts +1 -0
- package/@types/lib/metadataTypes/DataFilter.d.ts.map +1 -1
- package/@types/lib/metadataTypes/DataFilterHidden.d.ts +1 -0
- package/@types/lib/metadataTypes/DataFilterHidden.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Event.d.ts.map +1 -1
- package/@types/lib/metadataTypes/FileLocation.d.ts +74 -0
- package/@types/lib/metadataTypes/FileLocation.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Folder.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Journey.d.ts +6 -0
- package/@types/lib/metadataTypes/Journey.d.ts.map +1 -1
- package/@types/lib/metadataTypes/List.d.ts +1 -1
- package/@types/lib/metadataTypes/MetadataType.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Script.d.ts +14 -0
- package/@types/lib/metadataTypes/Script.d.ts.map +1 -1
- package/@types/lib/metadataTypes/definitions/DataFilter.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/DataFilterHidden.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/FileLocation.definition.d.ts +62 -4
- package/@types/lib/metadataTypes/definitions/Journey.definition.d.ts +6 -0
- package/@types/lib/metadataTypes/definitions/Script.definition.d.ts +10 -0
- package/@types/lib/util/auth.d.ts.map +1 -1
- package/@types/lib/util/cli.d.ts.map +1 -1
- package/@types/lib/util/file.d.ts.map +1 -1
- package/@types/lib/util/init.config.d.ts.map +1 -1
- package/@types/lib/util/init.d.ts +1 -1
- package/@types/lib/util/init.d.ts.map +1 -1
- package/@types/lib/util/init.git.d.ts.map +1 -1
- package/lib/Deployer.js +3 -3
- package/lib/cli.js +6 -0
- package/lib/index.js +15 -14
- package/lib/metadataTypes/Asset.js +7 -8
- package/lib/metadataTypes/Automation.js +8 -10
- package/lib/metadataTypes/DataExtension.js +4 -3
- package/lib/metadataTypes/DataExtensionField.js +3 -3
- package/lib/metadataTypes/DataFilter.js +36 -22
- package/lib/metadataTypes/Event.js +8 -7
- package/lib/metadataTypes/FileLocation.js +204 -4
- package/lib/metadataTypes/Folder.js +8 -7
- package/lib/metadataTypes/Journey.js +74 -47
- package/lib/metadataTypes/List.js +1 -1
- package/lib/metadataTypes/MetadataType.js +17 -21
- package/lib/metadataTypes/Script.js +16 -0
- package/lib/metadataTypes/User.js +2 -2
- package/lib/metadataTypes/definitions/DataFilter.definition.js +1 -0
- package/lib/metadataTypes/definitions/DataFilterHidden.definition.js +1 -0
- package/lib/metadataTypes/definitions/FileLocation.definition.js +52 -7
- package/lib/metadataTypes/definitions/Journey.definition.js +6 -0
- package/lib/metadataTypes/definitions/Script.definition.js +6 -0
- package/lib/util/auth.js +20 -24
- package/lib/util/businessUnit.js +1 -1
- package/lib/util/cli.js +2 -1
- package/lib/util/file.js +2 -1
- package/lib/util/init.config.js +3 -1
- package/lib/util/init.git.js +2 -1
- package/lib/util/init.js +2 -1
- package/lib/util/util.js +3 -3
- package/package.json +21 -21
- package/test/general.test.js +11 -11
- package/test/mockRoot/.mcdevrc.json +1 -1
- package/test/mockRoot/deploy/testInstance/testBU/fileLocation/ExactTarget Enhanced FTP.fileLocation-meta.json +5 -0
- package/test/mockRoot/deploy/testInstance/testBU/fileLocation/testExisting_fileLocation_aws.fileLocation-meta.json +14 -0
- package/test/mockRoot/deploy/testInstance/testBU/fileLocation/testExisting_fileLocation_exsftp.fileLocation-meta.json +12 -0
- package/test/resourceFactory.js +10 -3
- package/test/resources/9999999/automation/v1/ftplocations/get-response.json +26 -1
- package/test/resources/9999999/automation/v1/scripts/39f6a488-20eb-4ba0-b0b9-023725b574e4/get-response.json +10 -0
- package/test/resources/9999999/automation/v1/scripts/39f6a488-20eb-4ba0-b0b9-023725b574e4/patch-response.json +2 -2
- package/test/resources/9999999/data/v1/filetransferlocation/Salesforce%20Objects%20%26%20Reports/get-response.json +4 -0
- package/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_aws/patch-response.json +18 -0
- package/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_azure/delete-response.json +4 -0
- package/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_azure/get-response.json +18 -0
- package/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_exsftp/patch-response.json +16 -0
- package/test/resources/9999999/data/v1/filetransferlocations/get-response.json +59 -0
- package/test/resources/9999999/fileLocation/build-expected.json +14 -0
- package/test/resources/9999999/fileLocation/get-aws-expected.json +14 -0
- package/test/resources/9999999/fileLocation/get-azure-expected.json +14 -0
- package/test/resources/9999999/fileLocation/get-eftp-expected.json +5 -0
- package/test/resources/9999999/fileLocation/get-exsftp-expected.json +12 -0
- package/test/resources/9999999/fileLocation/get-gcp-expected.json +10 -0
- package/test/resources/9999999/fileLocation/get-sor-expected.json +5 -0
- package/test/resources/9999999/fileLocation/patch-aws-expected.json +14 -0
- package/test/resources/9999999/fileLocation/patch-exsftp-expected.json +12 -0
- package/test/resources/9999999/fileLocation/template-expected.json +14 -0
- package/test/resources/9999999/interaction/v1/interactions/get-response-status=Published.json +40 -0
- package/test/type.automation.test.js +14 -14
- package/test/type.dataFilter.test.js +10 -2
- package/test/type.fileLocation.test.js +279 -0
- package/test/type.fileTransfer.test.js +4 -4
- package/test/type.filter.test.js +9 -2
- package/test/type.importFile.test.js +5 -5
- package/test/type.journey.test.js +26 -0
- package/test/type.query.test.js +2 -2
- package/test/type.script.test.js +1 -1
- package/tsconfig.json +1 -1
- package/tsconfig.npmScripts.json +1 -1
- package/tsconfig.precommit.json +1 -1
|
@@ -110,8 +110,10 @@ class DataFilter extends MetadataType {
|
|
|
110
110
|
*/
|
|
111
111
|
static async _getFilterFolderIds(recached = false) {
|
|
112
112
|
const fromCache =
|
|
113
|
-
this.cache.folderFilter || cache.getCache().folder
|
|
114
|
-
? Object.values(
|
|
113
|
+
this.cache[this.buObject.mid]?.folderFilter || cache.getCache().folder
|
|
114
|
+
? Object.values(
|
|
115
|
+
this.cache[this.buObject.mid]?.folderFilter || cache.getCache().folder
|
|
116
|
+
)
|
|
115
117
|
.filter((item) => item.ContentType === 'filterdefinition')
|
|
116
118
|
.filter(
|
|
117
119
|
(item) =>
|
|
@@ -135,7 +137,10 @@ class DataFilter extends MetadataType {
|
|
|
135
137
|
Folder.client = this.client;
|
|
136
138
|
Folder.buObject = this.buObject;
|
|
137
139
|
Folder.properties = this.properties;
|
|
138
|
-
this.cache.
|
|
140
|
+
this.cache[this.buObject.mid] ||= {};
|
|
141
|
+
this.cache[this.buObject.mid].folderFilter = (
|
|
142
|
+
await Folder.retrieveForCache(null, subTypeArr)
|
|
143
|
+
).metadata;
|
|
139
144
|
return this._getFilterFolderIds(true);
|
|
140
145
|
}
|
|
141
146
|
/**
|
|
@@ -145,9 +150,9 @@ class DataFilter extends MetadataType {
|
|
|
145
150
|
*/
|
|
146
151
|
static async _getMeasureFolderIds() {
|
|
147
152
|
const fromCache =
|
|
148
|
-
this.cache
|
|
153
|
+
this.cache[this.buObject.mid]?.folderMeasure || cache.getCache().folder
|
|
149
154
|
? Object.values(
|
|
150
|
-
this.cache
|
|
155
|
+
this.cache[this.buObject.mid]?.folderMeasure || cache.getCache().folder
|
|
151
156
|
)
|
|
152
157
|
.filter((item) => item.ContentType === 'measure')
|
|
153
158
|
.map((item) => item.ID)
|
|
@@ -163,8 +168,9 @@ class DataFilter extends MetadataType {
|
|
|
163
168
|
Folder.client = this.client;
|
|
164
169
|
Folder.buObject = this.buObject;
|
|
165
170
|
Folder.properties = this.properties;
|
|
166
|
-
this.cache.
|
|
167
|
-
this.cache
|
|
171
|
+
this.cache[this.buObject.mid] ||= {};
|
|
172
|
+
this.cache[this.buObject.mid].folderMeasure ||= {};
|
|
173
|
+
this.cache[this.buObject.mid].folderMeasure = (
|
|
168
174
|
await Folder.retrieveForCache(null, subTypeArr)
|
|
169
175
|
).metadata;
|
|
170
176
|
return this._getMeasureFolderIds();
|
|
@@ -205,8 +211,8 @@ class DataFilter extends MetadataType {
|
|
|
205
211
|
.map((item) => item.r__source_dataExtension_key)
|
|
206
212
|
.filter(
|
|
207
213
|
(deKey) =>
|
|
208
|
-
!this.cache.dataExtensionField ||
|
|
209
|
-
!this.cache.dataExtensionField[deKey]
|
|
214
|
+
!this.cache[this.buObject.mid]?.dataExtensionField ||
|
|
215
|
+
!this.cache[this.buObject.mid]?.dataExtensionField[deKey]
|
|
210
216
|
)
|
|
211
217
|
.filter(Boolean);
|
|
212
218
|
if (deKeys.length) {
|
|
@@ -246,7 +252,8 @@ class DataFilter extends MetadataType {
|
|
|
246
252
|
* @param {DataExtensionFieldMap} deFieldCache -
|
|
247
253
|
*/
|
|
248
254
|
static saveDataExtensionFieldCacheToMap(deFieldCache) {
|
|
249
|
-
this.cache.
|
|
255
|
+
this.cache[this.buObject.mid] ||= {};
|
|
256
|
+
this.cache[this.buObject.mid].dataExtensionField ||= {};
|
|
250
257
|
|
|
251
258
|
if (!deFieldCache) {
|
|
252
259
|
return;
|
|
@@ -255,11 +262,16 @@ class DataFilter extends MetadataType {
|
|
|
255
262
|
if (!field?.DataExtension?.CustomerKey) {
|
|
256
263
|
continue;
|
|
257
264
|
}
|
|
258
|
-
if (
|
|
265
|
+
if (
|
|
266
|
+
!this.cache[this.buObject.mid].dataExtensionField[field.DataExtension.CustomerKey]
|
|
267
|
+
) {
|
|
259
268
|
/** @type {Object.<string, DataExtensionFieldItem[]>} */
|
|
260
|
-
this.cache.dataExtensionField[field.DataExtension.CustomerKey] =
|
|
269
|
+
this.cache[this.buObject.mid].dataExtensionField[field.DataExtension.CustomerKey] =
|
|
270
|
+
[];
|
|
261
271
|
}
|
|
262
|
-
this.cache.dataExtensionField[field.DataExtension.CustomerKey].push(
|
|
272
|
+
this.cache[this.buObject.mid].dataExtensionField[field.DataExtension.CustomerKey].push(
|
|
273
|
+
field
|
|
274
|
+
);
|
|
263
275
|
}
|
|
264
276
|
}
|
|
265
277
|
/**
|
|
@@ -268,7 +280,7 @@ class DataFilter extends MetadataType {
|
|
|
268
280
|
* @param {DataFilterMap} metadataTypeMap -
|
|
269
281
|
*/
|
|
270
282
|
static async _cacheContactAttributes(metadataTypeMap) {
|
|
271
|
-
if (this.cache
|
|
283
|
+
if (this.cache[this.buObject.mid]?.contactAttributes) {
|
|
272
284
|
return;
|
|
273
285
|
}
|
|
274
286
|
const subscriberFilters = Object.values(metadataTypeMap)
|
|
@@ -279,8 +291,8 @@ class DataFilter extends MetadataType {
|
|
|
279
291
|
const response = await this.client.rest.get('/email/v1/Contacts/Attributes/');
|
|
280
292
|
const keyFieldBackup = this.definition.keyField;
|
|
281
293
|
this.definition.keyField = 'id';
|
|
282
|
-
this.cache.
|
|
283
|
-
this.cache
|
|
294
|
+
this.cache[this.buObject.mid] ||= {};
|
|
295
|
+
this.cache[this.buObject.mid].contactAttributes = this.parseResponseBody(response);
|
|
284
296
|
this.definition.keyField = keyFieldBackup;
|
|
285
297
|
}
|
|
286
298
|
}
|
|
@@ -290,7 +302,7 @@ class DataFilter extends MetadataType {
|
|
|
290
302
|
* @param {DataFilterMap} metadataTypeMap -
|
|
291
303
|
*/
|
|
292
304
|
static async _cacheMeasures(metadataTypeMap) {
|
|
293
|
-
if (this.cache
|
|
305
|
+
if (this.cache?.[this.buObject.mid]?.measures) {
|
|
294
306
|
return;
|
|
295
307
|
}
|
|
296
308
|
const subscriberFilters = Object.values(metadataTypeMap)
|
|
@@ -312,8 +324,8 @@ class DataFilter extends MetadataType {
|
|
|
312
324
|
|
|
313
325
|
const keyFieldBackup = this.definition.keyField;
|
|
314
326
|
this.definition.keyField = 'measureID';
|
|
315
|
-
this.cache.
|
|
316
|
-
this.cache
|
|
327
|
+
this.cache[this.buObject.mid] ||= {};
|
|
328
|
+
this.cache[this.buObject.mid].measures = this.parseResponseBody(response);
|
|
317
329
|
this.definition.keyField = keyFieldBackup;
|
|
318
330
|
}
|
|
319
331
|
}
|
|
@@ -439,7 +451,9 @@ class DataFilter extends MetadataType {
|
|
|
439
451
|
return this._resolveFields(
|
|
440
452
|
metadata,
|
|
441
453
|
mode,
|
|
442
|
-
this.cache.dataExtensionField[
|
|
454
|
+
this.cache[this.buObject.mid].dataExtensionField[
|
|
455
|
+
metadata.r__source_dataExtension_key
|
|
456
|
+
],
|
|
443
457
|
metadata.c__filterDefinition?.ConditionSet
|
|
444
458
|
);
|
|
445
459
|
}
|
|
@@ -530,8 +544,8 @@ class DataFilter extends MetadataType {
|
|
|
530
544
|
metadata.c__filterDefinition?.ConditionSet
|
|
531
545
|
);
|
|
532
546
|
}
|
|
533
|
-
const contactAttributes = this.cache
|
|
534
|
-
const measures = this.cache
|
|
547
|
+
const contactAttributes = this.cache[this.buObject.mid]?.contactAttributes;
|
|
548
|
+
const measures = this.cache[this.buObject.mid]?.measures;
|
|
535
549
|
const conditionsArr = Array.isArray(filter.Condition)
|
|
536
550
|
? filter.Condition
|
|
537
551
|
: [filter.Condition];
|
|
@@ -695,7 +695,7 @@ class Event extends MetadataType {
|
|
|
695
695
|
...new Set(
|
|
696
696
|
Object.values(this.sfObjects.referencedObjects[objectAPIName])
|
|
697
697
|
.map((el) => el.referenceObjectName)
|
|
698
|
-
.
|
|
698
|
+
.toSorted()
|
|
699
699
|
),
|
|
700
700
|
]
|
|
701
701
|
: [];
|
|
@@ -793,7 +793,8 @@ class Event extends MetadataType {
|
|
|
793
793
|
} catch (ex) {
|
|
794
794
|
if (ex.code === 'ERR_BAD_RESPONSE') {
|
|
795
795
|
throw new Error(
|
|
796
|
-
`Could not find Salesforce entry object ${objectAPIName} on connected org
|
|
796
|
+
`Could not find Salesforce entry object ${objectAPIName} on connected org.`,
|
|
797
|
+
{ cause: ex }
|
|
797
798
|
);
|
|
798
799
|
}
|
|
799
800
|
}
|
|
@@ -861,7 +862,7 @@ class Event extends MetadataType {
|
|
|
861
862
|
*/
|
|
862
863
|
static checkSalesforceEntryEvents(ca, isPublished) {
|
|
863
864
|
// 1 check eventDataConfig
|
|
864
|
-
const edcObjects = ca.eventDataConfig.objects.
|
|
865
|
+
const edcObjects = ca.eventDataConfig.objects.toSorted((a, b) =>
|
|
865
866
|
a.dePrefix.localeCompare(b.dePrefix)
|
|
866
867
|
);
|
|
867
868
|
const warnings = [];
|
|
@@ -1067,7 +1068,7 @@ class Event extends MetadataType {
|
|
|
1067
1068
|
if (errors.length > 1) {
|
|
1068
1069
|
errors.unshift(``);
|
|
1069
1070
|
}
|
|
1070
|
-
throw new Error(errors.join('\n · '));
|
|
1071
|
+
throw new Error(errors.join('\n · '));
|
|
1071
1072
|
}
|
|
1072
1073
|
if (warnings?.length) {
|
|
1073
1074
|
// add a line break
|
|
@@ -1156,7 +1157,7 @@ class Event extends MetadataType {
|
|
|
1156
1157
|
ca.eventDataSummary =
|
|
1157
1158
|
'string' === typeof ca.eventDataSummary
|
|
1158
1159
|
? // @ts-expect-error transforming this from API-string-format to from mcdev-format
|
|
1159
|
-
ca.eventDataSummary.split('; ').filter(Boolean).
|
|
1160
|
+
ca.eventDataSummary.split('; ').filter(Boolean).toSorted()
|
|
1160
1161
|
: ca.eventDataSummary;
|
|
1161
1162
|
ca.passThroughArgument =
|
|
1162
1163
|
'string' === typeof ca.passThroughArgument
|
|
@@ -1204,7 +1205,7 @@ class Event extends MetadataType {
|
|
|
1204
1205
|
eventDataSummary =
|
|
1205
1206
|
'string' === typeof eventDataSummary
|
|
1206
1207
|
? // @ts-expect-error transforming this from API-string-format to from mcdev-format
|
|
1207
|
-
eventDataSummary.split('; ').filter(Boolean).
|
|
1208
|
+
eventDataSummary.split('; ').filter(Boolean).toSorted()
|
|
1208
1209
|
: eventDataSummary;
|
|
1209
1210
|
|
|
1210
1211
|
const errors = [];
|
|
@@ -1220,7 +1221,7 @@ class Event extends MetadataType {
|
|
|
1220
1221
|
if (errors.length > 1) {
|
|
1221
1222
|
errors.unshift(``);
|
|
1222
1223
|
}
|
|
1223
|
-
throw new Error(errors.join('\n · '));
|
|
1224
|
+
throw new Error(errors.join('\n · '));
|
|
1224
1225
|
}
|
|
1225
1226
|
}
|
|
1226
1227
|
|
|
@@ -22,6 +22,7 @@ import { Util } from '../util/util.js';
|
|
|
22
22
|
* @augments MetadataType
|
|
23
23
|
*/
|
|
24
24
|
class FileLocation extends MetadataType {
|
|
25
|
+
static cache = {};
|
|
25
26
|
/**
|
|
26
27
|
* Retrieves Metadata of FileLocation
|
|
27
28
|
* Endpoint /automation/v1/ftplocations/ return all FileLocations
|
|
@@ -32,8 +33,32 @@ class FileLocation extends MetadataType {
|
|
|
32
33
|
* @param {string} [key] customer key of single item to retrieve
|
|
33
34
|
* @returns {Promise.<MetadataTypeMapObj>} Promise
|
|
34
35
|
*/
|
|
35
|
-
static retrieve(retrieveDir, _, __, key) {
|
|
36
|
-
|
|
36
|
+
static async retrieve(retrieveDir, _, __, key) {
|
|
37
|
+
try {
|
|
38
|
+
const dataItems = await super.retrieveREST(
|
|
39
|
+
null,
|
|
40
|
+
'/data/v1/filetransferlocation' + (key ? '/' + encodeURIComponent(key) : 's'),
|
|
41
|
+
null,
|
|
42
|
+
key
|
|
43
|
+
);
|
|
44
|
+
this.cache[this.buObject.mid] ||= {};
|
|
45
|
+
this.cache[this.buObject.mid].dataItems = dataItems.metadata;
|
|
46
|
+
} catch (ex) {
|
|
47
|
+
if (ex.code === 'ERR_BAD_REQUEST') {
|
|
48
|
+
// if retrieve-by-key comes up empty, the data-endpoint returns a code 400
|
|
49
|
+
Util.logger.debug(ex.message);
|
|
50
|
+
} else {
|
|
51
|
+
Util.logger.warn(ex.message);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const items = await super.retrieveREST(
|
|
55
|
+
retrieveDir,
|
|
56
|
+
'/automation/v1/ftplocations/',
|
|
57
|
+
null,
|
|
58
|
+
key
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
return items;
|
|
37
62
|
}
|
|
38
63
|
|
|
39
64
|
/**
|
|
@@ -42,9 +67,156 @@ class FileLocation extends MetadataType {
|
|
|
42
67
|
* @returns {Promise.<MetadataTypeMapObj>} Promise
|
|
43
68
|
*/
|
|
44
69
|
static async retrieveForCache() {
|
|
45
|
-
return
|
|
70
|
+
return this.retrieve(null);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Creates a single item
|
|
75
|
+
*
|
|
76
|
+
* @param {MetadataTypeItem} metadata a single item
|
|
77
|
+
* @returns {Promise.<MetadataTypeItem>} Promise
|
|
78
|
+
*/
|
|
79
|
+
static create(metadata) {
|
|
80
|
+
return this.createREST(metadata, '/data/v1/filetransferlocation');
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Updates a single item
|
|
84
|
+
*
|
|
85
|
+
* @param {MetadataTypeItem} metadata a single item
|
|
86
|
+
* @returns {Promise.<MetadataTypeItem>} Promise
|
|
87
|
+
*/
|
|
88
|
+
static update(metadata) {
|
|
89
|
+
return this.updateREST(
|
|
90
|
+
metadata,
|
|
91
|
+
'/data/v1/filetransferlocation/' +
|
|
92
|
+
encodeURIComponent(metadata[this.definition.keyField])
|
|
93
|
+
);
|
|
46
94
|
}
|
|
47
95
|
|
|
96
|
+
/**
|
|
97
|
+
* helper for {@link MetadataType.parseResponseBody} that creates a custom key field for this type based on mobileCode and keyword
|
|
98
|
+
*
|
|
99
|
+
* @param {MetadataTypeItem} metadata single item
|
|
100
|
+
*/
|
|
101
|
+
static createCustomKeyField(metadata) {
|
|
102
|
+
if (metadata.fileTransferLocation) {
|
|
103
|
+
const fileTransferLocation = metadata.fileTransferLocation;
|
|
104
|
+
for (const key of Object.keys(metadata)) {
|
|
105
|
+
delete metadata[key];
|
|
106
|
+
}
|
|
107
|
+
Object.assign(metadata, fileTransferLocation);
|
|
108
|
+
} else {
|
|
109
|
+
if (!metadata.customerKey && this.cache[this.buObject.mid]?.dataItems) {
|
|
110
|
+
const nameMatch = Object.values(this.cache[this.buObject.mid].dataItems).find(
|
|
111
|
+
(item) => item.name === metadata.name
|
|
112
|
+
);
|
|
113
|
+
if (nameMatch) {
|
|
114
|
+
Object.assign(metadata, nameMatch);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (!this.definition.locationTypeIdMappingDeployable[metadata.locationTypeId]) {
|
|
118
|
+
// old file location types are only returned by the automation-endpoint which does not return customerKey field - but also these are not updatable and hence we can improvise here
|
|
119
|
+
|
|
120
|
+
metadata.customerKey ||= metadata.name;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Creates a single metadata entry via REST
|
|
127
|
+
*
|
|
128
|
+
* @param {MetadataTypeItem} metadataEntry a single metadata Entry
|
|
129
|
+
* @param {string} uri rest endpoint for POST
|
|
130
|
+
* @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method
|
|
131
|
+
* @returns {Promise.<object> | null} Promise of API response or null in case of an error
|
|
132
|
+
*/
|
|
133
|
+
static async createREST(metadataEntry, uri, handleOutside) {
|
|
134
|
+
this.removeNotCreateableFields(metadataEntry);
|
|
135
|
+
const createPayload = { fileTransferLocation: metadataEntry };
|
|
136
|
+
try {
|
|
137
|
+
// set to empty object in case API returned nothing to be able to update it in helper classes
|
|
138
|
+
let response = (await this.client.rest.post(uri, createPayload)) || {};
|
|
139
|
+
response = await this.postCreateTasks(metadataEntry, response);
|
|
140
|
+
if (!handleOutside) {
|
|
141
|
+
Util.logger.info(
|
|
142
|
+
` - created ${Util.getTypeKeyName(this.definition, metadataEntry)}`
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
return response;
|
|
146
|
+
} catch (ex) {
|
|
147
|
+
const parsedErrors = this.getErrorsREST(ex);
|
|
148
|
+
Util.logger.error(
|
|
149
|
+
` ☇ error creating ${Util.getTypeKeyName(this.definition, metadataEntry)}:`
|
|
150
|
+
);
|
|
151
|
+
if (parsedErrors.length) {
|
|
152
|
+
for (const msg of parsedErrors) {
|
|
153
|
+
Util.logger.error(' • ' + msg);
|
|
154
|
+
}
|
|
155
|
+
} else if (ex?.message) {
|
|
156
|
+
Util.logger.debug(ex.message);
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* helper for {@link MetadataType.createREST}
|
|
164
|
+
*
|
|
165
|
+
* @param {MetadataTypeItem} _ a single metadata Entry
|
|
166
|
+
* @param {object} apiResponse varies depending on the API call
|
|
167
|
+
* @returns {Promise.<object>} apiResponse, potentially modified
|
|
168
|
+
*/
|
|
169
|
+
static async postCreateTasks(_, apiResponse) {
|
|
170
|
+
return apiResponse?.fileTransferLocation || apiResponse;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Updates a single metadata entry via REST
|
|
175
|
+
*
|
|
176
|
+
* @param {MetadataTypeItem} metadataEntry a single metadata Entry
|
|
177
|
+
* @param {string} uri rest endpoint for PATCH
|
|
178
|
+
* @param {'patch'|'post'|'put'} [httpMethod] defaults to 'patch'; some update requests require PUT instead of PATCH
|
|
179
|
+
* @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method
|
|
180
|
+
* @returns {Promise.<object> | null} Promise of API response or null in case of an error
|
|
181
|
+
*/
|
|
182
|
+
static async updateREST(metadataEntry, uri, httpMethod = 'patch', handleOutside) {
|
|
183
|
+
this.removeNotUpdateableFields(metadataEntry);
|
|
184
|
+
const updatePayload = { fileTransferLocation: metadataEntry };
|
|
185
|
+
try {
|
|
186
|
+
// set to empty object in case API returned nothing to be able to update it in helper classes
|
|
187
|
+
let response = (await this.client.rest[httpMethod](uri, updatePayload)) || {};
|
|
188
|
+
await this._postChangeKeyTasks(metadataEntry);
|
|
189
|
+
this.getErrorsREST(response);
|
|
190
|
+
response = await this.postUpdateTasks(metadataEntry, response);
|
|
191
|
+
// some times, e.g. automation dont return a key in their update response and hence we need to fall back to name
|
|
192
|
+
if (!handleOutside) {
|
|
193
|
+
Util.logger.info(
|
|
194
|
+
` - updated ${Util.getTypeKeyName(this.definition, metadataEntry)}`
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
return response;
|
|
198
|
+
} catch (ex) {
|
|
199
|
+
const parsedErrors = this.getErrorsREST(ex);
|
|
200
|
+
Util.logger.error(
|
|
201
|
+
` ☇ error updating ${Util.getTypeKeyName(this.definition, metadataEntry)}:`
|
|
202
|
+
);
|
|
203
|
+
for (const msg of parsedErrors) {
|
|
204
|
+
Util.logger.error(' • ' + msg);
|
|
205
|
+
}
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP}
|
|
212
|
+
*
|
|
213
|
+
* @param {MetadataTypeItem} _ a single metadata Entry
|
|
214
|
+
* @param {object} apiResponse varies depending on the API call
|
|
215
|
+
* @returns {Promise.<object>} apiResponse, potentially modified
|
|
216
|
+
*/
|
|
217
|
+
static postUpdateTasks(_, apiResponse) {
|
|
218
|
+
return apiResponse?.fileTransferLocation || apiResponse;
|
|
219
|
+
}
|
|
48
220
|
/**
|
|
49
221
|
* prepares a import definition for deployment
|
|
50
222
|
*
|
|
@@ -54,6 +226,14 @@ class FileLocation extends MetadataType {
|
|
|
54
226
|
static async preDeployTasks(metadata) {
|
|
55
227
|
if (metadata.c__locationType) {
|
|
56
228
|
metadata.locationTypeId = this.definition.locationTypeMapping[metadata.c__locationType];
|
|
229
|
+
if (this.definition.locationTypeMappingDeployable[metadata.c__locationType]) {
|
|
230
|
+
metadata.locationType =
|
|
231
|
+
this.definition.locationTypeMappingDeployable[metadata.c__locationType];
|
|
232
|
+
} else {
|
|
233
|
+
throw new Error(
|
|
234
|
+
`Only FileLocations of types ${Object.keys(this.definition.locationTypeMappingDeployable).join(', ')} can be deployed via mcdev.`
|
|
235
|
+
);
|
|
236
|
+
}
|
|
57
237
|
}
|
|
58
238
|
return metadata;
|
|
59
239
|
}
|
|
@@ -65,7 +245,7 @@ class FileLocation extends MetadataType {
|
|
|
65
245
|
* @returns {MetadataTypeItem} parsed metadata
|
|
66
246
|
*/
|
|
67
247
|
static postRetrieveTasks(metadata) {
|
|
68
|
-
if (metadata.locationTypeId) {
|
|
248
|
+
if (metadata.locationTypeId !== undefined) {
|
|
69
249
|
try {
|
|
70
250
|
metadata.c__locationType = Util.inverseGet(
|
|
71
251
|
this.definition.locationTypeMapping,
|
|
@@ -78,9 +258,29 @@ class FileLocation extends MetadataType {
|
|
|
78
258
|
metadata.locationTypeId
|
|
79
259
|
);
|
|
80
260
|
}
|
|
261
|
+
} else if (metadata.locationType) {
|
|
262
|
+
// assuming create/update of new types
|
|
263
|
+
metadata.c__locationType = Util.inverseGet(
|
|
264
|
+
this.definition.locationTypeMappingDeployable,
|
|
265
|
+
metadata.locationType
|
|
266
|
+
);
|
|
81
267
|
}
|
|
82
268
|
return metadata;
|
|
83
269
|
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Delete a metadata item from the specified business unit
|
|
273
|
+
*
|
|
274
|
+
* @param {string} key Identifier of item
|
|
275
|
+
* @returns {Promise.<boolean>} deletion success flag
|
|
276
|
+
*/
|
|
277
|
+
static async deleteByKey(key) {
|
|
278
|
+
return super.deleteByKeyREST(
|
|
279
|
+
'/data/v1/filetransferlocation/' + encodeURIComponent(key),
|
|
280
|
+
key,
|
|
281
|
+
400
|
|
282
|
+
);
|
|
283
|
+
}
|
|
84
284
|
}
|
|
85
285
|
|
|
86
286
|
// Assign definition to static attributes
|
|
@@ -309,11 +309,12 @@ class Folder extends MetadataType {
|
|
|
309
309
|
parsed[normalizedKey] = parsed['undefined'];
|
|
310
310
|
delete parsed['undefined'];
|
|
311
311
|
}
|
|
312
|
-
const newObject = {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
312
|
+
const newObject = {
|
|
313
|
+
[normalizedKey]: Object.assign(
|
|
314
|
+
beforeMetadata,
|
|
315
|
+
parsed[normalizedKey]
|
|
316
|
+
),
|
|
317
|
+
};
|
|
317
318
|
cache.mergeMetadata('folder', newObject);
|
|
318
319
|
|
|
319
320
|
upsertResults[metadataKey] = beforeMetadata;
|
|
@@ -678,7 +679,7 @@ class Folder extends MetadataType {
|
|
|
678
679
|
return fileName2FileContent;
|
|
679
680
|
} catch (ex) {
|
|
680
681
|
Util.metadataLogger('error', this.definition.type, 'getJsonFromFS', ex);
|
|
681
|
-
throw
|
|
682
|
+
throw ex;
|
|
682
683
|
}
|
|
683
684
|
}
|
|
684
685
|
|
|
@@ -697,7 +698,7 @@ class Folder extends MetadataType {
|
|
|
697
698
|
leftOperand: 'ContentType',
|
|
698
699
|
operator: contentTypeList.length === 1 ? 'equals' : 'IN',
|
|
699
700
|
rightOperand:
|
|
700
|
-
contentTypeList.length === 1 ? contentTypeList[0] : contentTypeList.
|
|
701
|
+
contentTypeList.length === 1 ? contentTypeList[0] : contentTypeList.toSorted(),
|
|
701
702
|
};
|
|
702
703
|
options.filter = options.filter
|
|
703
704
|
? {
|