mcdev 4.2.1 → 4.3.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/PULL_REQUEST_TEMPLATE.md +1 -2
- package/.github/pr-labeler.yml +3 -0
- package/.github/workflows/close_issues_on_merge.yml +18 -0
- package/.github/workflows/pr-labeler.yml +19 -0
- package/LICENSE +1 -1
- package/README.md +1 -1
- package/docs/dist/documentation.md +700 -281
- package/lib/Deployer.js +21 -15
- package/lib/Retriever.js +23 -19
- package/lib/cli.js +36 -6
- package/lib/index.js +56 -10
- package/lib/metadataTypes/AccountUser.js +17 -23
- package/lib/metadataTypes/Asset.js +28 -21
- package/lib/metadataTypes/AttributeGroup.js +1 -2
- package/lib/metadataTypes/Automation.js +75 -37
- package/lib/metadataTypes/Campaign.js +4 -3
- package/lib/metadataTypes/ContentArea.js +2 -3
- package/lib/metadataTypes/DataExtension.js +56 -47
- package/lib/metadataTypes/DataExtensionField.js +9 -12
- package/lib/metadataTypes/DataExtensionTemplate.js +2 -3
- package/lib/metadataTypes/DataExtract.js +1 -2
- package/lib/metadataTypes/DataExtractType.js +1 -2
- package/lib/metadataTypes/Discovery.js +3 -4
- package/lib/metadataTypes/Email.js +20 -6
- package/lib/metadataTypes/EmailSendDefinition.js +5 -8
- package/lib/metadataTypes/EventDefinition.js +29 -2
- package/lib/metadataTypes/FileTransfer.js +1 -2
- package/lib/metadataTypes/Filter.js +1 -2
- package/lib/metadataTypes/Folder.js +12 -14
- package/lib/metadataTypes/FtpLocation.js +1 -2
- package/lib/metadataTypes/ImportFile.js +1 -2
- package/lib/metadataTypes/Interaction.js +678 -12
- package/lib/metadataTypes/List.js +36 -33
- package/lib/metadataTypes/MetadataType.js +170 -124
- package/lib/metadataTypes/MobileCode.js +1 -2
- package/lib/metadataTypes/MobileKeyword.js +1 -2
- package/lib/metadataTypes/Query.js +15 -6
- package/lib/metadataTypes/Role.js +10 -11
- package/lib/metadataTypes/Script.js +2 -5
- package/lib/metadataTypes/SetDefinition.js +1 -2
- package/lib/metadataTypes/TransactionalMessage.js +25 -32
- package/lib/metadataTypes/TransactionalSMS.js +3 -4
- package/lib/metadataTypes/TriggeredSendDefinition.js +232 -56
- package/lib/metadataTypes/definitions/Asset.definition.js +1 -1
- package/lib/metadataTypes/definitions/Automation.definition.js +1 -1
- package/lib/metadataTypes/definitions/DataExtension.definition.js +10 -1
- package/lib/metadataTypes/definitions/Email.definition.js +1 -1
- package/lib/metadataTypes/definitions/EmailSendDefinition.definition.js +1 -1
- package/lib/metadataTypes/definitions/EventDefinition.definition.js +40 -1
- package/lib/metadataTypes/definitions/Folder.definition.js +31 -0
- package/lib/metadataTypes/definitions/ImportFile.definition.js +1 -1
- package/lib/metadataTypes/definitions/Interaction.definition.js +47 -26
- package/lib/metadataTypes/definitions/List.definition.js +1 -1
- package/lib/metadataTypes/definitions/Query.definition.js +1 -1
- package/lib/metadataTypes/definitions/Script.definition.js +1 -1
- package/lib/metadataTypes/definitions/TransactionalEmail.definition.js +2 -1
- package/lib/metadataTypes/definitions/TransactionalPush.definition.js +2 -1
- package/lib/metadataTypes/definitions/TransactionalSMS.definition.js +2 -1
- package/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js +10 -2
- package/lib/util/auth.js +10 -2
- package/lib/util/cli.js +4 -1
- package/lib/util/file.js +7 -3
- package/lib/util/init.js +62 -0
- package/lib/util/util.js +131 -11
- package/package.json +22 -9
- package/test/dataExtension.test.js +10 -10
- package/test/interaction.test.js +123 -0
- package/test/mockRoot/.mcdevrc.json +1 -1
- package/test/mockRoot/deploy/testInstance/testBU/interaction/testExisting_interaction.interaction-meta.json +266 -0
- package/test/mockRoot/deploy/testInstance/testBU/interaction/testNew_interaction.interaction-meta.json +266 -0
- package/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json +0 -3
- package/test/query.test.js +8 -8
- package/test/resourceFactory.js +12 -7
- package/test/resources/1111111/dataExtension/retrieve-response.xml +26 -0
- package/test/resources/9999999/data/v1/customobjectdata/key/childBU_dataextension_test/rowset/get-response.json +13 -0
- package/test/resources/9999999/dataFolder/retrieve-response.xml +22 -0
- package/test/resources/9999999/eventDefinition/get-expected.json +34 -0
- package/test/resources/9999999/interaction/build-expected.json +260 -0
- package/test/resources/9999999/interaction/get-expected.json +264 -0
- package/test/resources/9999999/interaction/post-expected.json +264 -0
- package/test/resources/9999999/interaction/put-expected.json +264 -0
- package/test/resources/9999999/interaction/template-expected.json +260 -0
- package/test/resources/9999999/interaction/v1/EventDefinitions/get-response.json +43 -0
- package/test/resources/9999999/interaction/v1/interactions/get-response.json +222 -3
- package/test/resources/9999999/interaction/v1/interactions/post-response.json +280 -0
- package/test/resources/9999999/interaction/v1/interactions/put-response.json +280 -0
- package/test/resources/9999999/messaging/v1/email/definitions/post-response.json +1 -1
- package/test/resources/9999999/query/post-expected.sql +1 -1
- package/test/resources/9999999/transactionalEmail/post-expected.json +1 -1
- package/test/transactionalEmail.test.js +7 -7
- package/test/transactionalPush.test.js +7 -7
- package/test/transactionalSMS.test.js +7 -7
- package/test/utils.js +50 -0
- package/types/mcdev.d.js +1 -0
package/lib/Deployer.js
CHANGED
|
@@ -238,38 +238,44 @@ class Deployer {
|
|
|
238
238
|
Object.keys(this.metadata)
|
|
239
239
|
);
|
|
240
240
|
}
|
|
241
|
-
const foundDeployTypes = Object.keys(this.metadata)
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
241
|
+
const foundDeployTypes = Object.keys(this.metadata)
|
|
242
|
+
.map((type) =>
|
|
243
|
+
type === 'asset' && Util.includesStartsWith(typeArr, type)
|
|
244
|
+
? typeArr[Util.includesStartsWithIndex(typeArr, type)]
|
|
245
|
+
: type
|
|
246
|
+
)
|
|
247
|
+
// remove empty types
|
|
248
|
+
.filter((type) => Object.keys(this.metadata[type]).length);
|
|
249
|
+
if (!foundDeployTypes.length) {
|
|
250
|
+
throw new Error('No metadata found for deployment');
|
|
251
|
+
}
|
|
246
252
|
const deployOrder = Util.getMetadataHierachy(foundDeployTypes);
|
|
247
253
|
// build cache, including all metadata types which will be deployed (Avoids retrieve later)
|
|
248
|
-
for (const metadataType
|
|
249
|
-
const
|
|
254
|
+
for (const metadataType in deployOrder) {
|
|
255
|
+
const type = metadataType;
|
|
256
|
+
const subTypeArr = deployOrder[metadataType];
|
|
250
257
|
// add metadata & client to metadata process class instead of passing cache/mapping every time
|
|
251
258
|
MetadataTypeInfo[type].client = auth.getSDK(this.buObject);
|
|
252
259
|
MetadataTypeInfo[type].properties = this.properties;
|
|
253
260
|
MetadataTypeInfo[type].buObject = this.buObject;
|
|
254
|
-
Util.logger.info(
|
|
255
|
-
|
|
261
|
+
Util.logger.info(`Caching dependent Metadata: ${metadataType}`);
|
|
262
|
+
Util.logSubtypes(subTypeArr);
|
|
263
|
+
const result = await MetadataTypeInfo[type].retrieveForCache(null, subTypeArr);
|
|
256
264
|
cache.setMetadata(type, result.metadata);
|
|
257
265
|
}
|
|
258
266
|
/** @type {TYPE.MultiMetadataTypeMap} */
|
|
259
267
|
const multiMetadataTypeMap = {};
|
|
260
268
|
// deploy metadata files, extending cache once deploys
|
|
261
|
-
for (const metadataType
|
|
262
|
-
// TODO rewrite to allow deploying only a specific sub-type
|
|
263
|
-
|
|
264
|
-
const type = metadataType.split('-')[0];
|
|
269
|
+
for (const metadataType in deployOrder) {
|
|
270
|
+
// TODO rewrite to allow deploying only a specific sub-type; currently, subtypes are ignored when executing deploy
|
|
271
|
+
const type = metadataType;
|
|
265
272
|
if (this.metadata[type]) {
|
|
266
273
|
Util.logger.info('Deploying: ' + metadataType);
|
|
267
274
|
|
|
268
275
|
const result = await MetadataTypeInfo[type].deploy(
|
|
269
276
|
this.metadata[type],
|
|
270
277
|
this.deployDir,
|
|
271
|
-
this.retrieveDir
|
|
272
|
-
this.buObject
|
|
278
|
+
this.retrieveDir
|
|
273
279
|
);
|
|
274
280
|
multiMetadataTypeMap[type] = result;
|
|
275
281
|
cache.mergeMetadata(type, result);
|
package/lib/Retriever.js
CHANGED
|
@@ -59,16 +59,12 @@ class Retriever {
|
|
|
59
59
|
// assuming TypeKeyCombo was provided
|
|
60
60
|
typeKeyMap = namesOrKeys;
|
|
61
61
|
}
|
|
62
|
-
// defined colors for optionally printing the keys we filtered by
|
|
63
|
-
const color = {
|
|
64
|
-
reset: '\x1B[0m',
|
|
65
|
-
dim: '\x1B[2m',
|
|
66
|
-
};
|
|
67
62
|
// ensure we know which real dependencies we have to ensure we cache those completely
|
|
68
63
|
const dependencies = this._getTypeDependencies(metadataTypes);
|
|
69
|
-
|
|
70
|
-
for (const metadataType
|
|
71
|
-
const
|
|
64
|
+
const deployOrder = Util.getMetadataHierachy(metadataTypes);
|
|
65
|
+
for (const metadataType in deployOrder) {
|
|
66
|
+
const type = metadataType;
|
|
67
|
+
const subTypeArr = deployOrder[metadataType];
|
|
72
68
|
// if types were added by getMetadataHierachy() for caching, make sure the key-list is set to [null] for them which will retrieve all
|
|
73
69
|
typeKeyMap[metadataType] = typeKeyMap[metadataType] || [null];
|
|
74
70
|
// add client to metadata process class instead of passing every time
|
|
@@ -78,26 +74,36 @@ class Retriever {
|
|
|
78
74
|
try {
|
|
79
75
|
let result;
|
|
80
76
|
if (!metadataTypes.includes(type) && !metadataTypes.includes(metadataType)) {
|
|
77
|
+
// type not in list of types to retrieve, but is a dependency of one of them
|
|
81
78
|
if (changelogOnly && type !== 'folder') {
|
|
82
79
|
// no extra caching needed for list view except for folders
|
|
83
80
|
continue;
|
|
84
81
|
}
|
|
85
82
|
Util.logger.info(`Caching dependent Metadata: ${metadataType}`);
|
|
86
|
-
|
|
83
|
+
Util.logSubtypes(subTypeArr);
|
|
84
|
+
result = await MetadataTypeInfo[type].retrieveForCache(null, subTypeArr);
|
|
87
85
|
} else if (templateVariables) {
|
|
86
|
+
// type is in list of types to retrieve and we have template variables
|
|
88
87
|
Util.logger.info(`Retrieving as Template: ${metadataType}`);
|
|
89
|
-
|
|
88
|
+
if (subTypeArr?.length > 1) {
|
|
89
|
+
Util.logger.warn(
|
|
90
|
+
`retrieveAsTemplate only works with one subtype, ignoring all but first subtype from your list: ${subTypeArr.join(
|
|
91
|
+
', '
|
|
92
|
+
)}`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
90
95
|
result = await Promise.all(
|
|
91
96
|
typeKeyMap[metadataType].map((name) =>
|
|
92
97
|
MetadataTypeInfo[type].retrieveAsTemplate(
|
|
93
98
|
this.templateDir,
|
|
94
99
|
name,
|
|
95
100
|
templateVariables,
|
|
96
|
-
|
|
101
|
+
subTypeArr?.[0]
|
|
97
102
|
)
|
|
98
103
|
)
|
|
99
104
|
);
|
|
100
105
|
} else {
|
|
106
|
+
// type is in list of types to retrieve and we don't have template variables
|
|
101
107
|
let cacheResult = null;
|
|
102
108
|
if (
|
|
103
109
|
(typeKeyMap[metadataType].length > 1 ||
|
|
@@ -106,28 +112,26 @@ class Retriever {
|
|
|
106
112
|
) {
|
|
107
113
|
// if we have a key-list and the type is a dependency, we need to cache the whole type
|
|
108
114
|
Util.logger.info(`Caching dependent Metadata: ${metadataType}`);
|
|
115
|
+
Util.logSubtypes(subTypeArr);
|
|
109
116
|
cacheResult = await MetadataTypeInfo[type].retrieveForCache(
|
|
110
|
-
|
|
111
|
-
|
|
117
|
+
null,
|
|
118
|
+
subTypeArr
|
|
112
119
|
);
|
|
113
120
|
}
|
|
114
121
|
Util.logger.info(
|
|
115
122
|
`Retrieving: ${metadataType}` +
|
|
116
123
|
(typeKeyMap[metadataType][0] === null
|
|
117
124
|
? ''
|
|
118
|
-
:
|
|
119
|
-
color.reset
|
|
120
|
-
}`)
|
|
125
|
+
: Util.getKeysString(typeKeyMap[metadataType]))
|
|
121
126
|
);
|
|
122
127
|
result = await (changelogOnly
|
|
123
|
-
? MetadataTypeInfo[type].retrieveChangelog(
|
|
128
|
+
? MetadataTypeInfo[type].retrieveChangelog(null, subTypeArr)
|
|
124
129
|
: Promise.all(
|
|
125
130
|
typeKeyMap[metadataType].map((key) =>
|
|
126
131
|
MetadataTypeInfo[type].retrieve(
|
|
127
132
|
this.savePath,
|
|
128
133
|
null,
|
|
129
|
-
|
|
130
|
-
subType,
|
|
134
|
+
subTypeArr,
|
|
131
135
|
key
|
|
132
136
|
)
|
|
133
137
|
)
|
package/lib/cli.js
CHANGED
|
@@ -84,6 +84,15 @@ yargs
|
|
|
84
84
|
Mcdev.initProject(argv.credentialsName);
|
|
85
85
|
},
|
|
86
86
|
})
|
|
87
|
+
.command({
|
|
88
|
+
command: 'join',
|
|
89
|
+
desc: `clones an existing project from git`,
|
|
90
|
+
handler: (argv) => {
|
|
91
|
+
Mcdev.setSkipInteraction(argv.skipInteraction);
|
|
92
|
+
Mcdev.setLoggingLevel(argv);
|
|
93
|
+
Mcdev.joinProject();
|
|
94
|
+
},
|
|
95
|
+
})
|
|
87
96
|
.command({
|
|
88
97
|
command: 'reloadBUs [credentialsName]',
|
|
89
98
|
aliases: ['rb'],
|
|
@@ -221,9 +230,7 @@ yargs
|
|
|
221
230
|
handler: (argv) => {
|
|
222
231
|
Mcdev.setSkipInteraction(argv.skipInteraction);
|
|
223
232
|
Mcdev.setLoggingLevel(argv);
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
Mcdev.buildTemplate(argv.BU, argv.TYPE, keyArr, argv.MARKET);
|
|
233
|
+
Mcdev.buildTemplate(argv.BU, argv.TYPE, csvToArray(argv.KEY), argv.MARKET);
|
|
227
234
|
},
|
|
228
235
|
})
|
|
229
236
|
.command({
|
|
@@ -345,9 +352,32 @@ yargs
|
|
|
345
352
|
handler: (argv) => {
|
|
346
353
|
Mcdev.setSkipInteraction(argv.skipInteraction);
|
|
347
354
|
Mcdev.setLoggingLevel(argv);
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
355
|
+
Mcdev.getFilesToCommit(argv.BU, argv.TYPE, csvToArray(argv.KEY));
|
|
356
|
+
},
|
|
357
|
+
})
|
|
358
|
+
.command({
|
|
359
|
+
command: 'refresh <BU> [TYPE] [KEY]',
|
|
360
|
+
aliases: ['re'],
|
|
361
|
+
desc: 'ensures that updates are properly published',
|
|
362
|
+
builder: (yargs) => {
|
|
363
|
+
yargs
|
|
364
|
+
.positional('BU', {
|
|
365
|
+
type: 'string',
|
|
366
|
+
describe: 'the business unit to execute the refresh on',
|
|
367
|
+
})
|
|
368
|
+
.positional('TYPE', {
|
|
369
|
+
type: 'string',
|
|
370
|
+
describe: 'metadata type',
|
|
371
|
+
})
|
|
372
|
+
.positional('KEY', {
|
|
373
|
+
type: 'string',
|
|
374
|
+
describe: 'key(s) of the metadata component(s)',
|
|
375
|
+
});
|
|
376
|
+
},
|
|
377
|
+
handler: (argv) => {
|
|
378
|
+
Mcdev.setSkipInteraction(argv.skipInteraction);
|
|
379
|
+
Mcdev.setLoggingLevel(argv);
|
|
380
|
+
Mcdev.refresh(argv.BU, argv.TYPE, csvToArray(argv.KEY));
|
|
351
381
|
},
|
|
352
382
|
})
|
|
353
383
|
.command({
|
package/lib/index.js
CHANGED
|
@@ -147,7 +147,7 @@ class Mcdev {
|
|
|
147
147
|
if (
|
|
148
148
|
properties.credentials &&
|
|
149
149
|
(!properties.credentials[cred] ||
|
|
150
|
-
(bu !== '*' && properties.credentials[cred].businessUnits[bu]))
|
|
150
|
+
(bu !== '*' && !properties.credentials[cred].businessUnits[bu]))
|
|
151
151
|
) {
|
|
152
152
|
const buObject = await Cli.getCredentialObject(
|
|
153
153
|
properties,
|
|
@@ -220,7 +220,7 @@ class Mcdev {
|
|
|
220
220
|
for (const selectedType of Array.isArray(selectedTypesArr)
|
|
221
221
|
? selectedTypesArr
|
|
222
222
|
: Object.keys(selectedTypesArr)) {
|
|
223
|
-
const [type, subType] =
|
|
223
|
+
const [type, subType] = Util.getTypeAndSubType(selectedType);
|
|
224
224
|
const removePathArr = [properties.directories.retrieve, cred, bu, type];
|
|
225
225
|
if (
|
|
226
226
|
type &&
|
|
@@ -293,6 +293,15 @@ class Mcdev {
|
|
|
293
293
|
const properties = await config.getProperties(!!credentialsName, true);
|
|
294
294
|
await Init.initProject(properties, credentialsName);
|
|
295
295
|
}
|
|
296
|
+
/**
|
|
297
|
+
* Clones an existing project from git repository and installs it
|
|
298
|
+
*
|
|
299
|
+
* @returns {Promise.<void>} -
|
|
300
|
+
*/
|
|
301
|
+
static async joinProject() {
|
|
302
|
+
Util.logger.info('mcdev:: Joining an existing project');
|
|
303
|
+
await Init.joinProject();
|
|
304
|
+
}
|
|
296
305
|
|
|
297
306
|
/**
|
|
298
307
|
* Refreshes BU names and ID's from MC instance
|
|
@@ -338,7 +347,8 @@ class Mcdev {
|
|
|
338
347
|
);
|
|
339
348
|
if (buObject !== null) {
|
|
340
349
|
MetadataTypeInfo[type].properties = properties;
|
|
341
|
-
MetadataTypeInfo[type].
|
|
350
|
+
MetadataTypeInfo[type].buObject = buObject;
|
|
351
|
+
MetadataTypeInfo[type].document();
|
|
342
352
|
}
|
|
343
353
|
} catch (ex) {
|
|
344
354
|
Util.logger.error('mcdev.document ' + ex.message);
|
|
@@ -350,25 +360,59 @@ class Mcdev {
|
|
|
350
360
|
}
|
|
351
361
|
|
|
352
362
|
/**
|
|
353
|
-
*
|
|
363
|
+
* deletes metadata from MC instance by key
|
|
354
364
|
*
|
|
355
365
|
* @param {string} businessUnit references credentials from properties.json
|
|
356
366
|
* @param {string} type supported metadata type
|
|
357
|
-
* @param {string} customerKey Identifier of
|
|
367
|
+
* @param {string} customerKey Identifier of metadata
|
|
358
368
|
* @returns {Promise.<void>} -
|
|
359
369
|
*/
|
|
360
370
|
static async deleteByKey(businessUnit, type, customerKey) {
|
|
361
371
|
Util.logger.info('mcdev:: delete');
|
|
372
|
+
if (!Util._isValidType(type)) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
362
375
|
const properties = await config.getProperties();
|
|
363
376
|
if (!(await config.checkProperties(properties))) {
|
|
364
377
|
return null;
|
|
365
378
|
}
|
|
366
379
|
const buObject = await Cli.getCredentialObject(properties, businessUnit);
|
|
367
380
|
if (buObject !== null) {
|
|
368
|
-
|
|
369
|
-
|
|
381
|
+
try {
|
|
382
|
+
MetadataTypeInfo[type].client = auth.getSDK(buObject);
|
|
383
|
+
} catch (ex) {
|
|
384
|
+
Util.logger.error(ex.message);
|
|
370
385
|
return;
|
|
371
386
|
}
|
|
387
|
+
try {
|
|
388
|
+
MetadataTypeInfo[type].properties = properties;
|
|
389
|
+
MetadataTypeInfo[type].buObject = buObject;
|
|
390
|
+
await MetadataTypeInfo[type].deleteByKey(customerKey);
|
|
391
|
+
} catch (ex) {
|
|
392
|
+
Util.logger.errorStack(ex, ` - Deleting ${type} failed`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* ensures triggered sends are restarted to ensure they pick up on changes of the underlying emails
|
|
398
|
+
*
|
|
399
|
+
* @param {string} businessUnit references credentials from properties.json
|
|
400
|
+
* @param {string} type references credentials from properties.json
|
|
401
|
+
* @param {string[]} [keyArr] metadata keys
|
|
402
|
+
* @returns {Promise.<void>} -
|
|
403
|
+
*/
|
|
404
|
+
static async refresh(businessUnit, type, keyArr) {
|
|
405
|
+
Util.logger.info('mcdev:: refresh');
|
|
406
|
+
if (!type || !Util._isValidType(type, true)) {
|
|
407
|
+
type = 'triggeredSendDefinition';
|
|
408
|
+
Util.logger.info(' - setting type to ' + type);
|
|
409
|
+
}
|
|
410
|
+
const properties = await config.getProperties();
|
|
411
|
+
if (!(await config.checkProperties(properties))) {
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
414
|
+
const buObject = await Cli.getCredentialObject(properties, businessUnit);
|
|
415
|
+
if (buObject !== null) {
|
|
372
416
|
try {
|
|
373
417
|
MetadataTypeInfo[type].client = auth.getSDK(buObject);
|
|
374
418
|
} catch (ex) {
|
|
@@ -376,10 +420,12 @@ class Mcdev {
|
|
|
376
420
|
return;
|
|
377
421
|
}
|
|
378
422
|
try {
|
|
423
|
+
cache.initCache(buObject);
|
|
379
424
|
MetadataTypeInfo[type].properties = properties;
|
|
380
|
-
MetadataTypeInfo[type].
|
|
425
|
+
MetadataTypeInfo[type].buObject = buObject;
|
|
426
|
+
await MetadataTypeInfo[type].refresh(keyArr);
|
|
381
427
|
} catch (ex) {
|
|
382
|
-
Util.logger.
|
|
428
|
+
Util.logger.errorStack(ex, 'mcdev.refresh ' + ex.message);
|
|
383
429
|
}
|
|
384
430
|
}
|
|
385
431
|
}
|
|
@@ -472,7 +518,7 @@ class Mcdev {
|
|
|
472
518
|
if (!Util._isValidType(selectedType)) {
|
|
473
519
|
return;
|
|
474
520
|
}
|
|
475
|
-
const [type, subType] =
|
|
521
|
+
const [type, subType] = Util.getTypeAndSubType(selectedType);
|
|
476
522
|
|
|
477
523
|
let retrieveTypesArr;
|
|
478
524
|
if (
|
|
@@ -16,37 +16,34 @@ class AccountUser extends MetadataType {
|
|
|
16
16
|
*
|
|
17
17
|
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
18
18
|
* @param {void} _ unused parameter
|
|
19
|
-
* @param {
|
|
20
|
-
* @param {void} [___] unused parameter
|
|
19
|
+
* @param {void} [__] unused parameter
|
|
21
20
|
* @param {string} [key] customer key of single item to retrieve
|
|
22
21
|
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
|
|
23
22
|
*/
|
|
24
|
-
static async retrieve(retrieveDir, _,
|
|
25
|
-
if (buObject.eid !== buObject.mid) {
|
|
23
|
+
static async retrieve(retrieveDir, _, __, key) {
|
|
24
|
+
if (this.buObject.eid !== this.buObject.mid) {
|
|
26
25
|
Util.logger.info(' - Skipping User retrieval on non-parent BU');
|
|
27
26
|
return;
|
|
28
27
|
}
|
|
29
|
-
return this._retrieve(retrieveDir,
|
|
28
|
+
return this._retrieve(retrieveDir, key);
|
|
30
29
|
}
|
|
31
30
|
/**
|
|
32
31
|
* Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata
|
|
33
32
|
*
|
|
34
|
-
* @param {TYPE.BuObject} buObject properties for auth
|
|
35
33
|
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
|
|
36
34
|
*/
|
|
37
|
-
static async retrieveChangelog(
|
|
38
|
-
return this._retrieve(
|
|
35
|
+
static async retrieveChangelog() {
|
|
36
|
+
return this._retrieve();
|
|
39
37
|
}
|
|
40
38
|
/**
|
|
41
39
|
* Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata
|
|
42
40
|
*
|
|
43
41
|
* @private
|
|
44
42
|
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
45
|
-
* @param {TYPE.BuObject} buObject properties for auth
|
|
46
43
|
* @param {string} [key] customer key of single item to retrieve
|
|
47
44
|
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
|
|
48
45
|
*/
|
|
49
|
-
static async _retrieve(retrieveDir,
|
|
46
|
+
static async _retrieve(retrieveDir, key) {
|
|
50
47
|
Util.logger.info(' - Caching dependent Metadata: AccountUserAccount');
|
|
51
48
|
|
|
52
49
|
// get BUs that each users have access to
|
|
@@ -113,7 +110,7 @@ class AccountUser extends MetadataType {
|
|
|
113
110
|
};
|
|
114
111
|
}
|
|
115
112
|
Util.logger.info(` - Loading ${this.definition.type}. This might take a while...`);
|
|
116
|
-
return super.retrieveSOAP(retrieveDir,
|
|
113
|
+
return super.retrieveSOAP(retrieveDir, requestParams);
|
|
117
114
|
}
|
|
118
115
|
/**
|
|
119
116
|
*
|
|
@@ -175,24 +172,21 @@ class AccountUser extends MetadataType {
|
|
|
175
172
|
/**
|
|
176
173
|
* helper to print bu names
|
|
177
174
|
*
|
|
178
|
-
* @param {TYPE.BuObject} buObject needed for eid
|
|
179
|
-
* @param {string} buObject.eid needed to check for parent bu
|
|
180
175
|
* @param {number} id bu id
|
|
181
176
|
* @returns {string} "bu name (bu id)""
|
|
182
177
|
*/
|
|
183
|
-
static getBuName(
|
|
184
|
-
const name = buObject.eid == id ? '_ParentBU_' : this.buIdName[id];
|
|
178
|
+
static getBuName(id) {
|
|
179
|
+
const name = this.buObject.eid == id ? '_ParentBU_' : this.buIdName[id];
|
|
185
180
|
return `<nobr>${name} (${id})</nobr>`;
|
|
186
181
|
}
|
|
187
182
|
/**
|
|
188
183
|
* Creates markdown documentation of all roles
|
|
189
184
|
*
|
|
190
|
-
* @param {TYPE.BuObject} buObject properties for auth
|
|
191
185
|
* @param {TYPE.MetadataTypeMap} [metadata] user list
|
|
192
186
|
* @returns {Promise.<void>} -
|
|
193
187
|
*/
|
|
194
|
-
static async document(
|
|
195
|
-
if (buObject.eid !== buObject.mid) {
|
|
188
|
+
static async document(metadata) {
|
|
189
|
+
if (this.buObject.eid !== this.buObject.mid) {
|
|
196
190
|
Util.logger.error(
|
|
197
191
|
`Users can only be retrieved & documented for the ${Util.parentBuName}`
|
|
198
192
|
);
|
|
@@ -204,7 +198,7 @@ class AccountUser extends MetadataType {
|
|
|
204
198
|
metadata = this.readBUMetadataForType(
|
|
205
199
|
File.normalizePath([
|
|
206
200
|
this.properties.directories.retrieve,
|
|
207
|
-
buObject.credential,
|
|
201
|
+
this.buObject.credential,
|
|
208
202
|
Util.parentBuName,
|
|
209
203
|
]),
|
|
210
204
|
true
|
|
@@ -252,12 +246,12 @@ class AccountUser extends MetadataType {
|
|
|
252
246
|
if (user.AssociatedBusinessUnits__c) {
|
|
253
247
|
associatedBus = user.AssociatedBusinessUnits__c.map((item) => {
|
|
254
248
|
this.buIdName[item.ID] = item.Name;
|
|
255
|
-
return this.getBuName(
|
|
249
|
+
return this.getBuName(item.ID);
|
|
256
250
|
})
|
|
257
251
|
.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
|
|
258
252
|
.join(',<br> ');
|
|
259
253
|
}
|
|
260
|
-
const defaultBUName = this.getBuName(
|
|
254
|
+
const defaultBUName = this.getBuName(user.DefaultBusinessUnit);
|
|
261
255
|
users.push({
|
|
262
256
|
TYPE: user.type__c,
|
|
263
257
|
UserID: user.UserID,
|
|
@@ -297,7 +291,7 @@ class AccountUser extends MetadataType {
|
|
|
297
291
|
['Modified Date', 'ModifiedDate'],
|
|
298
292
|
['Created Date', 'CreatedDate'],
|
|
299
293
|
];
|
|
300
|
-
let output = `# User Overview - ${buObject.credential}`;
|
|
294
|
+
let output = `# User Overview - ${this.buObject.credential}`;
|
|
301
295
|
output += this._generateDocMd(
|
|
302
296
|
users.filter((user) => user.TYPE === 'User' && user.ActiveFlag === '✓'),
|
|
303
297
|
'User',
|
|
@@ -316,7 +310,7 @@ class AccountUser extends MetadataType {
|
|
|
316
310
|
const docPath = File.normalizePath([this.properties.directories.docs, 'user']);
|
|
317
311
|
|
|
318
312
|
try {
|
|
319
|
-
const filename = buObject.credential;
|
|
313
|
+
const filename = this.buObject.credential;
|
|
320
314
|
// write to disk
|
|
321
315
|
await File.writeToFile(docPath, filename + '.accountUsers', 'md', output);
|
|
322
316
|
Util.logger.info(`Created ${File.normalizePath([docPath, filename])}.accountUsers.md`);
|
|
@@ -19,17 +19,16 @@ class Asset extends MetadataType {
|
|
|
19
19
|
*
|
|
20
20
|
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
21
21
|
* @param {void} _ -
|
|
22
|
-
* @param {
|
|
23
|
-
* @param {TYPE.AssetSubType} [selectedSubType] optionally limit to a single subtype
|
|
22
|
+
* @param {TYPE.AssetSubType[]} [subTypeArr] optionally limit to a single subtype
|
|
24
23
|
* @param {string} [key] customer key
|
|
25
24
|
* @returns {Promise.<{metadata: TYPE.AssetMap, type: string}>} Promise
|
|
26
25
|
*/
|
|
27
|
-
static async retrieve(retrieveDir, _,
|
|
26
|
+
static async retrieve(retrieveDir, _, subTypeArr, key) {
|
|
28
27
|
const items = [];
|
|
29
|
-
|
|
28
|
+
subTypeArr = subTypeArr || this._getSubTypes();
|
|
30
29
|
await File.initPrettier();
|
|
31
30
|
// loop through subtypes and return results of each subType for caching (saving is handled per subtype)
|
|
32
|
-
for (const subType of
|
|
31
|
+
for (const subType of subTypeArr) {
|
|
33
32
|
// each subtype contains multiple different specific types (images contains jpg and png for example)
|
|
34
33
|
// we use await here to limit the risk of too many concurrent api requests at time
|
|
35
34
|
items.push(
|
|
@@ -46,7 +45,8 @@ class Asset extends MetadataType {
|
|
|
46
45
|
const metadata = this.parseResponseBody({ items: items });
|
|
47
46
|
if (retrieveDir) {
|
|
48
47
|
Util.logger.info(
|
|
49
|
-
`Downloaded: ${this.definition.type} (${Object.keys(metadata).length})`
|
|
48
|
+
`Downloaded: ${this.definition.type} (${Object.keys(metadata).length})` +
|
|
49
|
+
Util.getKeysString(key)
|
|
50
50
|
);
|
|
51
51
|
}
|
|
52
52
|
return { metadata: metadata, type: this.definition.type };
|
|
@@ -55,12 +55,12 @@ class Asset extends MetadataType {
|
|
|
55
55
|
/**
|
|
56
56
|
* Retrieves asset metadata for caching
|
|
57
57
|
*
|
|
58
|
-
* @param {void} _
|
|
59
|
-
* @param {string} [
|
|
58
|
+
* @param {void} _ unused
|
|
59
|
+
* @param {string[]} [subTypeArr] optionally limit to a single subtype
|
|
60
60
|
* @returns {Promise.<{metadata: TYPE.AssetMap, type: string}>} Promise
|
|
61
61
|
*/
|
|
62
|
-
static retrieveForCache(_,
|
|
63
|
-
return this.retrieve(null, null,
|
|
62
|
+
static retrieveForCache(_, subTypeArr) {
|
|
63
|
+
return this.retrieve(null, null, subTypeArr);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
@@ -507,10 +507,9 @@ class Asset extends MetadataType {
|
|
|
507
507
|
*
|
|
508
508
|
* @param {TYPE.AssetItem} metadata a single asset
|
|
509
509
|
* @param {string} deployDir directory of deploy files
|
|
510
|
-
* @param {TYPE.BuObject} buObject buObject properties for auth
|
|
511
510
|
* @returns {Promise.<TYPE.AssetItem>} Promise
|
|
512
511
|
*/
|
|
513
|
-
static async preDeployTasks(metadata, deployDir
|
|
512
|
+
static async preDeployTasks(metadata, deployDir) {
|
|
514
513
|
// additonalattributes fail where the value is "" so we need to remove them from deploy
|
|
515
514
|
if (metadata?.data?.email?.attributes?.length > 0) {
|
|
516
515
|
metadata.data.email.attributes = metadata.data.email.attributes.filter(
|
|
@@ -519,10 +518,7 @@ class Asset extends MetadataType {
|
|
|
519
518
|
}
|
|
520
519
|
|
|
521
520
|
// folder
|
|
522
|
-
metadata
|
|
523
|
-
id: cache.searchForField('folder', metadata.r__folder_Path, 'Path', 'ID'),
|
|
524
|
-
};
|
|
525
|
-
delete metadata.r__folder_Path;
|
|
521
|
+
this.setFolderId(metadata);
|
|
526
522
|
|
|
527
523
|
// restore asset type id which is needed for deploy
|
|
528
524
|
metadata.assetType.id = this.definition.typeMapping[metadata.assetType.name];
|
|
@@ -538,13 +534,13 @@ class Asset extends MetadataType {
|
|
|
538
534
|
|
|
539
535
|
// only execute #3 if we are deploying / copying from one BU to another, not while using mcdev as a developer tool
|
|
540
536
|
if (
|
|
541
|
-
buObject.mid &&
|
|
542
|
-
metadata.memberId !== buObject.mid &&
|
|
543
|
-
!metadata[this.definition.keyField].endsWith(buObject.mid)
|
|
537
|
+
this.buObject.mid &&
|
|
538
|
+
metadata.memberId !== this.buObject.mid &&
|
|
539
|
+
!metadata[this.definition.keyField].endsWith(this.buObject.mid)
|
|
544
540
|
) {
|
|
545
541
|
// #3 make sure customer key is unique by suffixing it with target MID (unless we are deploying to the same MID)
|
|
546
542
|
// check if this suffixed with the source MID
|
|
547
|
-
const suffix = '-' + buObject.mid;
|
|
543
|
+
const suffix = '-' + this.buObject.mid;
|
|
548
544
|
// for customer key max is 36 chars
|
|
549
545
|
metadata[this.definition.keyField] =
|
|
550
546
|
metadata[this.definition.keyField].slice(0, Math.max(0, 36 - suffix.length)) +
|
|
@@ -610,7 +606,7 @@ class Asset extends MetadataType {
|
|
|
610
606
|
*
|
|
611
607
|
* @private
|
|
612
608
|
* @param {TYPE.AssetItem} metadata a single asset
|
|
613
|
-
* @returns {TYPE.AssetSubType} subtype
|
|
609
|
+
* @returns {TYPE.AssetSubType | void} subtype
|
|
614
610
|
*/
|
|
615
611
|
static _getSubtype(metadata) {
|
|
616
612
|
for (const sub in this.definition.extendedSubTypes) {
|
|
@@ -790,6 +786,17 @@ class Asset extends MetadataType {
|
|
|
790
786
|
);
|
|
791
787
|
}
|
|
792
788
|
}
|
|
789
|
+
/**
|
|
790
|
+
* Asset-specific script that retrieves the folder ID from cache and updates the given metadata with it before deploy
|
|
791
|
+
*
|
|
792
|
+
* @param {TYPE.MetadataTypeItem} metadata a single item
|
|
793
|
+
*/
|
|
794
|
+
static setFolderId(metadata) {
|
|
795
|
+
metadata.category = {
|
|
796
|
+
id: cache.searchForField('folder', metadata.r__folder_Path, 'Path', 'ID'),
|
|
797
|
+
};
|
|
798
|
+
delete metadata.r__folder_Path;
|
|
799
|
+
}
|
|
793
800
|
|
|
794
801
|
/**
|
|
795
802
|
* helper for {@link preDeployTasks} that loads extracted code content back into JSON
|
|
@@ -15,11 +15,10 @@ class AttributeGroup extends MetadataType {
|
|
|
15
15
|
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
16
16
|
* @param {void} [_] unused parameter
|
|
17
17
|
* @param {void} [__] unused parameter
|
|
18
|
-
* @param {void} [___] unused parameter
|
|
19
18
|
* @param {string} [key] customer key of single item to retrieve
|
|
20
19
|
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
|
|
21
20
|
*/
|
|
22
|
-
static retrieve(retrieveDir, _, __,
|
|
21
|
+
static retrieve(retrieveDir, _, __, key) {
|
|
23
22
|
return super.retrieveREST(
|
|
24
23
|
retrieveDir,
|
|
25
24
|
'/hub/v1/contacts/schema/attributeGroups',
|