mcdev 7.7.0 → 7.7.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/.github/ISSUE_TEMPLATE/bug.yml +1 -0
- package/boilerplate/files/eslint.config.js +98 -3
- package/boilerplate/npm-dependencies.json +1 -0
- package/lib/Builder.js +12 -6
- package/lib/Deployer.js +2 -2
- package/lib/cli.js +1 -1
- package/lib/index.js +78 -37
- package/lib/metadataTypes/DataExtension.js +1 -1
- package/lib/metadataTypes/Journey.js +30 -8
- package/lib/metadataTypes/MetadataType.js +29 -22
- package/lib/metadataTypes/definitions/Journey.definition.js +6 -0
- package/lib/util/config.js +6 -0
- package/lib/util/devops.js +1 -1
- package/lib/util/file.js +3 -3
- package/lib/util/util.js +1 -4
- package/package.json +1 -1
- package/test/mockRoot/.mcdevrc.json +1 -1
- package/test/resourceFactory.js +1 -24
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
|
|
2
|
+
import eslintPluginUnicorn from 'eslint-plugin-unicorn';
|
|
3
|
+
import globals from 'globals';
|
|
2
4
|
import jsdoc from 'eslint-plugin-jsdoc';
|
|
3
5
|
import js from '@eslint/js';
|
|
4
6
|
import sfmcSsjs from 'eslint-config-ssjs';
|
|
5
|
-
import globals from 'globals';
|
|
6
7
|
|
|
7
8
|
export default [
|
|
8
9
|
{
|
|
9
10
|
ignores: ['deploy/**/*', 'docs/**/*', 'logs/**/*', 'node_modules/**/*', 'template/**/*']
|
|
10
11
|
},
|
|
11
|
-
js.configs
|
|
12
|
+
js.configs.recommended,
|
|
12
13
|
eslintPluginPrettierRecommended,
|
|
13
14
|
jsdoc.configs['flat/recommended'],
|
|
15
|
+
eslintPluginUnicorn.configs['flat/recommended'],
|
|
14
16
|
{
|
|
15
17
|
plugins: { jsdoc },
|
|
16
18
|
rules: {
|
|
@@ -66,7 +68,7 @@ export default [
|
|
|
66
68
|
}
|
|
67
69
|
},
|
|
68
70
|
{
|
|
69
|
-
files: ['.mcdev-validations.js'],
|
|
71
|
+
files: ['lib/**.js', '.mcdev-validations.js'],
|
|
70
72
|
|
|
71
73
|
languageOptions: {
|
|
72
74
|
globals: {
|
|
@@ -76,8 +78,101 @@ export default [
|
|
|
76
78
|
ecmaVersion: 2022,
|
|
77
79
|
sourceType: 'module'
|
|
78
80
|
},
|
|
81
|
+
settings: {
|
|
82
|
+
jsdoc: {
|
|
83
|
+
mode: 'typescript',
|
|
84
|
+
|
|
85
|
+
preferredTypes: {
|
|
86
|
+
array: 'Array',
|
|
87
|
+
'array.<>': '[]',
|
|
88
|
+
'Array.<>': '[]',
|
|
89
|
+
'array<>': '[]',
|
|
90
|
+
'Array<>': '[]',
|
|
91
|
+
Object: 'object',
|
|
92
|
+
'object.<>': 'Object.<>',
|
|
93
|
+
'object<>': 'Object.<>',
|
|
94
|
+
'Object<>': 'Object.<>',
|
|
95
|
+
set: 'Set',
|
|
96
|
+
'set.<>': 'Set.<>',
|
|
97
|
+
'set<>': 'Set.<>',
|
|
98
|
+
'Set<>': 'Set.<>',
|
|
99
|
+
promise: 'Promise',
|
|
100
|
+
'promise.<>': 'Promise.<>',
|
|
101
|
+
'promise<>': 'Promise.<>',
|
|
102
|
+
'Promise<>': 'Promise.<>'
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
79
106
|
|
|
80
107
|
rules: {
|
|
108
|
+
'logical-assignment-operators': ['error', 'always'],
|
|
109
|
+
'unicorn/better-regex': 'off',
|
|
110
|
+
|
|
111
|
+
'unicorn/catch-error-name': [
|
|
112
|
+
'error',
|
|
113
|
+
{
|
|
114
|
+
name: 'ex'
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
|
|
118
|
+
'unicorn/explicit-length-check': 'off',
|
|
119
|
+
'unicorn/no-null': 'off',
|
|
120
|
+
'unicorn/prefer-module': 'off',
|
|
121
|
+
'unicorn/prevent-abbreviations': 'off',
|
|
122
|
+
'unicorn/filename-case': 'off',
|
|
123
|
+
'unicorn/no-array-callback-reference': 'off',
|
|
124
|
+
'unicorn/no-array-reduce': 'off',
|
|
125
|
+
'unicorn/no-await-expression-member': 'off',
|
|
126
|
+
'unicorn/no-hex-escape': 'off',
|
|
127
|
+
'unicorn/no-nested-ternary': 'off',
|
|
128
|
+
'unicorn/no-static-only-class': 'off',
|
|
129
|
+
'unicorn/no-unused-properties': 'warn',
|
|
130
|
+
'unicorn/numeric-separators-style': 'off',
|
|
131
|
+
'unicorn/prefer-array-some': 'off',
|
|
132
|
+
'unicorn/prefer-set-has': 'off',
|
|
133
|
+
'unicorn/prefer-spread': 'off',
|
|
134
|
+
'unicorn/prefer-string-replace-all': 'error',
|
|
135
|
+
'arrow-body-style': ['error', 'as-needed'],
|
|
136
|
+
curly: 'error',
|
|
137
|
+
|
|
138
|
+
'jsdoc/check-line-alignment': 2,
|
|
139
|
+
|
|
140
|
+
'jsdoc/require-jsdoc': [
|
|
141
|
+
'warn',
|
|
142
|
+
{
|
|
143
|
+
require: {
|
|
144
|
+
FunctionDeclaration: true,
|
|
145
|
+
MethodDefinition: true,
|
|
146
|
+
ClassDeclaration: true,
|
|
147
|
+
ArrowFunctionExpression: false,
|
|
148
|
+
FunctionExpression: true
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
|
|
153
|
+
'jsdoc/require-param-type': 'error',
|
|
154
|
+
|
|
155
|
+
'jsdoc/tag-lines': [
|
|
156
|
+
'warn',
|
|
157
|
+
'any',
|
|
158
|
+
{
|
|
159
|
+
startLines: 1
|
|
160
|
+
}
|
|
161
|
+
],
|
|
162
|
+
|
|
163
|
+
'jsdoc/no-undefined-types': 'off',
|
|
164
|
+
'jsdoc/valid-types': 'off',
|
|
165
|
+
|
|
166
|
+
'spaced-comment': [
|
|
167
|
+
'warn',
|
|
168
|
+
'always',
|
|
169
|
+
{
|
|
170
|
+
block: {
|
|
171
|
+
exceptions: ['*'],
|
|
172
|
+
balanced: true
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
],
|
|
81
176
|
'no-var': 'error',
|
|
82
177
|
'prefer-const': 'error',
|
|
83
178
|
'prettier/prettier': 'warn'
|
package/lib/Builder.js
CHANGED
|
@@ -112,8 +112,8 @@ saved
|
|
|
112
112
|
*/
|
|
113
113
|
static async buildTemplate(businessUnit, selectedType, keyArr, marketArr) {
|
|
114
114
|
const properties = await config.getProperties();
|
|
115
|
-
if (!
|
|
116
|
-
return
|
|
115
|
+
if (!properties) {
|
|
116
|
+
return;
|
|
117
117
|
}
|
|
118
118
|
if (!Util._isValidType(selectedType)) {
|
|
119
119
|
return;
|
|
@@ -198,8 +198,8 @@ saved
|
|
|
198
198
|
*/
|
|
199
199
|
static async buildDefinition(businessUnit, selectedType, nameArr, marketArr) {
|
|
200
200
|
const properties = await config.getProperties();
|
|
201
|
-
if (!
|
|
202
|
-
return
|
|
201
|
+
if (!properties) {
|
|
202
|
+
return;
|
|
203
203
|
}
|
|
204
204
|
if (!Util._isValidType(selectedType)) {
|
|
205
205
|
return;
|
|
@@ -241,8 +241,8 @@ saved
|
|
|
241
241
|
*/
|
|
242
242
|
static async buildDefinitionBulk(listName, type, nameArr) {
|
|
243
243
|
const properties = await config.getProperties();
|
|
244
|
-
if (!
|
|
245
|
-
return
|
|
244
|
+
if (!properties) {
|
|
245
|
+
return;
|
|
246
246
|
}
|
|
247
247
|
try {
|
|
248
248
|
Util.verifyMarketList(listName, properties);
|
|
@@ -301,6 +301,9 @@ saved
|
|
|
301
301
|
*/
|
|
302
302
|
static async purgeDeployFolderList(listName) {
|
|
303
303
|
const properties = await config.getProperties();
|
|
304
|
+
if (!properties) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
304
307
|
for (const businessUnit in properties.marketList[listName]) {
|
|
305
308
|
if (businessUnit === 'description') {
|
|
306
309
|
// skip, it's just a metadata on this list and not a BU
|
|
@@ -320,6 +323,9 @@ saved
|
|
|
320
323
|
*/
|
|
321
324
|
static async purgeDeployFolder(businessUnit) {
|
|
322
325
|
const properties = await config.getProperties();
|
|
326
|
+
if (!properties) {
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
323
329
|
if (!Util.isValidBU(properties, businessUnit, true)) {
|
|
324
330
|
throw new Error(`'${businessUnit}' does not exist.`);
|
|
325
331
|
}
|
package/lib/Deployer.js
CHANGED
|
@@ -71,8 +71,8 @@ class Deployer {
|
|
|
71
71
|
/** @type {Object.<string, MultiMetadataTypeMap>} */
|
|
72
72
|
const buMultiMetadataTypeMap = {};
|
|
73
73
|
const properties = await config.getProperties();
|
|
74
|
-
if (!
|
|
75
|
-
return
|
|
74
|
+
if (!properties) {
|
|
75
|
+
return;
|
|
76
76
|
}
|
|
77
77
|
const deployDirBak = properties.directories.deploy;
|
|
78
78
|
if (Util.OPTIONS.fromRetrieve) {
|
package/lib/cli.js
CHANGED
|
@@ -1372,7 +1372,7 @@ yargs(hideBin(process.argv))
|
|
|
1372
1372
|
.recommendCommands()
|
|
1373
1373
|
.wrap(yargs(hideBin(process.argv)).terminalWidth())
|
|
1374
1374
|
.epilog(
|
|
1375
|
-
'Copyright
|
|
1375
|
+
'Copyright 2025. Accenture. Get support at https://github.com/Accenture/sfmc-devtools/issues'
|
|
1376
1376
|
)
|
|
1377
1377
|
.help().argv;
|
|
1378
1378
|
|
package/lib/index.js
CHANGED
|
@@ -158,8 +158,8 @@ class Mcdev {
|
|
|
158
158
|
Util.startLogger();
|
|
159
159
|
Util.logger.info('Create Delta Package ::');
|
|
160
160
|
const properties = await config.getProperties();
|
|
161
|
-
if (!
|
|
162
|
-
return
|
|
161
|
+
if (!properties) {
|
|
162
|
+
return;
|
|
163
163
|
}
|
|
164
164
|
if (argv.commitrange) {
|
|
165
165
|
Util.logger.warn(
|
|
@@ -189,9 +189,10 @@ class Mcdev {
|
|
|
189
189
|
static async selectTypes() {
|
|
190
190
|
Util.startLogger();
|
|
191
191
|
const properties = await config.getProperties();
|
|
192
|
-
if (!
|
|
193
|
-
return
|
|
192
|
+
if (!properties) {
|
|
193
|
+
return;
|
|
194
194
|
}
|
|
195
|
+
|
|
195
196
|
await Cli.selectTypes(properties);
|
|
196
197
|
}
|
|
197
198
|
|
|
@@ -207,11 +208,11 @@ class Mcdev {
|
|
|
207
208
|
*/
|
|
208
209
|
static async upgrade() {
|
|
209
210
|
Util.startLogger();
|
|
210
|
-
const properties = await config.getProperties();
|
|
211
|
+
const properties = await config.getProperties(false, true);
|
|
211
212
|
if (!properties) {
|
|
212
|
-
|
|
213
|
-
return false;
|
|
213
|
+
return;
|
|
214
214
|
}
|
|
215
|
+
|
|
215
216
|
if ((await InitGit.initGitRepo()).status === 'error') {
|
|
216
217
|
return false;
|
|
217
218
|
}
|
|
@@ -229,9 +230,7 @@ class Mcdev {
|
|
|
229
230
|
}
|
|
230
231
|
Util.OPTIONS._welcomeMessageShown = true;
|
|
231
232
|
|
|
232
|
-
const color = Util.
|
|
233
|
-
? { reset: '', bgWhite: '', fgBlue: '' }
|
|
234
|
-
: Util.color;
|
|
233
|
+
const color = Util.color;
|
|
235
234
|
/* eslint-disable no-console */
|
|
236
235
|
if (process.env['USERDNSDOMAIN'] === 'DIR.SVC.ACCENTURE.COM') {
|
|
237
236
|
// Accenture internal message
|
|
@@ -270,9 +269,8 @@ class Mcdev {
|
|
|
270
269
|
Util.startLogger();
|
|
271
270
|
Util.logger.info('mcdev:: Retrieve');
|
|
272
271
|
const properties = await config.getProperties();
|
|
273
|
-
if (!
|
|
274
|
-
|
|
275
|
-
return null;
|
|
272
|
+
if (!properties) {
|
|
273
|
+
return;
|
|
276
274
|
}
|
|
277
275
|
|
|
278
276
|
// assume a list was passed in and check each entry's validity
|
|
@@ -398,9 +396,10 @@ class Mcdev {
|
|
|
398
396
|
selectedTypesArr = structuredClone(selectedTypesArr);
|
|
399
397
|
|
|
400
398
|
const properties = await config.getProperties();
|
|
401
|
-
if (!
|
|
402
|
-
return
|
|
399
|
+
if (!properties) {
|
|
400
|
+
return;
|
|
403
401
|
}
|
|
402
|
+
|
|
404
403
|
const buObject = await Cli.getCredentialObject(
|
|
405
404
|
properties,
|
|
406
405
|
cred === null ? null : cred + '/' + bu,
|
|
@@ -559,9 +558,10 @@ class Mcdev {
|
|
|
559
558
|
Util.startLogger();
|
|
560
559
|
Util.logger.info('mcdev:: Load BUs');
|
|
561
560
|
const properties = await config.getProperties();
|
|
562
|
-
if (!
|
|
563
|
-
return
|
|
561
|
+
if (!properties) {
|
|
562
|
+
return;
|
|
564
563
|
}
|
|
564
|
+
|
|
565
565
|
const buObject = await Cli.getCredentialObject(properties, credentialsName, true);
|
|
566
566
|
if (buObject !== null) {
|
|
567
567
|
BuHelper.refreshBUProperties(properties, buObject.credential);
|
|
@@ -579,9 +579,10 @@ class Mcdev {
|
|
|
579
579
|
Util.startLogger();
|
|
580
580
|
Util.logger.info('mcdev:: Document');
|
|
581
581
|
const properties = await config.getProperties();
|
|
582
|
-
if (!
|
|
583
|
-
return
|
|
582
|
+
if (!properties) {
|
|
583
|
+
return;
|
|
584
584
|
}
|
|
585
|
+
|
|
585
586
|
if (type && !MetadataTypeInfo[type]) {
|
|
586
587
|
Util.logger.error(`:: '${type}' is not a valid metadata type`);
|
|
587
588
|
return;
|
|
@@ -640,9 +641,10 @@ class Mcdev {
|
|
|
640
641
|
}
|
|
641
642
|
}
|
|
642
643
|
const properties = await config.getProperties();
|
|
643
|
-
if (!
|
|
644
|
-
return
|
|
644
|
+
if (!properties) {
|
|
645
|
+
return;
|
|
645
646
|
}
|
|
647
|
+
|
|
646
648
|
const buObject = await Cli.getCredentialObject(properties, businessUnit);
|
|
647
649
|
if (!buObject) {
|
|
648
650
|
return;
|
|
@@ -711,9 +713,10 @@ class Mcdev {
|
|
|
711
713
|
return;
|
|
712
714
|
}
|
|
713
715
|
const properties = await config.getProperties();
|
|
714
|
-
if (!
|
|
715
|
-
return
|
|
716
|
+
if (!properties) {
|
|
717
|
+
return;
|
|
716
718
|
}
|
|
719
|
+
|
|
717
720
|
const buObject = await Cli.getCredentialObject(properties, businessUnit);
|
|
718
721
|
if (buObject !== null) {
|
|
719
722
|
try {
|
|
@@ -760,9 +763,10 @@ class Mcdev {
|
|
|
760
763
|
Util.startLogger();
|
|
761
764
|
Util.logger.info('mcdev:: describe SOAP');
|
|
762
765
|
const properties = await config.getProperties();
|
|
763
|
-
if (!
|
|
764
|
-
return
|
|
766
|
+
if (!properties) {
|
|
767
|
+
return;
|
|
765
768
|
}
|
|
769
|
+
|
|
766
770
|
const credential = Object.keys(properties.credentials)[0];
|
|
767
771
|
businessUnit ||=
|
|
768
772
|
credential + '/' + Object.keys(properties.credentials[credential].businessUnits)[0];
|
|
@@ -807,9 +811,10 @@ class Mcdev {
|
|
|
807
811
|
static async badKeys(businessUnit) {
|
|
808
812
|
Util.startLogger();
|
|
809
813
|
const properties = await config.getProperties();
|
|
810
|
-
if (!
|
|
811
|
-
return
|
|
814
|
+
if (!properties) {
|
|
815
|
+
return;
|
|
812
816
|
}
|
|
817
|
+
|
|
813
818
|
const buObject = await Cli.getCredentialObject(properties, businessUnit);
|
|
814
819
|
if (buObject !== null) {
|
|
815
820
|
Util.logger.info('Gathering list of Name<>External Key mismatches (bad keys)');
|
|
@@ -884,9 +889,10 @@ class Mcdev {
|
|
|
884
889
|
'mcdev:: [DEPRECATED] Retrieve as Template [DEPRECATED] - use "retrieve" + "buildTemplate" instead'
|
|
885
890
|
);
|
|
886
891
|
const properties = await config.getProperties();
|
|
887
|
-
if (!
|
|
888
|
-
return
|
|
892
|
+
if (!properties) {
|
|
893
|
+
return;
|
|
889
894
|
}
|
|
895
|
+
|
|
890
896
|
if (!Util._isValidType(selectedType)) {
|
|
891
897
|
return;
|
|
892
898
|
}
|
|
@@ -924,6 +930,10 @@ class Mcdev {
|
|
|
924
930
|
}
|
|
925
931
|
const initialAssetNumber = typeKeyList['asset']?.length || 0;
|
|
926
932
|
const properties = await config.getProperties();
|
|
933
|
+
if (!properties) {
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
|
|
927
937
|
const buObject = await Cli.getCredentialObject(properties, businessUnit);
|
|
928
938
|
Util.logger.info(
|
|
929
939
|
'Searching for additional dependencies that were linked via ContentBlockByKey, ContentBlockByName and ContentBlockById'
|
|
@@ -1032,6 +1042,9 @@ class Mcdev {
|
|
|
1032
1042
|
const initiallySelectedTypesArr = Object.keys(typeKeyList);
|
|
1033
1043
|
|
|
1034
1044
|
const properties = await config.getProperties();
|
|
1045
|
+
if (!properties) {
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1035
1048
|
const buObject = await Cli.getCredentialObject(properties, businessUnit);
|
|
1036
1049
|
for (const type of initiallySelectedTypesArr) {
|
|
1037
1050
|
MetadataTypeInfo[type].properties = properties;
|
|
@@ -1138,6 +1151,9 @@ class Mcdev {
|
|
|
1138
1151
|
|
|
1139
1152
|
// redirect templates to temporary folder when executed via build()
|
|
1140
1153
|
const properties = await config.getProperties();
|
|
1154
|
+
if (!properties) {
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1141
1157
|
const templateDirBackup = properties.directories.template;
|
|
1142
1158
|
properties.directories.template = '.mcdev/template/';
|
|
1143
1159
|
|
|
@@ -1145,7 +1161,6 @@ class Mcdev {
|
|
|
1145
1161
|
await this.buildTemplate(businessUnitTemplate, typeKeyCombo, null, marketTemplate);
|
|
1146
1162
|
|
|
1147
1163
|
if (typeof Util.OPTIONS.purge !== 'boolean') {
|
|
1148
|
-
const properties = await config.getProperties();
|
|
1149
1164
|
// deploy folder is in targets for definition creation
|
|
1150
1165
|
// recommend to purge their content first
|
|
1151
1166
|
Util.OPTIONS.purge = await confirm({
|
|
@@ -1190,6 +1205,9 @@ class Mcdev {
|
|
|
1190
1205
|
Util.startLogger();
|
|
1191
1206
|
Util.logger.info('mcdev:: Build Template from retrieved files');
|
|
1192
1207
|
const properties = await config.getProperties();
|
|
1208
|
+
if (!properties) {
|
|
1209
|
+
return;
|
|
1210
|
+
}
|
|
1193
1211
|
const buObject = await Cli.getCredentialObject(properties, businessUnit);
|
|
1194
1212
|
if (!Util.checkMarketList(marketArr, properties)) {
|
|
1195
1213
|
return;
|
|
@@ -1317,6 +1335,9 @@ class Mcdev {
|
|
|
1317
1335
|
Util.startLogger();
|
|
1318
1336
|
Util.logger.info('mcdev:: Build Definition from Template');
|
|
1319
1337
|
const properties = await config.getProperties();
|
|
1338
|
+
if (!properties) {
|
|
1339
|
+
return;
|
|
1340
|
+
}
|
|
1320
1341
|
if (!Util.checkMarketList(marketArr, properties)) {
|
|
1321
1342
|
return;
|
|
1322
1343
|
}
|
|
@@ -1331,7 +1352,7 @@ class Mcdev {
|
|
|
1331
1352
|
|
|
1332
1353
|
if (Util.OPTIONS.purge) {
|
|
1333
1354
|
const buObject = await Cli.getCredentialObject(properties, businessUnit);
|
|
1334
|
-
Builder.purgeDeployFolder(buObject.credential + '/' + buObject.businessUnit);
|
|
1355
|
+
await Builder.purgeDeployFolder(buObject.credential + '/' + buObject.businessUnit);
|
|
1335
1356
|
} else {
|
|
1336
1357
|
Util.logger.info(` ☇ skipping purge of folder`);
|
|
1337
1358
|
}
|
|
@@ -1365,6 +1386,9 @@ class Mcdev {
|
|
|
1365
1386
|
Util.logger.info('mcdev:: Build Definition from Template Bulk');
|
|
1366
1387
|
|
|
1367
1388
|
const properties = await config.getProperties();
|
|
1389
|
+
if (!properties) {
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1368
1392
|
try {
|
|
1369
1393
|
Util.verifyMarketList(listName, properties);
|
|
1370
1394
|
} catch (ex) {
|
|
@@ -1380,7 +1404,7 @@ class Mcdev {
|
|
|
1380
1404
|
return;
|
|
1381
1405
|
}
|
|
1382
1406
|
if (Util.OPTIONS.purge) {
|
|
1383
|
-
Builder.purgeDeployFolderList(listName);
|
|
1407
|
+
await Builder.purgeDeployFolderList(listName);
|
|
1384
1408
|
} else {
|
|
1385
1409
|
Util.logger.info(` ☇ skipping purge of folder`);
|
|
1386
1410
|
}
|
|
@@ -1406,8 +1430,8 @@ class Mcdev {
|
|
|
1406
1430
|
Util.startLogger();
|
|
1407
1431
|
Util.logger.info('mcdev:: getFilesToCommit');
|
|
1408
1432
|
const properties = await config.getProperties();
|
|
1409
|
-
if (!
|
|
1410
|
-
return
|
|
1433
|
+
if (!properties) {
|
|
1434
|
+
return;
|
|
1411
1435
|
}
|
|
1412
1436
|
if (!Util._isValidType(selectedType)) {
|
|
1413
1437
|
return;
|
|
@@ -1539,6 +1563,9 @@ class Mcdev {
|
|
|
1539
1563
|
this.setOptions({ referenceFrom, referenceTo });
|
|
1540
1564
|
|
|
1541
1565
|
const properties = await config.getProperties();
|
|
1566
|
+
if (!properties) {
|
|
1567
|
+
return;
|
|
1568
|
+
}
|
|
1542
1569
|
if (!Util.isValidBU(properties, businessUnit)) {
|
|
1543
1570
|
return;
|
|
1544
1571
|
}
|
|
@@ -1596,6 +1623,9 @@ class Mcdev {
|
|
|
1596
1623
|
*/
|
|
1597
1624
|
static async fixKeys(businessUnit, selectedTypes, keys) {
|
|
1598
1625
|
const properties = await config.getProperties();
|
|
1626
|
+
if (!properties) {
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1599
1629
|
// make sure validation rules dont keep us from fixing the keys
|
|
1600
1630
|
this.setOptions({ skipValidation: true });
|
|
1601
1631
|
let reRetrieveAll = false;
|
|
@@ -1797,9 +1827,8 @@ class Mcdev {
|
|
|
1797
1827
|
return resultObj;
|
|
1798
1828
|
}
|
|
1799
1829
|
const properties = await config.getProperties();
|
|
1800
|
-
if (!
|
|
1801
|
-
|
|
1802
|
-
return resultObj;
|
|
1830
|
+
if (!properties) {
|
|
1831
|
+
return;
|
|
1803
1832
|
}
|
|
1804
1833
|
for (const selectedType of selectedTypesArr || Object.keys(selectedTypesObj)) {
|
|
1805
1834
|
Util.logger.info(`mcdev:: ${methodName} ${selectedType}`);
|
|
@@ -1924,6 +1953,9 @@ class Mcdev {
|
|
|
1924
1953
|
*/
|
|
1925
1954
|
static async #runOnBU(methodName, cred, bu, type, keyArr) {
|
|
1926
1955
|
const properties = await config.getProperties();
|
|
1956
|
+
if (!properties) {
|
|
1957
|
+
return;
|
|
1958
|
+
}
|
|
1927
1959
|
const resultArr = [];
|
|
1928
1960
|
const buObject = await Cli.getCredentialObject(
|
|
1929
1961
|
properties,
|
|
@@ -1983,6 +2015,9 @@ class Mcdev {
|
|
|
1983
2015
|
*/
|
|
1984
2016
|
static async #retrieveKeysWithLike(selectedType, buObject) {
|
|
1985
2017
|
const properties = await config.getProperties();
|
|
2018
|
+
if (!properties) {
|
|
2019
|
+
return;
|
|
2020
|
+
}
|
|
1986
2021
|
|
|
1987
2022
|
// cache depenencies
|
|
1988
2023
|
const deployOrder = Util.getMetadataHierachy([selectedType]);
|
|
@@ -2050,6 +2085,9 @@ class Mcdev {
|
|
|
2050
2085
|
*/
|
|
2051
2086
|
static async #fixKeys(cred, bu, type, keyArr) {
|
|
2052
2087
|
const properties = await config.getProperties();
|
|
2088
|
+
if (!properties) {
|
|
2089
|
+
return;
|
|
2090
|
+
}
|
|
2053
2091
|
let actuallyFixedKeys = [];
|
|
2054
2092
|
const resultArr = [];
|
|
2055
2093
|
|
|
@@ -2133,6 +2171,9 @@ class Mcdev {
|
|
|
2133
2171
|
*/
|
|
2134
2172
|
static async #replaceCbReference(cred, bu, type, keyArr) {
|
|
2135
2173
|
const properties = await config.getProperties();
|
|
2174
|
+
if (!properties) {
|
|
2175
|
+
return;
|
|
2176
|
+
}
|
|
2136
2177
|
let updatedKeys = [];
|
|
2137
2178
|
const resultArr = [];
|
|
2138
2179
|
|
|
@@ -402,7 +402,7 @@ class DataExtension extends MetadataType {
|
|
|
402
402
|
}
|
|
403
403
|
|
|
404
404
|
// find all shared data extensions
|
|
405
|
-
if (!this.deployedSharedKeys
|
|
405
|
+
if (!this.deployedSharedKeys?.length) {
|
|
406
406
|
Util.logger.debug(
|
|
407
407
|
`Skipping fixShared logic because no Shared Data Extensions were updated`
|
|
408
408
|
);
|
|
@@ -290,25 +290,42 @@ class Journey extends MetadataType {
|
|
|
290
290
|
);
|
|
291
291
|
// break;
|
|
292
292
|
}
|
|
293
|
-
|
|
294
|
-
// Quicksend
|
|
295
|
-
const
|
|
293
|
+
case 'Quicksend': {
|
|
294
|
+
// Quicksend doesnt have versions
|
|
295
|
+
const isDeleted = await super.deleteByKeyREST(
|
|
296
|
+
'/interaction/v1/interactions/' + id,
|
|
297
|
+
key,
|
|
298
|
+
false
|
|
299
|
+
);
|
|
300
|
+
return isDeleted;
|
|
301
|
+
}
|
|
302
|
+
case 'Transactional': {
|
|
303
|
+
// Transactional dont have versions
|
|
304
|
+
const isDeleted = await super.deleteByKeyREST(
|
|
296
305
|
'/interaction/v1/interactions/' + id,
|
|
297
306
|
key,
|
|
298
307
|
false
|
|
299
308
|
);
|
|
300
|
-
|
|
309
|
+
const transactionalEmailKey =
|
|
310
|
+
cachedJourney.activities[0]?.configurationArguments?.triggeredSendKey;
|
|
311
|
+
if (isDeleted) {
|
|
301
312
|
const msg = [];
|
|
302
313
|
if (cachedJourney.activities[0]?.configurationArguments?.triggeredSendKey) {
|
|
303
314
|
msg.push(
|
|
304
315
|
`transactionalEmail "${cachedJourney.activities[0].configurationArguments.triggeredSendKey}"`
|
|
305
316
|
);
|
|
306
317
|
}
|
|
307
|
-
if (msg.length) {
|
|
308
|
-
Util.logger.info(` - Remember to also delete linked ${msg.join(' and ')}`);
|
|
309
|
-
}
|
|
310
318
|
}
|
|
311
|
-
|
|
319
|
+
if (isDeleted && transactionalEmailKey) {
|
|
320
|
+
Util.logger.info(
|
|
321
|
+
` - deleted ${TransactionalEmail.definition.type}: ${transactionalEmailKey} (SFMC auto-deletes the related transactionalEmail of ${this.definition.type} ${key})`
|
|
322
|
+
);
|
|
323
|
+
TransactionalEmail.buObject = this.buObject;
|
|
324
|
+
TransactionalEmail.properties = this.properties;
|
|
325
|
+
TransactionalEmail.client = this.client;
|
|
326
|
+
TransactionalEmail.postDeleteTasks(transactionalEmailKey);
|
|
327
|
+
}
|
|
328
|
+
return isDeleted;
|
|
312
329
|
}
|
|
313
330
|
}
|
|
314
331
|
}
|
|
@@ -416,6 +433,10 @@ class Journey extends MetadataType {
|
|
|
416
433
|
*/
|
|
417
434
|
static async postRetrieveTasks(metadata) {
|
|
418
435
|
// folder
|
|
436
|
+
if (metadata.r__folder_Path && Util.OPTIONS.publish) {
|
|
437
|
+
// if we re-retrieve this as part of deploy with --publish then the cached version will already have been processed
|
|
438
|
+
return metadata;
|
|
439
|
+
}
|
|
419
440
|
super.setFolderPath(metadata);
|
|
420
441
|
|
|
421
442
|
switch (metadata.definitionType) {
|
|
@@ -2288,6 +2309,7 @@ class Journey extends MetadataType {
|
|
|
2288
2309
|
toBeRetrievedTypes.map((item) => item + 's').join(', ')
|
|
2289
2310
|
);
|
|
2290
2311
|
await retriever.retrieve(toBeRetrievedTypes, eventTransEmailCombo);
|
|
2312
|
+
// TODO find r__automation_key in events and retrieve these automations as well
|
|
2291
2313
|
}
|
|
2292
2314
|
}
|
|
2293
2315
|
} catch (ex) {
|
|
@@ -2857,17 +2857,17 @@ class MetadataType {
|
|
|
2857
2857
|
* Gets executed before deploying metadata
|
|
2858
2858
|
*
|
|
2859
2859
|
* @param {'retrieve'|'buildDefinition'|'deploy'} method used to select the right config
|
|
2860
|
-
* @param {MetadataTypeItem | CodeExtractItem}
|
|
2860
|
+
* @param {MetadataTypeItem | CodeExtractItem} originalItem a single metadata item
|
|
2861
2861
|
* @param {string} targetDir folder where files for deployment are stored
|
|
2862
2862
|
* @returns {Promise.<MetadataTypeItem | CodeExtractItem>} Promise of a single metadata item
|
|
2863
2863
|
*/
|
|
2864
|
-
static async validation(method,
|
|
2864
|
+
static async validation(method, originalItem, targetDir) {
|
|
2865
2865
|
if (!this.properties.options?.validation?.[method]) {
|
|
2866
|
-
return
|
|
2866
|
+
return originalItem;
|
|
2867
2867
|
}
|
|
2868
2868
|
// if the fix parameter was set, allow validation rules to override the metadata
|
|
2869
|
-
|
|
2870
|
-
item = Util.OPTIONS.fix ?
|
|
2869
|
+
/** @type {MetadataTypeItem | CodeExtractItem} */
|
|
2870
|
+
let item = Util.OPTIONS.fix ? originalItem : structuredClone(originalItem);
|
|
2871
2871
|
/** @type {MetadataTypeItem} */
|
|
2872
2872
|
const metadataItem = item.json && item.codeArr ? item.json : item;
|
|
2873
2873
|
const codeArr = item.codeArr || null;
|
|
@@ -2902,36 +2902,43 @@ class MetadataType {
|
|
|
2902
2902
|
|
|
2903
2903
|
// run validation rules
|
|
2904
2904
|
const warnings = [];
|
|
2905
|
+
let fixed = false;
|
|
2905
2906
|
for (const rule of Object.keys(validationRules)) {
|
|
2906
2907
|
if (
|
|
2907
2908
|
validationConfig[rule] &&
|
|
2908
2909
|
validationConfig[rule] !== 'off' &&
|
|
2909
2910
|
!this.definition.skipValidation?.[rule]
|
|
2910
2911
|
) {
|
|
2911
|
-
const
|
|
2912
|
+
const mode = Util.OPTIONS.fix ? 'fix' : validationConfig[rule];
|
|
2913
|
+
const passed = await validationRules[rule].passed(mode);
|
|
2914
|
+
if (mode === 'fix') {
|
|
2915
|
+
// potentially fixed really
|
|
2916
|
+
fixed = true;
|
|
2917
|
+
}
|
|
2912
2918
|
if (!passed) {
|
|
2913
|
-
if (
|
|
2914
|
-
if (
|
|
2915
|
-
throw new Error(validationRules[rule].failedMsg);
|
|
2916
|
-
} else if (Util.OPTIONS.fix && passed === null) {
|
|
2917
|
-
// ensure this item no longer exists outside of the validation rule
|
|
2918
|
-
item = null;
|
|
2919
|
-
warnings.push(
|
|
2920
|
-
` ☇ filtered item via validation rule --fix: ` +
|
|
2921
|
-
validationRules[rule].failedMsg
|
|
2922
|
-
);
|
|
2923
|
-
}
|
|
2924
|
-
} else if (Util.OPTIONS.skipValidation || validationConfig[rule] === 'warn') {
|
|
2925
|
-
if (!Util.OPTIONS.fix || passed === false) {
|
|
2919
|
+
if (mode === 'fix') {
|
|
2920
|
+
if (passed === false) {
|
|
2926
2921
|
warnings.push(validationRules[rule].failedMsg);
|
|
2927
|
-
} else if (
|
|
2922
|
+
} else if (passed === null) {
|
|
2928
2923
|
// ensure this item no longer exists outside of the validation rule
|
|
2929
2924
|
item = null;
|
|
2930
2925
|
warnings.push(
|
|
2931
|
-
` ☇ filtered item via validation rule
|
|
2926
|
+
` ☇ filtered item via validation rule fix: ` +
|
|
2932
2927
|
validationRules[rule].failedMsg
|
|
2933
2928
|
);
|
|
2929
|
+
break;
|
|
2934
2930
|
}
|
|
2931
|
+
} else if (
|
|
2932
|
+
!Util.OPTIONS.skipValidation &&
|
|
2933
|
+
validationConfig[rule] === 'error' &&
|
|
2934
|
+
passed === false
|
|
2935
|
+
) {
|
|
2936
|
+
throw new Error(validationRules[rule].failedMsg);
|
|
2937
|
+
} else if (
|
|
2938
|
+
(Util.OPTIONS.skipValidation || validationConfig[rule] === 'warn') &&
|
|
2939
|
+
passed === false
|
|
2940
|
+
) {
|
|
2941
|
+
warnings.push(validationRules[rule].failedMsg);
|
|
2935
2942
|
}
|
|
2936
2943
|
}
|
|
2937
2944
|
}
|
|
@@ -2943,7 +2950,7 @@ class MetadataType {
|
|
|
2943
2950
|
);
|
|
2944
2951
|
}
|
|
2945
2952
|
// only return "fixed" item if --fix is set, otherwise return the original item
|
|
2946
|
-
return Util.OPTIONS.fix ? item : originalItem;
|
|
2953
|
+
return Util.OPTIONS.fix || fixed ? item : originalItem;
|
|
2947
2954
|
}
|
|
2948
2955
|
}
|
|
2949
2956
|
|
|
@@ -990,6 +990,12 @@ export default {
|
|
|
990
990
|
retrieving: true,
|
|
991
991
|
template: true,
|
|
992
992
|
},
|
|
993
|
+
'triggers[].metaData.scheduleState': {
|
|
994
|
+
isCreateable: true,
|
|
995
|
+
isUpdateable: true,
|
|
996
|
+
retrieving: true,
|
|
997
|
+
template: true,
|
|
998
|
+
},
|
|
993
999
|
version: {
|
|
994
1000
|
isCreateable: false,
|
|
995
1001
|
isUpdateable: true,
|
package/lib/util/config.js
CHANGED
|
@@ -46,6 +46,9 @@ const config = {
|
|
|
46
46
|
if (await File.pathExists(Util.configFileName)) {
|
|
47
47
|
try {
|
|
48
48
|
config.properties = await File.readJSON(Util.configFileName);
|
|
49
|
+
if (!isInit && !(await this.checkProperties(config.properties, silent))) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
49
52
|
} catch (ex) {
|
|
50
53
|
Util.logger.error(`${ex.code}: ${ex.message}`);
|
|
51
54
|
return;
|
|
@@ -94,6 +97,9 @@ const config = {
|
|
|
94
97
|
);
|
|
95
98
|
return;
|
|
96
99
|
}
|
|
100
|
+
} else if (!silent && !isInit) {
|
|
101
|
+
Util.logger.error(`Could not find ${Util.configFileName} in ${process.cwd()}.`);
|
|
102
|
+
Util.logger.error(`Run 'mcdev init' to initialize your project.\n`);
|
|
97
103
|
}
|
|
98
104
|
return config.properties;
|
|
99
105
|
},
|
package/lib/util/devops.js
CHANGED
|
@@ -450,7 +450,7 @@ const DevOps = {
|
|
|
450
450
|
// if --purge was defined and there is more than one source-target mapping, execute the purge up front to avoid deleting the package that was created by a prior mapping in this same run
|
|
451
451
|
for (const sourceMlName of sourceMarketListArr) {
|
|
452
452
|
/** @type {string} */
|
|
453
|
-
Builder.purgeDeployFolderList(sourceTargetMapping[sourceMlName]);
|
|
453
|
+
await Builder.purgeDeployFolderList(sourceTargetMapping[sourceMlName]);
|
|
454
454
|
}
|
|
455
455
|
Util.OPTIONS.purge = false;
|
|
456
456
|
}
|
package/lib/util/file.js
CHANGED
|
@@ -196,7 +196,7 @@ const File = {
|
|
|
196
196
|
let formatted;
|
|
197
197
|
const properties = await config.getProperties();
|
|
198
198
|
if (
|
|
199
|
-
(properties
|
|
199
|
+
(properties?.options?.formatOnSave && Util.OPTIONS.format === undefined) ||
|
|
200
200
|
Util.OPTIONS.format
|
|
201
201
|
) {
|
|
202
202
|
formatted =
|
|
@@ -239,7 +239,7 @@ const File = {
|
|
|
239
239
|
beautify_beautyAmp: async function (content, formatHTML = true) {
|
|
240
240
|
const properties = await config.getProperties();
|
|
241
241
|
if (
|
|
242
|
-
(properties
|
|
242
|
+
(properties?.options?.formatOnSave && Util.OPTIONS.format === undefined) ||
|
|
243
243
|
Util.OPTIONS.format
|
|
244
244
|
) {
|
|
245
245
|
// logs trough console only for the moment.
|
|
@@ -338,7 +338,7 @@ const File = {
|
|
|
338
338
|
|
|
339
339
|
formatted = await prettier.format(content, FileFs.prettierConfig);
|
|
340
340
|
} catch (ex) {
|
|
341
|
-
if (properties
|
|
341
|
+
if (properties?.options?.formatErrorLog) {
|
|
342
342
|
// save prettier errror into log file
|
|
343
343
|
// Note: we have to filter color codes from prettier's error message before saving it to file
|
|
344
344
|
/* eslint-disable no-control-regex */
|
package/lib/util/util.js
CHANGED
|
@@ -39,9 +39,6 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
39
39
|
* Util that contains logger and simple util methods
|
|
40
40
|
*/
|
|
41
41
|
export const Util = {
|
|
42
|
-
isRunViaVSCodeExtension:
|
|
43
|
-
process.env.VSCODE_AMD_ENTRYPOINT === 'vs/workbench/api/node/extensionHostProcess' || // run via VSCode extension
|
|
44
|
-
process.env.VSCODE_CRASH_REPORTER_PROCESS_TYPE === 'extensionHost',
|
|
45
42
|
authFileName: '.mcdev-auth.json',
|
|
46
43
|
boilerplateDirectory: '../../boilerplate',
|
|
47
44
|
configFileName: '.mcdevrc.json',
|
|
@@ -359,8 +356,8 @@ export const Util = {
|
|
|
359
356
|
// debug: 5,
|
|
360
357
|
// silly: 6
|
|
361
358
|
// }
|
|
359
|
+
|
|
362
360
|
if (
|
|
363
|
-
this.isRunViaVSCodeExtension || // run via VSCode extension
|
|
364
361
|
process.env.FORK_PROCESS_ID || // run via Git-Fork
|
|
365
362
|
process.env.PATH.toLowerCase().includes('sourcetree') // run via Atlassian SourceTree
|
|
366
363
|
) {
|
package/package.json
CHANGED
package/test/resourceFactory.js
CHANGED
|
@@ -12,30 +12,7 @@ const projectRoot = projectRootHelper.join(path.sep) + path.sep;
|
|
|
12
12
|
const parser = new XMLParser();
|
|
13
13
|
const attributeParser = new XMLParser({ ignoreAttributes: false });
|
|
14
14
|
/** @type {typeof Util.color} */
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
/* eslint-disable unicorn/prefer-ternary */
|
|
18
|
-
if (Util.isRunViaVSCodeExtension) {
|
|
19
|
-
// when we execute the test in a VSCode extension host, we don't want CLI color codes.
|
|
20
|
-
// @ts-expect-error hacky way to get rid of colors - ts doesn't appreciate the hack
|
|
21
|
-
color = new Proxy(
|
|
22
|
-
{},
|
|
23
|
-
{
|
|
24
|
-
/**
|
|
25
|
-
* catch-all for color
|
|
26
|
-
*
|
|
27
|
-
* @returns {string} empty string
|
|
28
|
-
*/
|
|
29
|
-
get() {
|
|
30
|
-
return '';
|
|
31
|
-
},
|
|
32
|
-
}
|
|
33
|
-
);
|
|
34
|
-
} else {
|
|
35
|
-
// test is executed directly in a command prompt. Use colors.
|
|
36
|
-
color = Util.color;
|
|
37
|
-
}
|
|
38
|
-
/* eslint-enable unicorn/prefer-ternary */
|
|
15
|
+
const color = Util.color;
|
|
39
16
|
|
|
40
17
|
export const tWarn = `${color.bgYellow}${color.fgBlack}TEST-WARNING${color.reset}`;
|
|
41
18
|
export const tError = `${color.bgRed}${color.fgBlack}TEST-ERROR${color.reset}`;
|