mcdev 8.0.2 → 8.2.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 (58) hide show
  1. package/.github/ISSUE_TEMPLATE/bug.yml +2 -0
  2. package/.github/workflows/code-test.yml +2 -2
  3. package/.github/workflows/coverage-base-update.yml +3 -3
  4. package/.github/workflows/coverage-develop-branch.yml +3 -3
  5. package/.github/workflows/coverage-main-branch.yml +3 -3
  6. package/.github/workflows/coverage.yml +4 -4
  7. package/.github/workflows/npm-publish.yml +4 -4
  8. package/@types/lib/MetadataTypeDefinitions.d.ts +2 -0
  9. package/@types/lib/MetadataTypeDefinitions.d.ts.map +1 -1
  10. package/@types/lib/MetadataTypeInfo.d.ts +2 -0
  11. package/@types/lib/MetadataTypeInfo.d.ts.map +1 -1
  12. package/@types/lib/index.d.ts.map +1 -1
  13. package/@types/lib/metadataTypes/Asset.d.ts.map +1 -1
  14. package/@types/lib/metadataTypes/DataExtensionField.d.ts +1 -7
  15. package/@types/lib/metadataTypes/DataExtensionField.d.ts.map +1 -1
  16. package/@types/lib/metadataTypes/Journey.d.ts +6 -0
  17. package/@types/lib/metadataTypes/Journey.d.ts.map +1 -1
  18. package/@types/lib/metadataTypes/MetadataType.d.ts.map +1 -1
  19. package/@types/lib/metadataTypes/TriggeredSendSummary.d.ts +257 -0
  20. package/@types/lib/metadataTypes/TriggeredSendSummary.d.ts.map +1 -0
  21. package/@types/lib/metadataTypes/definitions/DataExtensionField.definition.d.ts +1 -0
  22. package/@types/lib/metadataTypes/definitions/Journey.definition.d.ts +6 -0
  23. package/@types/lib/metadataTypes/definitions/TriggeredSendSummary.definition.d.ts +208 -0
  24. package/@types/lib/metadataTypes/definitions/TriggeredSendSummary.definition.d.ts.map +1 -0
  25. package/@types/lib/util/devops.d.ts +2 -1
  26. package/@types/lib/util/devops.d.ts.map +1 -1
  27. package/@types/lib/util/util.d.ts +2 -1
  28. package/@types/lib/util/util.d.ts.map +1 -1
  29. package/lib/MetadataTypeDefinitions.js +2 -0
  30. package/lib/MetadataTypeInfo.js +2 -0
  31. package/lib/cli.js +5 -0
  32. package/lib/index.js +29 -8
  33. package/lib/metadataTypes/Asset.js +30 -7
  34. package/lib/metadataTypes/Automation.js +1 -1
  35. package/lib/metadataTypes/DataExtensionField.js +102 -49
  36. package/lib/metadataTypes/Folder.js +2 -2
  37. package/lib/metadataTypes/Journey.js +5 -2
  38. package/lib/metadataTypes/MetadataType.js +8 -2
  39. package/lib/metadataTypes/TriggeredSendSummary.js +102 -0
  40. package/lib/metadataTypes/definitions/DataExtensionField.definition.js +1 -0
  41. package/lib/metadataTypes/definitions/Journey.definition.js +6 -0
  42. package/lib/metadataTypes/definitions/TriggeredSendSummary.definition.js +211 -0
  43. package/lib/util/devops.js +33 -15
  44. package/lib/util/util.js +13 -4
  45. package/package.json +10 -10
  46. package/test/mockRoot/.mcdevrc.json +1 -1
  47. package/test/resources/1111111/dataFolder/retrieve-ContentTypeINdataextension,hidden,queryactivity,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml +26 -0
  48. package/test/resources/9999999/automation/create-testNew_automation-expected.md +1 -1
  49. package/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md +1 -1
  50. package/test/resources/9999999/automation/update-testExisting_automation-expected.md +1 -1
  51. package/test/resources/9999999/dataExtensionField/retrieve-Name=FirstName-response.xml +78 -0
  52. package/test/resources/9999999/dataExtensionField/retrieve-Name=LastName-response.xml +78 -0
  53. package/test/resources/9999999/triggeredSendSummary/get-expected.json +24 -0
  54. package/test/resources/9999999/triggeredSendSummary/retrieve-response.xml +49 -0
  55. package/test/type.dataExtension.test.js +41 -14
  56. package/test/type.dataExtensionField.test.js +81 -0
  57. package/test/type.journey.test.js +37 -2
  58. package/test/type.triggeredSendSummary.test.js +45 -0
