mcdev 5.0.1 → 5.0.2
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 +1 -0
- package/.github/ISSUE_TEMPLATE/bug.yml +1 -0
- package/.husky/commit-msg +1 -1
- package/.husky/post-checkout +34 -3
- package/.husky/post-merge +21 -0
- package/.husky/pre-commit +1 -0
- package/docs/dist/documentation.md +60 -15
- package/lib/Deployer.js +0 -1
- package/lib/cli.js +8 -8
- package/lib/index.js +2 -1
- package/lib/metadataTypes/Asset.js +4 -2
- package/lib/metadataTypes/Automation.js +39 -28
- package/lib/metadataTypes/DataExtension.js +1 -3
- package/lib/metadataTypes/DataExtensionField.js +5 -5
- package/lib/metadataTypes/Journey.js +11 -10
- package/lib/metadataTypes/MetadataType.js +34 -7
- package/lib/metadataTypes/MobileKeyword.js +165 -20
- package/lib/metadataTypes/MobileMessage.js +20 -28
- package/lib/metadataTypes/Role.js +2 -3
- package/lib/metadataTypes/TransactionalSMS.js +5 -5
- package/lib/metadataTypes/User.js +3 -17
- package/lib/metadataTypes/definitions/MobileKeyword.definition.js +19 -7
- package/lib/metadataTypes/definitions/MobileMessage.definition.js +50 -8
- package/lib/metadataTypes/definitions/User.definition.js +1 -0
- package/lib/util/auth.js +4 -1
- package/lib/util/cli.js +1 -1
- package/lib/util/file.js +5 -3
- package/lib/util/util.js +1 -0
- package/package.json +9 -9
- package/test/mockRoot/.mcdevrc.json +3 -1
- package/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/{testNew_keyword.mobileKeyword-meta.json → 4912312345678.TESTNEW_KEYWORD.mobileKeyword-meta.json} +1 -4
- package/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/{testNew_keyword_blocked.mobileKeyword-meta.json → 4912312345678.TESTNEW_KEYWORD_BLOCKED.mobileKeyword-meta.json} +1 -4
- package/test/mockRoot/deploy/testInstance/testBU/transactionalSMS/testExisting_tsms.transactionalSMS-meta.json +1 -1
- package/test/mockRoot/deploy/testInstance/testBU/transactionalSMS/testNew_tsms.transactionalSMS-meta.json +1 -1
- package/test/resources/1111111/user/retrieve-expected.md +19 -0
- package/test/resources/9999999/dataExtension/retrieve-expected.md +18 -0
- package/test/resources/9999999/journey/build-expected.json +1 -1
- package/test/resources/9999999/journey/get-expected.json +1 -1
- package/test/resources/9999999/journey/put-expected.json +1 -1
- package/test/resources/9999999/journey/template-expected.json +1 -1
- package/test/resources/9999999/legacy/v1/beta/mobile/keyword/NXV4ZFMwTEFwRVczd3RaLUF5X3p5dzo4Njow/get-response.json +1 -1
- package/test/resources/9999999/legacy/v1/beta/mobile/keyword/get-response.json +1 -1
- package/test/resources/9999999/legacy/v1/beta/mobile/message/NTIzOjc4OjA/get-response.json +1 -1
- package/test/resources/9999999/legacy/v1/beta/mobile/message/get-response.json +1 -1
- package/test/resources/9999999/messaging/v1/sms/definitions/post-response.json +1 -1
- package/test/resources/9999999/messaging/v1/sms/definitions/testExisting_tsms/get-response.json +1 -1
- package/test/resources/9999999/messaging/v1/sms/definitions/testExisting_tsms/patch-response.json +1 -1
- package/test/resources/9999999/mobileKeyword/build-expected.json +1 -4
- package/test/resources/9999999/mobileKeyword/get-expected.json +1 -4
- package/test/resources/9999999/mobileKeyword/post-create-expected.json +1 -4
- package/test/resources/9999999/mobileKeyword/template-expected.json +1 -4
- package/test/resources/9999999/query/build-expected.sql +1 -1
- package/test/resources/9999999/query/get-expected.sql +1 -1
- package/test/resources/9999999/query/patch-expected.sql +1 -1
- package/test/resources/9999999/query/post-expected.sql +1 -1
- package/test/resources/9999999/query/template-expected.sql +1 -1
- package/test/resources/9999999/transactionalSMS/build-expected.json +1 -1
- package/test/resources/9999999/transactionalSMS/get-expected.json +1 -1
- package/test/resources/9999999/transactionalSMS/patch-expected.json +1 -1
- package/test/resources/9999999/transactionalSMS/post-expected.json +1 -1
- package/test/resources/9999999/transactionalSMS/template-expected.json +1 -1
- package/test/type.dataExtension.test.js +13 -1
- package/test/type.mobileKeyword.test.js +57 -19
- package/test/type.user.test.js +30 -1
- package/test/utils.js +10 -0
- /package/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/{testNew_keyword.mobileKeyword-meta.amp → 4912312345678.TESTNEW_KEYWORD.mobileKeyword-meta.amp} +0 -0
- /package/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/{testNew_keyword_blocked.mobileKeyword-meta.amp → 4912312345678.TESTNEW_KEYWORD_BLOCKED.mobileKeyword-meta.amp} +0 -0
|
@@ -24,14 +24,12 @@ class MobileKeyword extends MetadataType {
|
|
|
24
24
|
*/
|
|
25
25
|
static retrieve(retrieveDir, _, __, key) {
|
|
26
26
|
try {
|
|
27
|
+
let queryParams;
|
|
28
|
+
[key, queryParams] = this.#getRetrieveKeyAndUrl(key);
|
|
29
|
+
|
|
27
30
|
return super.retrieveREST(
|
|
28
31
|
retrieveDir,
|
|
29
|
-
'/legacy/v1/beta/mobile/keyword/' +
|
|
30
|
-
(key
|
|
31
|
-
? key.startsWith('id:')
|
|
32
|
-
? key.slice(3)
|
|
33
|
-
: `?view=simple&$where=keyword%20eq%20%27${key}%27%20`
|
|
34
|
-
: '?view=simple'),
|
|
32
|
+
'/legacy/v1/beta/mobile/keyword/' + queryParams,
|
|
35
33
|
null,
|
|
36
34
|
key
|
|
37
35
|
);
|
|
@@ -47,6 +45,109 @@ class MobileKeyword extends MetadataType {
|
|
|
47
45
|
}
|
|
48
46
|
}
|
|
49
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Builds map of metadata entries mapped to their keyfields
|
|
50
|
+
*
|
|
51
|
+
* @param {object} body json of response body
|
|
52
|
+
* @param {string|number} [singleRetrieve] key of single item to filter by
|
|
53
|
+
* @returns {TYPE.MetadataTypeMap} keyField => metadata map
|
|
54
|
+
*/
|
|
55
|
+
static parseResponseBody(body, singleRetrieve) {
|
|
56
|
+
const bodyIteratorField = this.definition.bodyIteratorField;
|
|
57
|
+
const keyField = this.definition.keyField;
|
|
58
|
+
const metadataStructure = {};
|
|
59
|
+
if (body !== null) {
|
|
60
|
+
if (Array.isArray(body)) {
|
|
61
|
+
// in some cases data is just an array
|
|
62
|
+
for (const item of body) {
|
|
63
|
+
this.#createCustomKeyField(item);
|
|
64
|
+
const key = item[keyField];
|
|
65
|
+
metadataStructure[key] = item;
|
|
66
|
+
}
|
|
67
|
+
} else if (body[bodyIteratorField]) {
|
|
68
|
+
for (const item of body[bodyIteratorField]) {
|
|
69
|
+
this.#createCustomKeyField(item);
|
|
70
|
+
const key = item[keyField];
|
|
71
|
+
metadataStructure[key] = item;
|
|
72
|
+
}
|
|
73
|
+
} else if (singleRetrieve) {
|
|
74
|
+
// some types will return a single item intead of an array if the key is supported by their api
|
|
75
|
+
this.#createCustomKeyField(body);
|
|
76
|
+
// ! currently, the id: prefix is only supported by journey (interaction)
|
|
77
|
+
if (singleRetrieve.startsWith('id:')) {
|
|
78
|
+
singleRetrieve = body[keyField];
|
|
79
|
+
}
|
|
80
|
+
metadataStructure[singleRetrieve] = body;
|
|
81
|
+
return metadataStructure;
|
|
82
|
+
}
|
|
83
|
+
if (
|
|
84
|
+
metadataStructure[singleRetrieve] &&
|
|
85
|
+
(typeof singleRetrieve === 'string' || typeof singleRetrieve === 'number')
|
|
86
|
+
) {
|
|
87
|
+
// in case we really just wanted one entry but couldnt do so in the api call, filter it here
|
|
88
|
+
const single = {};
|
|
89
|
+
single[singleRetrieve] = metadataStructure[singleRetrieve];
|
|
90
|
+
return single;
|
|
91
|
+
} else if (singleRetrieve) {
|
|
92
|
+
return {};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return metadataStructure;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* helper for {@link parseResponseBody} that creates a custom key field for this type based on mobileCode and keyword
|
|
100
|
+
*
|
|
101
|
+
* @private
|
|
102
|
+
* @param {TYPE.MetadataType} metadata single item
|
|
103
|
+
*/
|
|
104
|
+
static #createCustomKeyField(metadata) {
|
|
105
|
+
metadata.c__codeKeyword = metadata.code.code + '.' + metadata.keyword;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* helper for {@link preDeployTasks} and {@link createOrUpdate} to ensure we have code & keyword properly set
|
|
110
|
+
*
|
|
111
|
+
* @private
|
|
112
|
+
* @param {TYPE.MetadataType} metadata single item
|
|
113
|
+
*/
|
|
114
|
+
static #setCodeAndKeyword(metadata) {
|
|
115
|
+
const [code, keyword] = metadata.c__codeKeyword.split('.');
|
|
116
|
+
|
|
117
|
+
// mobileCode
|
|
118
|
+
metadata.code = {
|
|
119
|
+
id: cache.searchForField('mobileCode', code, 'code', 'id'),
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// keyword
|
|
123
|
+
metadata.keyword = keyword;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* helper for {@link MetadataType.upsert}
|
|
128
|
+
*
|
|
129
|
+
* @param {TYPE.MetadataTypeMap} metadataMap list of metadata
|
|
130
|
+
* @param {string} metadataKey key of item we are looking at
|
|
131
|
+
* @param {boolean} hasError error flag from previous code
|
|
132
|
+
* @param {TYPE.MetadataTypeItemDiff[]} metadataToUpdate list of items to update
|
|
133
|
+
* @param {TYPE.MetadataTypeItem[]} metadataToCreate list of items to create
|
|
134
|
+
* @returns {'create' | 'update' | 'skip'} action to take
|
|
135
|
+
*/
|
|
136
|
+
static createOrUpdate(metadataMap, metadataKey, hasError, metadataToUpdate, metadataToCreate) {
|
|
137
|
+
const createOrUpdateAction = super.createOrUpdate(
|
|
138
|
+
metadataMap,
|
|
139
|
+
metadataKey,
|
|
140
|
+
hasError,
|
|
141
|
+
metadataToUpdate,
|
|
142
|
+
metadataToCreate
|
|
143
|
+
);
|
|
144
|
+
if (createOrUpdateAction === 'update') {
|
|
145
|
+
// in case --changeKeyField or --changeKeyValue was used, let's ensure we set code & keyword here again
|
|
146
|
+
this.#setCodeAndKeyword(metadataMap[metadataKey]);
|
|
147
|
+
}
|
|
148
|
+
return createOrUpdateAction;
|
|
149
|
+
}
|
|
150
|
+
|
|
50
151
|
/**
|
|
51
152
|
* Retrieves event definition metadata for caching
|
|
52
153
|
*
|
|
@@ -60,26 +161,29 @@ class MobileKeyword extends MetadataType {
|
|
|
60
161
|
}
|
|
61
162
|
|
|
62
163
|
/**
|
|
63
|
-
*
|
|
164
|
+
* retrieve an item and create a template from it
|
|
64
165
|
*
|
|
65
166
|
* @param {string} templateDir Directory where retrieved metadata directory will be saved
|
|
66
|
-
* @param {string}
|
|
167
|
+
* @param {string} key name of the metadata file
|
|
67
168
|
* @param {TYPE.TemplateMap} templateVariables variables to be replaced in the metadata
|
|
68
169
|
* @returns {Promise.<TYPE.MetadataTypeItemObj>} Promise of metadata
|
|
69
170
|
*/
|
|
70
|
-
static async retrieveAsTemplate(templateDir,
|
|
171
|
+
static async retrieveAsTemplate(templateDir, key, templateVariables) {
|
|
71
172
|
try {
|
|
173
|
+
let queryParams;
|
|
174
|
+
[key, queryParams] = this.#getRetrieveKeyAndUrl(key);
|
|
175
|
+
|
|
72
176
|
return super.retrieveTemplateREST(
|
|
73
177
|
templateDir,
|
|
74
|
-
`/legacy/v1/beta/mobile/keyword
|
|
178
|
+
`/legacy/v1/beta/mobile/keyword/` + queryParams,
|
|
75
179
|
templateVariables,
|
|
76
|
-
|
|
180
|
+
key
|
|
77
181
|
);
|
|
78
182
|
} catch (ex) {
|
|
79
183
|
// if the mobileMessage does not exist, the API returns the error "Request failed with status code 400 (ERR_BAD_REQUEST)" which would otherwise bring execution to a hold
|
|
80
|
-
if (
|
|
184
|
+
if (key && ex.code === 'ERR_BAD_REQUEST') {
|
|
81
185
|
Util.logger.info(
|
|
82
|
-
`Downloaded: ${this.definition.type} (0)${Util.getKeysString(
|
|
186
|
+
`Downloaded: ${this.definition.type} (0)${Util.getKeysString(key)}`
|
|
83
187
|
);
|
|
84
188
|
} else {
|
|
85
189
|
throw ex;
|
|
@@ -88,13 +192,43 @@ class MobileKeyword extends MetadataType {
|
|
|
88
192
|
}
|
|
89
193
|
|
|
90
194
|
/**
|
|
91
|
-
*
|
|
195
|
+
* helper for {@link retrieve} and {@link retrieveAsTemplate}
|
|
196
|
+
*
|
|
197
|
+
* @private
|
|
198
|
+
* @param {string} key customer key of single item to retrieve / name of the metadata file
|
|
199
|
+
* @returns {Array} key, queryParams
|
|
200
|
+
*/
|
|
201
|
+
static #getRetrieveKeyAndUrl(key) {
|
|
202
|
+
let queryParams;
|
|
203
|
+
if (key) {
|
|
204
|
+
if (key.startsWith('id:')) {
|
|
205
|
+
// overwrite queryParams
|
|
206
|
+
queryParams = key.slice(3);
|
|
207
|
+
} else if (key.includes('.')) {
|
|
208
|
+
// keywords are always uppercased
|
|
209
|
+
key = key.toUpperCase();
|
|
210
|
+
// format: code.keyword
|
|
211
|
+
const [code, keyword] = key.split('.');
|
|
212
|
+
queryParams = `?view=simple&$where=keyword%20eq%20%27${keyword}%27%20and%code%20eq%20%27${code}%27%20`;
|
|
213
|
+
} else {
|
|
214
|
+
throw new Error(
|
|
215
|
+
`key ${key} has unexpected format. Expected 'code.keyword' or 'id:yourId'`
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
queryParams = '?view=simple';
|
|
220
|
+
}
|
|
221
|
+
return [key, queryParams];
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Creates a single item
|
|
92
226
|
*
|
|
93
|
-
* @param {TYPE.MetadataTypeItem}
|
|
227
|
+
* @param {TYPE.MetadataTypeItem} metadata a single item
|
|
94
228
|
* @returns {Promise} Promise
|
|
95
229
|
*/
|
|
96
|
-
static create(
|
|
97
|
-
return super.createREST(
|
|
230
|
+
static create(metadata) {
|
|
231
|
+
return super.createREST(metadata, '/legacy/v1/beta/mobile/keyword/');
|
|
98
232
|
}
|
|
99
233
|
/**
|
|
100
234
|
* Updates a single item
|
|
@@ -114,9 +248,21 @@ class MobileKeyword extends MetadataType {
|
|
|
114
248
|
* manages post retrieve steps
|
|
115
249
|
*
|
|
116
250
|
* @param {TYPE.MetadataTypeItem} metadata a single item
|
|
117
|
-
* @returns {TYPE.CodeExtractItem | TYPE.MetadataTypeItem} Array with one metadata object and one ssjs string
|
|
251
|
+
* @returns {TYPE.CodeExtractItem | TYPE.MetadataTypeItem | void} Array with one metadata object and one ssjs string; or single metadata object; nothing if filtered
|
|
118
252
|
*/
|
|
119
253
|
static postRetrieveTasks(metadata) {
|
|
254
|
+
try {
|
|
255
|
+
cache.searchForField('mobileCode', metadata.code.code, 'code', 'id');
|
|
256
|
+
} catch {
|
|
257
|
+
// in case the the mobileCode cannot be found, do not save this keyword as its no longer accessible in the UI either
|
|
258
|
+
Util.logger.debug(
|
|
259
|
+
` - skipping ${this.definition.type} ${
|
|
260
|
+
metadata[this.definition.keyField]
|
|
261
|
+
}. Could not find parent mobileCode ${metadata.code.code}`
|
|
262
|
+
);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
|
|
120
266
|
if (metadata.responseMessage) {
|
|
121
267
|
// extract message body
|
|
122
268
|
const codeArr = [];
|
|
@@ -295,8 +441,7 @@ class MobileKeyword extends MetadataType {
|
|
|
295
441
|
);
|
|
296
442
|
}
|
|
297
443
|
|
|
298
|
-
|
|
299
|
-
metadata.code.id = cache.searchForField('mobileCode', metadata.code.code, 'code', 'id');
|
|
444
|
+
this.#setCodeAndKeyword(metadata);
|
|
300
445
|
return metadata;
|
|
301
446
|
}
|
|
302
447
|
/**
|
|
@@ -163,21 +163,17 @@ class MobileMessage extends MetadataType {
|
|
|
163
163
|
|
|
164
164
|
// mobileKeyword
|
|
165
165
|
try {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
metadata.subscriptionKeyword.keyword,
|
|
178
|
-
'keyword',
|
|
179
|
-
'keyword'
|
|
180
|
-
);
|
|
166
|
+
for (const attr of ['keyword', 'subscriptionKeyword', 'nextKeyword']) {
|
|
167
|
+
if (metadata[attr]?.id) {
|
|
168
|
+
metadata[attr] = {
|
|
169
|
+
c__codeKeyword: cache.searchForField(
|
|
170
|
+
'mobileKeyword',
|
|
171
|
+
metadata[attr].id,
|
|
172
|
+
'id',
|
|
173
|
+
'c__codeKeyword'
|
|
174
|
+
),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
181
177
|
}
|
|
182
178
|
} catch (ex) {
|
|
183
179
|
Util.logger.warn(
|
|
@@ -265,20 +261,16 @@ class MobileMessage extends MetadataType {
|
|
|
265
261
|
metadata.code = code;
|
|
266
262
|
|
|
267
263
|
// mobileKeyword
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
if (!keyword) {
|
|
278
|
-
throw new Error(`mobileKeyword ${metadata.keyword.keyword} not found in cache`);
|
|
264
|
+
for (const attr of ['keyword', 'subscriptionKeyword', 'nextKeyword']) {
|
|
265
|
+
if (metadata[attr]?.c__codeKeyword) {
|
|
266
|
+
const keywordObj = cache.getByKey('mobileKeyword', metadata[attr].c__codeKeyword);
|
|
267
|
+
if (!keywordObj) {
|
|
268
|
+
throw new Error(
|
|
269
|
+
`mobileKeyword ${metadata[attr].c__codeKeyword} not found in cache`
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
metadata[attr] = keywordObj;
|
|
279
273
|
}
|
|
280
|
-
|
|
281
|
-
metadata.subscriptionKeyword.keyword = keyword;
|
|
282
274
|
}
|
|
283
275
|
|
|
284
276
|
// campaign
|
|
@@ -102,9 +102,8 @@ class Role extends MetadataType {
|
|
|
102
102
|
`Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` +
|
|
103
103
|
Util.getKeysString(key)
|
|
104
104
|
);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
105
|
+
|
|
106
|
+
await this.runDocumentOnRetrieve(key, savedMetadata);
|
|
108
107
|
}
|
|
109
108
|
return { metadata: parsed, type: this.definition.type };
|
|
110
109
|
}
|
|
@@ -58,9 +58,9 @@ class TransactionalSMS extends TransactionalMessage {
|
|
|
58
58
|
// we merely want to be able to show an error if it does not exist
|
|
59
59
|
cache.searchForField(
|
|
60
60
|
'mobileKeyword',
|
|
61
|
-
metadata.subscriptions.keyword,
|
|
62
|
-
'
|
|
63
|
-
'
|
|
61
|
+
metadata.subscriptions.shortCode + '.' + metadata.subscriptions.keyword,
|
|
62
|
+
'c__codeKeyword',
|
|
63
|
+
'id'
|
|
64
64
|
);
|
|
65
65
|
}
|
|
66
66
|
return metadata;
|
|
@@ -142,9 +142,9 @@ class TransactionalSMS extends TransactionalMessage {
|
|
|
142
142
|
// we merely want to be able to show a warning if it does not exist
|
|
143
143
|
cache.searchForField(
|
|
144
144
|
'mobileKeyword',
|
|
145
|
-
metadata.subscriptions.keyword,
|
|
145
|
+
metadata.subscriptions.shortCode + '.' + metadata.subscriptions.keyword,
|
|
146
146
|
'keyword',
|
|
147
|
-
'
|
|
147
|
+
'id'
|
|
148
148
|
);
|
|
149
149
|
} catch {
|
|
150
150
|
Util.logger.warn(
|
|
@@ -215,12 +215,12 @@ class User extends MetadataType {
|
|
|
215
215
|
);
|
|
216
216
|
|
|
217
217
|
if (action === 'create') {
|
|
218
|
-
const createItem = metadataToCreate
|
|
218
|
+
const createItem = metadataToCreate.at(-1);
|
|
219
219
|
User._setPasswordForNewUser(createItem);
|
|
220
220
|
User._prepareRoleAssignments({ after: createItem });
|
|
221
221
|
User._prepareBuAssignments(metadata[metadataKey], null, createItem);
|
|
222
222
|
} else if (action === 'update') {
|
|
223
|
-
const updateItem = metadataToUpdate
|
|
223
|
+
const updateItem = metadataToUpdate.at(-1);
|
|
224
224
|
User._prepareRoleAssignments(updateItem);
|
|
225
225
|
User._prepareBuAssignments(metadata[metadataKey], updateItem, null);
|
|
226
226
|
}
|
|
@@ -731,13 +731,7 @@ class User extends MetadataType {
|
|
|
731
731
|
)
|
|
732
732
|
);
|
|
733
733
|
}
|
|
734
|
-
|
|
735
|
-
!singleRetrieve &&
|
|
736
|
-
this.buObject &&
|
|
737
|
-
this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)
|
|
738
|
-
) {
|
|
739
|
-
await this.document(savedMetadata);
|
|
740
|
-
}
|
|
734
|
+
await this.runDocumentOnRetrieve(singleRetrieve, savedMetadata);
|
|
741
735
|
}
|
|
742
736
|
return { metadata: metadata, type: this.definition.type };
|
|
743
737
|
}
|
|
@@ -944,14 +938,6 @@ class User extends MetadataType {
|
|
|
944
938
|
return;
|
|
945
939
|
}
|
|
946
940
|
|
|
947
|
-
// if ran as part of retrieve/deploy with key, exit here
|
|
948
|
-
if (metadata && Object.keys(metadata).length === 1) {
|
|
949
|
-
Util.logger.debug(
|
|
950
|
-
'Only 1 user found. Skipping documentation, assuming we ran retrieve-by-key.'
|
|
951
|
-
);
|
|
952
|
-
return;
|
|
953
|
-
}
|
|
954
|
-
|
|
955
941
|
if (!metadata) {
|
|
956
942
|
// load users from disk if document was called directly and not part of a retrieve
|
|
957
943
|
try {
|
|
@@ -3,8 +3,8 @@ module.exports = {
|
|
|
3
3
|
dependencies: ['mobileCode'],
|
|
4
4
|
hasExtended: false,
|
|
5
5
|
idField: 'id',
|
|
6
|
-
keyIsFixed: false,
|
|
7
|
-
keyField: '
|
|
6
|
+
keyIsFixed: false, // custom field but mapped to normal fields
|
|
7
|
+
keyField: 'c__codeKeyword',
|
|
8
8
|
nameField: 'keyword',
|
|
9
9
|
createdDateField: 'createdDate',
|
|
10
10
|
createdNameField: 'createdBy.name',
|
|
@@ -21,14 +21,20 @@ module.exports = {
|
|
|
21
21
|
// irregular format: NXV4ZFMwTEFwRVczd3RaLUF5X3p5dzo4Njow
|
|
22
22
|
isCreateable: false,
|
|
23
23
|
isUpdateable: true,
|
|
24
|
-
retrieving:
|
|
24
|
+
retrieving: false,
|
|
25
25
|
template: false,
|
|
26
26
|
},
|
|
27
|
+
c__codeKeyword: {
|
|
28
|
+
isCreateable: false,
|
|
29
|
+
isUpdateable: false,
|
|
30
|
+
retrieving: true,
|
|
31
|
+
template: true,
|
|
32
|
+
},
|
|
27
33
|
keyword: {
|
|
28
34
|
isCreateable: true,
|
|
29
35
|
isUpdateable: true,
|
|
30
|
-
retrieving:
|
|
31
|
-
template:
|
|
36
|
+
retrieving: false,
|
|
37
|
+
template: false,
|
|
32
38
|
},
|
|
33
39
|
createdDate: {
|
|
34
40
|
isCreateable: false,
|
|
@@ -133,11 +139,17 @@ module.exports = {
|
|
|
133
139
|
retrieving: true,
|
|
134
140
|
template: false,
|
|
135
141
|
},
|
|
142
|
+
code: {
|
|
143
|
+
isCreateable: true,
|
|
144
|
+
isUpdateable: true,
|
|
145
|
+
retrieving: false,
|
|
146
|
+
template: false,
|
|
147
|
+
},
|
|
136
148
|
'code.code': {
|
|
137
149
|
isCreateable: false,
|
|
138
150
|
isUpdateable: false,
|
|
139
|
-
retrieving:
|
|
140
|
-
template:
|
|
151
|
+
retrieving: false,
|
|
152
|
+
template: false,
|
|
141
153
|
},
|
|
142
154
|
'code.id': {
|
|
143
155
|
isCreateable: true,
|
|
@@ -316,6 +316,12 @@ module.exports = {
|
|
|
316
316
|
'keyword.keyword': {
|
|
317
317
|
isCreateable: true,
|
|
318
318
|
isUpdateable: true,
|
|
319
|
+
retrieving: false,
|
|
320
|
+
template: false,
|
|
321
|
+
},
|
|
322
|
+
'keyword.c__codeKeyword': {
|
|
323
|
+
isCreateable: false,
|
|
324
|
+
isUpdateable: false,
|
|
319
325
|
retrieving: true,
|
|
320
326
|
template: true,
|
|
321
327
|
},
|
|
@@ -620,27 +626,63 @@ module.exports = {
|
|
|
620
626
|
'subscriptionKeyword.id': {
|
|
621
627
|
isCreatable: true,
|
|
622
628
|
isUpdatable: true,
|
|
623
|
-
retrieving:
|
|
624
|
-
template:
|
|
629
|
+
retrieving: false,
|
|
630
|
+
template: false,
|
|
625
631
|
},
|
|
626
632
|
'subscriptionKeyword.keyword': {
|
|
627
|
-
isCreatable:
|
|
628
|
-
isUpdatable:
|
|
633
|
+
isCreatable: false,
|
|
634
|
+
isUpdatable: false,
|
|
635
|
+
retrieving: false,
|
|
636
|
+
template: false,
|
|
637
|
+
},
|
|
638
|
+
'subscriptionKeyword.c__codeKeyword': {
|
|
639
|
+
isCreateable: false,
|
|
640
|
+
isUpdateable: false,
|
|
629
641
|
retrieving: true,
|
|
630
642
|
template: true,
|
|
631
643
|
},
|
|
632
644
|
'subscriptionKeyword.restriction': {
|
|
633
|
-
isCreatable:
|
|
634
|
-
isUpdatable:
|
|
635
|
-
retrieving:
|
|
636
|
-
template:
|
|
645
|
+
isCreatable: false,
|
|
646
|
+
isUpdatable: false,
|
|
647
|
+
retrieving: false,
|
|
648
|
+
template: false,
|
|
637
649
|
},
|
|
638
650
|
'subscriptionKeyword.isInherited': {
|
|
651
|
+
isCreatable: false,
|
|
652
|
+
isUpdatable: false,
|
|
653
|
+
retrieving: false,
|
|
654
|
+
template: false,
|
|
655
|
+
},
|
|
656
|
+
'nextKeyword.id': {
|
|
639
657
|
isCreatable: true,
|
|
640
658
|
isUpdatable: true,
|
|
659
|
+
retrieving: false,
|
|
660
|
+
template: false,
|
|
661
|
+
},
|
|
662
|
+
'nextKeyword.keyword': {
|
|
663
|
+
isCreatable: false,
|
|
664
|
+
isUpdatable: false,
|
|
665
|
+
retrieving: false,
|
|
666
|
+
template: false,
|
|
667
|
+
},
|
|
668
|
+
'nextKeyword.c__codeKeyword': {
|
|
669
|
+
isCreateable: false,
|
|
670
|
+
isUpdateable: false,
|
|
641
671
|
retrieving: true,
|
|
642
672
|
template: true,
|
|
643
673
|
},
|
|
674
|
+
'nextKeyword.restriction': {
|
|
675
|
+
isCreatable: false,
|
|
676
|
+
isUpdatable: false,
|
|
677
|
+
retrieving: false,
|
|
678
|
+
template: false,
|
|
679
|
+
},
|
|
680
|
+
'nextKeyword.isInherited': {
|
|
681
|
+
isCreatable: false,
|
|
682
|
+
isUpdatable: false,
|
|
683
|
+
retrieving: false,
|
|
684
|
+
template: false,
|
|
685
|
+
},
|
|
644
686
|
subscriberResponseMessage: {
|
|
645
687
|
isCreatable: true,
|
|
646
688
|
isUpdatable: true,
|
|
@@ -17,6 +17,7 @@ module.exports = {
|
|
|
17
17
|
typeDescription: 'Marketing Cloud users',
|
|
18
18
|
typeName: 'User',
|
|
19
19
|
typeRetrieveByDefault: false,
|
|
20
|
+
documentInOneFile: true,
|
|
20
21
|
stringifyFieldsBeforeTemplate: ['DefaultBusinessUnit', 'c__AssociatedBusinessUnits'],
|
|
21
22
|
fields: {
|
|
22
23
|
AccountUserID: {
|
package/lib/util/auth.js
CHANGED
|
@@ -137,7 +137,10 @@ function setupSDK(sessionKey, authObject) {
|
|
|
137
137
|
Util.logger.debug('API REQUEST >> ' + JSON.stringify(msg, null, 2));
|
|
138
138
|
if (data) {
|
|
139
139
|
// printing it separately leads to better formatting
|
|
140
|
-
Util.logger.debug(
|
|
140
|
+
Util.logger.debug(
|
|
141
|
+
'API REQUEST body >> \n ' +
|
|
142
|
+
(typeof data === 'string' ? data : JSON.stringify(data, null, 2))
|
|
143
|
+
);
|
|
141
144
|
}
|
|
142
145
|
}
|
|
143
146
|
},
|
package/lib/util/cli.js
CHANGED
|
@@ -570,7 +570,7 @@ const Cli = {
|
|
|
570
570
|
}
|
|
571
571
|
if (Util.OPTIONS.json) {
|
|
572
572
|
if (Util.OPTIONS.loggerLevel !== 'error') {
|
|
573
|
-
console.log(json); // eslint-disable-line no-console
|
|
573
|
+
console.log(JSON.stringify(json, null, 2)); // eslint-disable-line no-console
|
|
574
574
|
}
|
|
575
575
|
return json;
|
|
576
576
|
}
|
package/lib/util/file.js
CHANGED
|
@@ -517,9 +517,10 @@ const File = {
|
|
|
517
517
|
* @param {string} [filetype='html'] filetype ie. JSON or SSJS
|
|
518
518
|
* @returns {Promise.<boolean>} success of config load
|
|
519
519
|
*/
|
|
520
|
-
async initPrettier(filetype) {
|
|
521
|
-
if (FileFs.prettierConfig === null) {
|
|
522
|
-
filetype
|
|
520
|
+
async initPrettier(filetype = 'html') {
|
|
521
|
+
if (FileFs.prettierConfig === null || FileFs.prettierConfigFileType !== filetype) {
|
|
522
|
+
// run this if no config was yet found or if the filetype previously used to initialize it differs (because it results in a potentially different config!)
|
|
523
|
+
FileFs.prettierConfigFileType = filetype;
|
|
523
524
|
try {
|
|
524
525
|
// pass in project dir with fake index.html to avoid "no parser" error
|
|
525
526
|
// by using process.cwd we are limiting ourselves to a config in the project root
|
|
@@ -547,5 +548,6 @@ const File = {
|
|
|
547
548
|
};
|
|
548
549
|
const FileFs = { ...fs, ...File };
|
|
549
550
|
FileFs.prettierConfig = null;
|
|
551
|
+
FileFs.prettierConfigFileType = null;
|
|
550
552
|
|
|
551
553
|
module.exports = FileFs;
|
package/lib/util/util.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcdev",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.2",
|
|
4
4
|
"description": "Accenture Salesforce Marketing Cloud DevTools",
|
|
5
5
|
"author": "Accenture: joern.berkefeld, douglas.midgley, robert.zimmermann, maciej.barnas",
|
|
6
6
|
"license": "MIT",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"command-exists": "1.2.9",
|
|
64
64
|
"conf": "10.2.0",
|
|
65
65
|
"console.table": "0.10.0",
|
|
66
|
-
"deep-equal": "2.1
|
|
66
|
+
"deep-equal": "2.2.1",
|
|
67
67
|
"fs-extra": "11.1.0",
|
|
68
68
|
"inquirer": "8.2.5",
|
|
69
69
|
"json-to-table": "4.2.1",
|
|
@@ -72,29 +72,29 @@
|
|
|
72
72
|
"prettier": "2.8.8",
|
|
73
73
|
"prettier-plugin-sql": "0.14.0",
|
|
74
74
|
"semver": "7.5.0",
|
|
75
|
-
"sfmc-sdk": "1.0.
|
|
76
|
-
"simple-git": "3.
|
|
75
|
+
"sfmc-sdk": "1.0.1",
|
|
76
|
+
"simple-git": "3.18.0",
|
|
77
77
|
"toposort": "2.0.2",
|
|
78
78
|
"update-notifier": "5.1.0",
|
|
79
79
|
"winston": "3.8.2",
|
|
80
|
-
"yargs": "17.
|
|
80
|
+
"yargs": "17.7.2"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"assert": "2.0.0",
|
|
84
84
|
"axios-mock-adapter": "1.21.3",
|
|
85
85
|
"chai": "4.3.7",
|
|
86
86
|
"chai-files": "1.4.0",
|
|
87
|
-
"eslint": "8.
|
|
87
|
+
"eslint": "8.41.0",
|
|
88
88
|
"eslint-config-prettier": "8.7.0",
|
|
89
89
|
"eslint-config-ssjs": "1.1.11",
|
|
90
|
-
"eslint-plugin-jsdoc": "
|
|
90
|
+
"eslint-plugin-jsdoc": "45.0.0",
|
|
91
91
|
"eslint-plugin-mocha": "10.1.0",
|
|
92
92
|
"eslint-plugin-prettier": "4.2.1",
|
|
93
|
-
"eslint-plugin-unicorn": "
|
|
93
|
+
"eslint-plugin-unicorn": "47.0.0",
|
|
94
94
|
"fast-xml-parser": "4.2.2",
|
|
95
95
|
"husky": "8.0.3",
|
|
96
96
|
"jsdoc-to-markdown": "8.0.0",
|
|
97
|
-
"lint-staged": "13.2.
|
|
97
|
+
"lint-staged": "13.2.2",
|
|
98
98
|
"mocha": "10.2.0",
|
|
99
99
|
"mock-fs": "5.2.0",
|
|
100
100
|
"npm-check": "6.0.1",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"sharedFolder": "/Shared Data Extensions/test",
|
|
42
42
|
"suffix": "_test",
|
|
43
43
|
"prefix": "testExisting_",
|
|
44
|
+
"prefixUpper": "TESTEXISTING_",
|
|
44
45
|
"description": "bla bla",
|
|
45
46
|
"countryCodeIn": "'test'"
|
|
46
47
|
},
|
|
@@ -51,6 +52,7 @@
|
|
|
51
52
|
"sharedFolder": "/Shared Data Extensions/test target",
|
|
52
53
|
"suffix": "_testTarget",
|
|
53
54
|
"prefix": "testTemplated_",
|
|
55
|
+
"prefixUpper": "TESTTEMPLATED_",
|
|
54
56
|
"description": "foobar",
|
|
55
57
|
"countryCodeIn": "'testTarget'"
|
|
56
58
|
}
|
|
@@ -76,5 +78,5 @@
|
|
|
76
78
|
"triggeredSend"
|
|
77
79
|
]
|
|
78
80
|
},
|
|
79
|
-
"version": "5.0.
|
|
81
|
+
"version": "5.0.2"
|
|
80
82
|
}
|