@@ -81,7 +81,7 @@ class Folder extends MetadataType {
81
81
  };
82
82
  for (const id of sortPairs) {
83
83
  if (!idMap[id]) {
84
- Util.logger.debug(`Error: id ${id} not found in idMap-obj but in sortPairs-array.`);
84
+ Util.logger.debug(`id ${id} not found in idMap-obj but in sortPairs-array.`);
85
85
  } else if (
86
86
  idMap[id].ParentFolder &&
87
87
  Number.isSafeInteger(idMap[id].ParentFolder.ID) &&
@@ -714,7 +714,7 @@ class Folder extends MetadataType {
714
714
  ),
715
715
  options
716
716
  );
717
- return response.Results;
717
+ return response.Results ?? [];
718
718
  }
719
719
 
720
720
  /**
@@ -2554,9 +2554,12 @@ class Journey extends MetadataType {
2554
2554
  break;
2555
2555
  }
2556
2556
  default: {
2557
- throw new Error(
2558
- `${this.definition.type} type ${journey.definitionType} not supported yet by validate method`
2557
+ Util.logger.info(
2558
+ Util.getGrayMsg(
2559
+ ` ☇ skipping ${this.definition.type} ${key}: type ${journey.definitionType} not supported yet by validate method`
2560
+ )
2559
2561
  );
2562
+ continue;
2560
2563
  }
2561
2564
  }
2562
2565
  } // for loop
@@ -2080,6 +2080,12 @@ class MetadataType {
2080
2080
  subtypeExtension,
2081
2081
  templateVariables
2082
2082
  );
2083
+ if (!savedResults[originalKey]) {
2084
+ // happens in case like-filter struck
2085
+ delete savedResults[originalKey];
2086
+ filterCounter++;
2087
+ continue;
2088
+ }
2083
2089
  } catch (ex) {
2084
2090
  Util.logger.debug(JSON.stringify(savedResults[originalKey]));
2085
2091
  Util.logger.errorStack(
@@ -2126,7 +2132,7 @@ class MetadataType {
2126
2132
  // normalize results[metadataEntry]
2127
2133
  results[originalKey] = postRetrieveData.json;
2128
2134
 
2129
- if (Util.OPTIONS.like && !Util.fieldsLike(results[originalKey])) {
2135
+ if (Util.OPTIONS.like && !Util.fieldsLike(results[originalKey], this.definition)) {
2130
2136
  Util.logger.debug(`Filtered ${originalKey} because of --like option`);
2131
2137
  return;
2132
2138
  }
@@ -2161,7 +2167,7 @@ class MetadataType {
2161
2167
  templateVariables
2162
2168
  );
2163
2169
  }
2164
- if (Util.OPTIONS.like && !Util.fieldsLike(results[originalKey])) {
2170
+ if (Util.OPTIONS.like && !Util.fieldsLike(results[originalKey], this.definition)) {
2165
2171
  Util.logger.debug(`Filtered ${originalKey} because of --like option`);
2166
2172
  return;
2167
2173
  }
@@ -0,0 +1,102 @@
1
+ 'use strict';
2
+
3
+ import MetadataType from './MetadataType.js';
4
+ import cache from '../util/cache.js';
5
+ import { Util } from '../util/util.js';
6
+
7
+ /**
8
+ * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject
9
+ * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract
10
+ * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem
11
+ * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem
12
+ * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff
13
+ * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj
14
+ * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap
15
+ * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj
16
+ * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams
17
+ * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap
18
+ */
19
+
20
+ /**
21
+ * TriggeredSendSummary MetadataType
22
+ *
23
+ * @augments MetadataType
24
+ */
25
+ class TriggeredSendSummary extends MetadataType {
26
+ /**
27
+ * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata
28
+ *
29
+ * @param {string} retrieveDir Directory where retrieved metadata directory will be saved
30
+ * @param {void | string[]} [_] unused parameter
31
+ * @param {void | string[]} [__] unused parameter
32
+ * @param {string} [key] customer key of single item to retrieve
33
+ * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata
34
+ */
35
+ static retrieve(retrieveDir, _, __, key) {
36
+ /** @type {SoapRequestParams} */
37
+ let requestParams = {};
38
+ if (key) {
39
+ // filter by CustomerKey when a specific key is requested
40
+ requestParams = {
41
+ filter: {
42
+ leftOperand: 'CustomerKey',
43
+ operator: 'equals',
44
+ rightOperand: key,
45
+ },
46
+ };
47
+ }
48
+
49
+ return super.retrieveSOAP(retrieveDir, requestParams, key);
50
+ }
51
+ /**
52
+ * parses retrieved Metadata before saving
53
+ *
54
+ * @param {MetadataTypeItem} metadata a single item
55
+ * @returns {MetadataTypeItem | void} Array with one metadata object and one sql string
56
+ */
57
+ static postRetrieveTasks(metadata) {
58
+ // CustomerKey for this type is the same as the CustomerKey of the TriggeredSend it relates to
59
+ const triggeredSend = cache.getByKey('triggeredSend', metadata.CustomerKey);
60
+ if (!triggeredSend) {
61
+ Util.logger.verbose(
62
+ `Could not find related TriggeredSend with CustomerKey '${metadata.CustomerKey}' for the TriggeredSendSummary.`
63
+ );
64
+ return null;
65
+ }
66
+ metadata['TriggeredSend.CategoryID'] = triggeredSend.CategoryID;
67
+ // folder path for a TriggeredSendSummary is the same as for the related TriggeredSend. CategoryID is not retrievable for this type, so use the TriggeredSend's field
68
+ this.setFolderPath(metadata);
69
+ delete metadata['TriggeredSend.CategoryID'];
70
+ metadata.r__triggeredSend_name = triggeredSend.Name;
71
+ metadata.r__triggeredSend_key = triggeredSend.CustomerKey;
72
+ return metadata;
73
+ }
74
+ /**
75
+ * retrieves the folder path from cache and updates the TriggeredSendSummary metadata with it after retrieve
76
+ *
77
+ * @param {MetadataTypeItem} metadata a single item
78
+ */
79
+ static setFolderPath(metadata) {
80
+ try {
81
+ metadata.r__folder_Path = cache.searchForField(
82
+ 'folder',
83
+ metadata[this.definition.folderIdField],
84
+ 'ID',
85
+ 'Path'
86
+ );
87
+ delete metadata[this.definition.folderIdField];
88
+ } catch {
89
+ Util.logger.verbose(
90
+ ` ☇ skipping ${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': Could not find folder.`
91
+ );
92
+ // do not save this Triggered Send Summary because it would not be visible in the user interface
93
+ return;
94
+ }
95
+ }
96
+ }
97
+
98
+ // Assign definition to static attributes
99
+ import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js';
100
+ TriggeredSendSummary.definition = MetadataTypeDefinitions.triggeredSendSummary;
101
+
102
+ export default TriggeredSendSummary;
@@ -14,6 +14,7 @@ export default {
14
14
  typeRetrieveByDefault: false,
15
15
  typeCdpByDefault: false,
16
16
  typeName: 'Data Extension Field',
17
+ deleteSynchronously: true, // should be run one at a time to allow asking for permission to mass-delete if *.fieldname is used
17
18
  fields: {
18
19
  'Client.ID': {
19
20
  isCreateable: false,
@@ -261,6 +261,12 @@ export default {
261
261
  retrieving: true,
262
262
  template: true,
263
263
  },
264
+ 'activities[].configurationArguments.isReconcilable': {
265
+ isCreateable: true,
266
+ isUpdateable: true,
267
+ retrieving: true,
268
+ template: true,
269
+ },
264
270
  'activities[].configurationArguments.isActivityBatchValidated': {
265
271
  isCreateable: true,
266
272
  isUpdateable: true,
@@ -0,0 +1,211 @@
1
+ export default {
2
+ bodyIteratorField: 'Results',
3
+ dependencies: [
4
+ 'triggeredSend',
5
+ 'folder-hidden',
6
+ 'folder-triggered_send',
7
+ 'folder-triggered_send_journeybuilder',
8
+ ],
9
+ dependencyGraph: {
10
+ triggeredSend: ['r__triggeredSend_key'],
11
+ },
12
+ filter: {},
13
+ hasExtended: false,
14
+ idField: 'ObjectID',
15
+ keepId: false,
16
+ keyIsFixed: true,
17
+ keyField: 'CustomerKey',
18
+ nameField: 'r__triggeredSend_name',
19
+ folderIdField: 'TriggeredSend.CategoryID',
20
+ createdDateField: null,
21
+ createdNameField: null,
22
+ lastmodDateField: null,
23
+ lastmodNameField: null,
24
+ restPagination: null,
25
+ maxKeyLength: 36,
26
+ type: 'triggeredSendSummary',
27
+ soapType: 'triggeredSendSummary',
28
+ typeDescription: 'Summary data for a Triggered Send',
29
+ typeRetrieveByDefault: false,
30
+ typeCdpByDefault: false,
31
+ typeName: 'Triggered Send Summary',
32
+ fields: {
33
+ Bounces: {
34
+ isCreateable: true,
35
+ isUpdateable: false,
36
+ retrieving: true,
37
+ templating: true,
38
+ },
39
+ Clicks: {
40
+ isCreateable: true,
41
+ isUpdateable: false,
42
+ retrieving: true,
43
+ templating: true,
44
+ },
45
+ 'Client.ID': {
46
+ isCreateable: false,
47
+ isUpdateable: false,
48
+ retrieving: false,
49
+ templating: false,
50
+ },
51
+ Conversions: {
52
+ isCreateable: true,
53
+ isUpdateable: false,
54
+ retrieving: true,
55
+ templating: true,
56
+ },
57
+ CustomerKey: {
58
+ isCreateable: true,
59
+ isUpdateable: true,
60
+ retrieving: true,
61
+ templating: true,
62
+ },
63
+ FTAFEmailsSent: {
64
+ isCreateable: true,
65
+ isUpdateable: false,
66
+ retrieving: true,
67
+ templating: true,
68
+ },
69
+ FTAFOptIns: {
70
+ isCreateable: true,
71
+ isUpdateable: false,
72
+ retrieving: true,
73
+ templating: true,
74
+ },
75
+ FTAFRequests: {
76
+ isCreateable: true,
77
+ isUpdateable: false,
78
+ retrieving: true,
79
+ templating: true,
80
+ },
81
+ ID: {
82
+ isCreateable: false,
83
+ isUpdateable: false,
84
+ retrieving: false,
85
+ templating: false,
86
+ },
87
+ InProcess: {
88
+ isCreateable: true,
89
+ isUpdateable: false,
90
+ retrieving: true,
91
+ templating: true,
92
+ },
93
+ NotSentDueToError: {
94
+ isCreateable: true,
95
+ isUpdateable: false,
96
+ retrieving: true,
97
+ templating: true,
98
+ },
99
+ NotSentDueToOptOut: {
100
+ isCreateable: true,
101
+ isUpdateable: false,
102
+ retrieving: true,
103
+ templating: true,
104
+ },
105
+ NotSentDueToUndeliverable: {
106
+ isCreateable: true,
107
+ isUpdateable: false,
108
+ retrieving: true,
109
+ templating: true,
110
+ },
111
+ ObjectID: {
112
+ isCreateable: false,
113
+ isUpdateable: false,
114
+ retrieving: false,
115
+ templating: false,
116
+ },
117
+ /* ObjectState: {
118
+ isCreateable: false,
119
+ isUpdateable: false,
120
+ retrieving: false,
121
+ templating: false,
122
+ }, */ // according to the documentation"Reserved for future use"
123
+ Opens: {
124
+ isCreateable: true,
125
+ isUpdateable: false,
126
+ retrieving: true,
127
+ templating: true,
128
+ },
129
+ OptOuts: {
130
+ isCreateable: true,
131
+ isUpdateable: false,
132
+ retrieving: true,
133
+ templating: true,
134
+ },
135
+ Owner: {
136
+ isCreateable: false,
137
+ isUpdateable: false,
138
+ retrieving: false,
139
+ templating: false,
140
+ },
141
+ PartnerKey: {
142
+ isCreateable: false,
143
+ isUpdateable: false,
144
+ retrieving: false,
145
+ templating: false,
146
+ },
147
+ PartnerProperties: {
148
+ isCreateable: false,
149
+ isUpdateable: false,
150
+ retrieving: false,
151
+ templating: false,
152
+ },
153
+ Queued: {
154
+ isCreateable: true,
155
+ isUpdateable: false,
156
+ retrieving: true,
157
+ templating: true,
158
+ },
159
+ Sent: {
160
+ isCreateable: true,
161
+ isUpdateable: false,
162
+ retrieving: true,
163
+ templating: true,
164
+ },
165
+ SurveyResponses: {
166
+ isCreateable: true,
167
+ isUpdateable: false,
168
+ retrieving: true,
169
+ templating: true,
170
+ },
171
+ UniqueClicks: {
172
+ isCreateable: true,
173
+ isUpdateable: false,
174
+ retrieving: true,
175
+ templating: true,
176
+ },
177
+ UniqueConversions: {
178
+ isCreateable: true,
179
+ isUpdateable: false,
180
+ retrieving: true,
181
+ templating: true,
182
+ },
183
+ UniqueOpens: {
184
+ isCreateable: true,
185
+ isUpdateable: false,
186
+ retrieving: true,
187
+ templating: true,
188
+ },
189
+ CorrelationID: {
190
+ isCreateable: false,
191
+ isUpdateable: false,
192
+ retrieving: false,
193
+ templating: false,
194
+ },
195
+ CreatedDate: {
196
+ isCreateable: false,
197
+ isUpdateable: false,
198
+ retrieving: false /** Listed in the type documentation but not retrievable */,
199
+ templating: false,
200
+ },
201
+ ModifiedDate: {
202
+ isCreateable: false,
203
+ isUpdateable: false,
204
+ retrieving: false /** Listed in the type documentation but not retrievable */,
205
+ templating: false,
206
+ },
207
+ r__triggeredSend_name: { skipValidation: true },
208
+ r__triggeredSend_key: { skipValidation: true },
209
+ r__folder_Path: { skipValidation: true },
210
+ },
211
+ };
@@ -50,11 +50,12 @@ const DevOps = {
50
50
  async getDeltaList(properties, range, saveToDeployDir, filterPathsCSV, commitHistory) {
51
51
  const rangeUserInput = range;
52
52
  const filterPaths = filterPathsCSV
53
- ? filterPathsCSV.split(',').map((filePath) =>
54
- path
55
- .normalize(properties.directories.retrieve + filePath)
56
- .split('\\')
57
- .join('/')
53
+ ? filterPathsCSV.split(',').map(
54
+ (filePath) =>
55
+ path
56
+ .normalize(properties.directories.retrieve + filePath)
57
+ .split('\\')
58
+ .join('/') + '/'
58
59
  )
59
60
  : [properties.directories.retrieve];
60
61
  if (range) {
@@ -194,10 +195,13 @@ const DevOps = {
194
195
  // - retrieve/cred/bu/asset/block/016aecc7-7063-4b78-93f4-aa119ea933c7.asset-block-meta.html
195
196
  // - retrieve/cred/bu/asset/message/003c1ef5-f538-473a-91da-26942024a64a/blocks/views.html.slots.[bottom-8frq7iw2k99].asset-message-meta.html
196
197
  // - retrieve/cred/bu/query/03efd5f1-ba1f-487a-9c9a-36aeb2ae5192.query-meta.sql
197
- file.externalKey =
198
- file.type === 'asset'
199
- ? file.file.split('/')[5].split('.')[0] // assets have an additional folder level for their subtype
200
- : file.file.split('/')[4].split('.')[0];
198
+ // assets have an additional folder level for their subtype
199
+ // keys could contain dots themselves
200
+ file.externalKey = file.file
201
+ .split('/')
202
+ [file.type === 'asset' ? 5 : 4].split('.')
203
+ .slice(0, -2)
204
+ .join('.');
201
205
  file.name = null;
202
206
  }
203
207
 
@@ -266,14 +270,20 @@ const DevOps = {
266
270
  }
267
271
  // Write into delta.json to serve as documentation
268
272
  const directoryDeltaPkg = 'logs/';
269
- await File.writeJSONToFile(directoryDeltaPkg, Util.logFileName + '-delta_package', delta);
270
- this.document(directoryDeltaPkg, delta);
273
+ await File.writeJSONToFile(
274
+ directoryDeltaPkg,
275
+ Util.logFileName +
276
+ '-delta_package-' +
277
+ filterPathsCSV.replaceAll(',', '-').replaceAll('/', '-'),
278
+ delta
279
+ );
280
+ this.document(directoryDeltaPkg, filterPathsCSV, delta);
271
281
  Util.logger.info(
272
282
  `- ✔️ Identified changes: Add/Update=${gitActionsCounter['add/update']}, Move=${gitActionsCounter['move']}, Delete=${gitActionsCounter['delete']}`
273
283
  );
274
- if (gitActionsCounter.delete > 0) {
284
+ if (gitActionsCounter.move > 0 || gitActionsCounter.delete > 0) {
275
285
  Util.logger.warn(
276
- 'Please note that deletions have to be done manually on the SFMC website.'
286
+ 'Deleted/Changed keys detected! Please note that re-keyed components should have their key changed as a pre-deployment step.'
277
287
  );
278
288
  }
279
289
  Util.logger.info(
@@ -571,10 +581,11 @@ const DevOps = {
571
581
  * create markdown file for deployment listing
572
582
  *
573
583
  * @param {string} directory -
584
+ * @param {string} filterPathsCSV -
574
585
  * @param {object} jsonReport -
575
586
  * @returns {void}
576
587
  */
577
- document(directory, jsonReport) {
588
+ document(directory, filterPathsCSV, jsonReport) {
578
589
  const tabled = jsonToTable(jsonReport);
579
590
  let output = `# Deployment Report\n\n`;
580
591
  let tableSeparator = '';
@@ -596,7 +607,14 @@ const DevOps = {
596
607
  }
597
608
  try {
598
609
  // write to disk (asynchronously)
599
- File.writeToFile(directory, Util.logFileName + '-delta_package', 'md', output);
610
+ File.writeToFile(
611
+ directory,
612
+ Util.logFileName +
613
+ '-delta_package-' +
614
+ filterPathsCSV.replaceAll(',', '-').replaceAll('/', '-'),
615
+ 'md',
616
+ output
617
+ );
600
618
  } catch (ex) {
601
619
  Util.logger.error(`DevOps.document():: error | ` + ex.message);
602
620
  }
package/lib/util/util.js CHANGED
@@ -1143,14 +1143,17 @@ export const Util = {
1143
1143
  * returns true if no LIKE filter is defined or if all filters match
1144
1144
  *
1145
1145
  * @param {MetadataTypeItem} metadata a single metadata item
1146
+ * @param {object} definition type definition
1146
1147
  * @param {object} [filters] only used in recursive calls
1147
1148
  * @returns {boolean} true if no LIKE filter is defined or if all filters match
1148
1149
  */
1149
- fieldsLike(metadata, filters) {
1150
+ fieldsLike(metadata, definition, filters) {
1150
1151
  if (metadata.json && metadata.codeArr) {
1151
1152
  // Compensate for CodeExtractItem format
1152
1153
  metadata = metadata.json;
1153
1154
  }
1155
+ // ensure we only convert "key" and "name" fields on the first call to this method
1156
+ const checkDefaultKeyAndName = filters ? false : true;
1154
1157
  filters ||= Util.OPTIONS.like;
1155
1158
  if (!filters) {
1156
1159
  return true;
@@ -1163,14 +1166,20 @@ export const Util = {
1163
1166
  ? filters[field].split(',')
1164
1167
  : filters[field];
1165
1168
  if (Array.isArray(metadata[field])) {
1166
- return metadata[field].some((f) => Util.fieldsLike(f, filter));
1169
+ return metadata[field].some((f) => Util.fieldsLike(f, definition, filter));
1167
1170
  } else {
1171
+ let fieldName;
1172
+ if (field === 'key' && checkDefaultKeyAndName) {
1173
+ fieldName = definition.keyField;
1174
+ } else if (field === 'name' && checkDefaultKeyAndName) {
1175
+ fieldName = definition.nameField;
1176
+ }
1168
1177
  if (typeof filter === 'string') {
1169
- return Util.stringLike(metadata[field], filter);
1178
+ return Util.stringLike(metadata[fieldName || field], filter);
1170
1179
  } else if (Array.isArray(filter)) {
1171
1180
  return filter.some((f) => Util.stringLike(metadata[field], f));
1172
1181
  } else if (typeof filter === 'object') {
1173
- return Util.fieldsLike(metadata[field], filter);
1182
+ return Util.fieldsLike(metadata[field], definition, filter);
1174
1183
  }
1175
1184
  }
1176
1185
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcdev",
3
- "version": "8.0.2",
3
+ "version": "8.2.0",
4
4
  "description": "Accenture Salesforce Marketing Cloud DevTools",
5
5
  "author": "Accenture: joern.berkefeld, douglas.midgley, robert.zimmermann, maciej.barnas",
6
6
  "license": "MIT",
@@ -80,21 +80,21 @@
80
80
  "p-limit": "6.2.0",
81
81
  "prettier": "3.5.3",
82
82
  "prettier-plugin-sql": "0.19.0",
83
- "semver": "7.7.1",
83
+ "semver": "7.7.3",
84
84
  "sfmc-sdk": "2.1.2",
85
- "simple-git": "3.27.0",
85
+ "simple-git": "3.29.0",
86
86
  "toposort": "2.0.2",
87
87
  "update-notifier": "7.3.1",
88
88
  "winston": "3.17.0",
89
89
  "yargs": "17.7.2",
90
- "yocto-spinner": "0.2.2"
90
+ "yocto-spinner": "1.0.0"
91
91
  },
92
92
  "devDependencies": {
93
93
  "@eslint/js": "9.28.0",
94
94
  "@types/fs-extra": "11.0.4",
95
95
  "@types/inquirer": "9.0.7",
96
96
  "@types/mocha": "10.0.8",
97
- "@types/node": "22.15.29",
97
+ "@types/node": "24.9.1",
98
98
  "@types/yargs": "17.0.33",
99
99
  "assert": "2.1.0",
100
100
  "axios-mock-adapter": "2.0.0",
@@ -104,17 +104,17 @@
104
104
  "eslint": "9.28.0",
105
105
  "eslint-config-ssjs": "2.0.0",
106
106
  "eslint-plugin-jsdoc": "50.7.1",
107
- "eslint-plugin-mocha": "11.0.0",
107
+ "eslint-plugin-mocha": "11.2.0",
108
108
  "eslint-plugin-prettier": "5.4.1",
109
109
  "eslint-plugin-unicorn": "59.0.1",
110
- "fast-xml-parser": "5.2.3",
110
+ "fast-xml-parser": "5.3.0",
111
111
  "globals": "16.2.0",
112
112
  "husky": "9.1.7",
113
- "lint-staged": "15.5.1",
114
- "mocha": "11.5.0",
113
+ "lint-staged": "16.2.6",
114
+ "mocha": "11.7.4",
115
115
  "mock-fs": "5.3.0",
116
116
  "npm-run-all": "4.1.5",
117
- "prettier-eslint": "16.4.1",
117
+ "prettier-eslint": "16.4.2",
118
118
  "typescript": "5.8.3"
119
119
  },
120
120
  "optionalDependencies": {
@@ -175,5 +175,5 @@
175
175
  "verification"
176
176
  ]
177
177
  },
178
- "version": "8.0.2"
178
+ "version": "8.2.0"
179
179
  }
@@ -0,0 +1,26 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
3
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
5
+ xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
6
+ xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
7
+ xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
8
+ <soap:Header>
9
+ <wsa:Action>RetrieveResponse</wsa:Action>
10
+ <wsa:MessageID>urn:uuid:998a6923-b781-40be-abad-0506f0f97477</wsa:MessageID>
11
+ <wsa:RelatesTo>urn:uuid:a5d518cc-9bfb-45f1-a4a7-5d11cc1a8d44</wsa:RelatesTo>
12
+ <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
13
+ <wsse:Security>
14
+ <wsu:Timestamp wsu:Id="Timestamp-a6c00a2f-fcfa-4882-a72d-8b8983a8cc7e">
15
+ <wsu:Created>2025-09-05T16:29:03Z</wsu:Created>
16
+ <wsu:Expires>2025-09-05T16:34:03Z</wsu:Expires>
17
+ </wsu:Timestamp>
18
+ </wsse:Security>
19
+ </soap:Header>
20
+ <soap:Body>
21
+ <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI">
22
+ <OverallStatus>OK</OverallStatus>
23
+ <RequestID>ac40bccd-e8cd-4232-b1ee-e3cfbbfd0b89</RequestID>
24
+ </RetrieveResponseMsg>
25
+ </soap:Body>
26
+ </soap:Envelope>
@@ -13,7 +13,7 @@
13
13
  * Start: 2020-05-13 18:30:32.11-06:00 +01:00
14
14
  * End: 2079-06-06 21:00:00-06:00 +01:00
15
15
  * Timezone: W. Europe Standard Time
16
- * Recurrance: every 5 minutes until end date
16
+ * Recurrence: every 5 minutes until end date
17
17
 
18
18
  **Notifications:** _none_
19
19
 
@@ -13,7 +13,7 @@
13
13
  * Start: 2022-07-30 00:00:00 +01:00
14
14
  * End: 2022-07-30 00:00:00 +01:00
15
15
  * Timezone: W. Europe Standard Time
16
- * Recurrance: run only once
16
+ * Recurrence: run only once
17
17
 
18
18
  **Notifications:**
19
19
 
@@ -13,7 +13,7 @@
13
13
  * Start: 2022-07-30 00:00:00 +01:00
14
14
  * End: 2022-07-30 00:00:00 +01:00
15
15
  * Timezone: W. Europe Standard Time
16
- * Recurrance: run only once
16
+ * Recurrence: run only once
17
17
 
18
18
  **Notifications:**
19
19