mcdev 3.0.1 → 3.1.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/.eslintrc.json +1 -1
- package/.github/ISSUE_TEMPLATE/bug.yml +72 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- package/.github/ISSUE_TEMPLATE/task.md +10 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +11 -0
- package/.issuetracker +11 -3
- package/.vscode/settings.json +3 -3
- package/CHANGELOG.md +103 -1
- package/README.md +245 -141
- package/boilerplate/config.json +3 -2
- package/docs/dist/documentation.md +803 -337
- package/lib/Deployer.js +4 -1
- package/lib/MetadataTypeDefinitions.js +1 -0
- package/lib/MetadataTypeInfo.js +1 -0
- package/lib/Retriever.js +32 -17
- package/lib/cli.js +295 -0
- package/lib/index.js +774 -1019
- package/lib/metadataTypes/AccountUser.js +389 -0
- package/lib/metadataTypes/Asset.js +20 -12
- package/lib/metadataTypes/Automation.js +115 -52
- package/lib/metadataTypes/DataExtension.js +159 -113
- package/lib/metadataTypes/DataExtensionField.js +134 -4
- package/lib/metadataTypes/Folder.js +66 -69
- package/lib/metadataTypes/ImportFile.js +4 -6
- package/lib/metadataTypes/MetadataType.js +136 -67
- package/lib/metadataTypes/Query.js +2 -3
- package/lib/metadataTypes/Role.js +13 -8
- package/lib/metadataTypes/definitions/AccountUser.definition.js +227 -0
- package/lib/metadataTypes/definitions/Asset.definition.js +1 -0
- package/lib/metadataTypes/definitions/Campaign.definition.js +1 -1
- package/lib/metadataTypes/definitions/DataExtension.definition.js +1 -1
- package/lib/metadataTypes/definitions/DataExtensionField.definition.js +1 -1
- package/lib/metadataTypes/definitions/Folder.definition.js +1 -1
- package/lib/metadataTypes/definitions/ImportFile.definition.js +2 -1
- package/lib/metadataTypes/definitions/Script.definition.js +5 -5
- package/lib/retrieveChangelog.js +96 -0
- package/lib/util/cli.js +4 -6
- package/lib/util/init.git.js +2 -1
- package/lib/util/util.js +31 -15
- package/package.json +19 -23
- package/img/README.md/troubleshoot-nodejs-postinstall.jpg +0 -0
- package/postinstall.js +0 -41
|
@@ -13,16 +13,16 @@ class Folder extends MetadataType {
|
|
|
13
13
|
/**
|
|
14
14
|
* Retrieves metadata of metadata type into local filesystem. executes callback with retrieved metadata
|
|
15
15
|
* @param {String} retrieveDir Directory where retrieved metadata directory will be saved
|
|
16
|
-
* @param {String[]} [
|
|
16
|
+
* @param {String[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true
|
|
17
17
|
* @param {Object} buObject properties for auth
|
|
18
18
|
* @returns {Promise} Promise
|
|
19
19
|
*/
|
|
20
|
-
static async retrieve(retrieveDir,
|
|
21
|
-
const queryAllFolders = await this.retrieveHelper(
|
|
20
|
+
static async retrieve(retrieveDir, additionalFields, buObject) {
|
|
21
|
+
const queryAllFolders = await this.retrieveHelper(additionalFields, true);
|
|
22
22
|
// if this is the parent, no need to query twice as QueryAllAccounts works.
|
|
23
23
|
|
|
24
24
|
if (buObject.eid !== buObject.mid) {
|
|
25
|
-
queryAllFolders.push(...(await this.retrieveHelper(
|
|
25
|
+
queryAllFolders.push(...(await this.retrieveHelper(additionalFields, false)));
|
|
26
26
|
}
|
|
27
27
|
const sortPairs = toposort(queryAllFolders.map((a) => [a.ParentFolder.ID, a.ID]));
|
|
28
28
|
const idMap = {};
|
|
@@ -258,39 +258,36 @@ class Folder extends MetadataType {
|
|
|
258
258
|
* @param {Object} metadata metadata of the folder
|
|
259
259
|
* @returns {Promise} Promise
|
|
260
260
|
*/
|
|
261
|
-
static create(metadata) {
|
|
262
|
-
|
|
261
|
+
static async create(metadata) {
|
|
262
|
+
if (metadata.Parent && metadata.Parent.ID && metadata.Parent.ID === 0) {
|
|
263
|
+
Util.logger.error(
|
|
264
|
+
`${this.definition.type}-${metadata.ContentType}.create:: Cannot create Root Folder: ${metadata.Name}`
|
|
265
|
+
);
|
|
266
|
+
return {};
|
|
267
|
+
}
|
|
263
268
|
const path = metadata.Path;
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
if (
|
|
269
|
+
try {
|
|
270
|
+
const response = await super.createSOAP(metadata, 'DataFolder', true);
|
|
271
|
+
if (response) {
|
|
272
|
+
response.body.Results[0].Object = metadata;
|
|
273
|
+
response.body.Results[0].Object.ID = response.body.Results[0].NewID;
|
|
274
|
+
response.body.Results[0].Object.CustomerKey = metadata.CustomerKey;
|
|
275
|
+
delete response.body.Results[0].Object.$;
|
|
276
|
+
|
|
277
|
+
Util.logger.info(`- created folder: ${path}`);
|
|
278
|
+
return response;
|
|
279
|
+
}
|
|
280
|
+
} catch (ex) {
|
|
281
|
+
if (ex && ex.results) {
|
|
267
282
|
Util.logger.error(
|
|
268
|
-
`${this.definition.type}-${metadata.ContentType}.create::
|
|
283
|
+
`${this.definition.type}-${metadata.ContentType}.create:: error creating: '${path}'. ${ex.results[0].StatusMessage}`
|
|
284
|
+
);
|
|
285
|
+
} else if (ex) {
|
|
286
|
+
Util.logger.error(
|
|
287
|
+
`${this.definition.type}-${metadata.ContentType}.create:: error creating: '${path}'. ${ex.message}`
|
|
269
288
|
);
|
|
270
|
-
resolve({});
|
|
271
|
-
} else {
|
|
272
|
-
this.client.SoapClient.create('DataFolder', metadata, null, (ex, response) => {
|
|
273
|
-
if (ex && ex.results) {
|
|
274
|
-
Util.logger.error(
|
|
275
|
-
`${this.definition.type}-${metadata.ContentType}.create:: error creating: ${path}. ${ex.results[0].StatusMessage}`
|
|
276
|
-
);
|
|
277
|
-
resolve();
|
|
278
|
-
} else if (ex) {
|
|
279
|
-
Util.logger.error(
|
|
280
|
-
`${this.definition.type}-${metadata.ContentType}.create:: error creating: ${path}. ${ex.message}`
|
|
281
|
-
);
|
|
282
|
-
resolve();
|
|
283
|
-
} else {
|
|
284
|
-
response.body.Results[0].Object = metadata;
|
|
285
|
-
response.body.Results[0].Object.ID = response.body.Results[0].NewID;
|
|
286
|
-
response.body.Results[0].Object.CustomerKey = tempCustomerKey;
|
|
287
|
-
delete response.body.Results[0].Object.$;
|
|
288
|
-
Util.logger.info(`- created folder: ${path}`);
|
|
289
|
-
resolve(response);
|
|
290
|
-
}
|
|
291
|
-
});
|
|
292
289
|
}
|
|
293
|
-
}
|
|
290
|
+
}
|
|
294
291
|
}
|
|
295
292
|
|
|
296
293
|
/**
|
|
@@ -299,30 +296,27 @@ class Folder extends MetadataType {
|
|
|
299
296
|
* @returns {Promise} Promise
|
|
300
297
|
*/
|
|
301
298
|
static async update(metadata) {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
}
|
|
324
|
-
});
|
|
325
|
-
});
|
|
299
|
+
const path = metadata.Path;
|
|
300
|
+
try {
|
|
301
|
+
const response = await super.updateSOAP(metadata, 'DataFolder', true);
|
|
302
|
+
if (response) {
|
|
303
|
+
response.body.Results[0].Object = metadata;
|
|
304
|
+
response.body.Results[0].Object.CustomerKey = metadata.CustomerKey;
|
|
305
|
+
delete response.body.Results[0].Object.$;
|
|
306
|
+
Util.logger.info(`- updated folder: ${path}`);
|
|
307
|
+
return response;
|
|
308
|
+
}
|
|
309
|
+
} catch (ex) {
|
|
310
|
+
if (ex && ex.results) {
|
|
311
|
+
Util.logger.error(
|
|
312
|
+
`${this.definition.type}-${metadata.ContentType}.update:: error updating: '${path}'. ${ex.results[0].StatusMessage}`
|
|
313
|
+
);
|
|
314
|
+
} else if (ex) {
|
|
315
|
+
Util.logger.error(
|
|
316
|
+
`${this.definition.type}-${metadata.ContentType}.update:: error updating: '${path}'. ${ex.message}`
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
326
320
|
}
|
|
327
321
|
|
|
328
322
|
/**
|
|
@@ -451,25 +445,28 @@ class Folder extends MetadataType {
|
|
|
451
445
|
|
|
452
446
|
/**
|
|
453
447
|
* Helper to retrieve the folders as promise
|
|
454
|
-
* @param {String[]} [
|
|
448
|
+
* @param {String[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true
|
|
455
449
|
* @param {Boolean} [queryAllAccounts] which queryAllAccounts setting to use
|
|
456
450
|
* @returns {Promise<Object>} soap object
|
|
457
451
|
*/
|
|
458
|
-
static async retrieveHelper(
|
|
452
|
+
static async retrieveHelper(additionalFields, queryAllAccounts) {
|
|
459
453
|
const options = { queryAllAccounts: !!queryAllAccounts };
|
|
460
454
|
let status = 'MoreDataAvailable';
|
|
461
455
|
const Results = [];
|
|
462
456
|
do {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
this.
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
457
|
+
let response;
|
|
458
|
+
await Util.retryOnError(`Retrying ${this.definition.type}`, async () => {
|
|
459
|
+
response = await new Promise((resolve, reject) => {
|
|
460
|
+
// filtered out path as we need them to be stored locally, but do not want to try and retrieve
|
|
461
|
+
this.client.SoapClient.retrieve(
|
|
462
|
+
'DataFolder',
|
|
463
|
+
this.getFieldNamesToRetrieve(additionalFields).filter(
|
|
464
|
+
(field) => !field.includes('Path')
|
|
465
|
+
),
|
|
466
|
+
options,
|
|
467
|
+
(ex, response) => (ex ? reject(ex) : resolve(response))
|
|
468
|
+
);
|
|
469
|
+
});
|
|
473
470
|
});
|
|
474
471
|
// merge results with existing
|
|
475
472
|
Results.push(...response.body.Results);
|
|
@@ -147,12 +147,10 @@ class ImportFile extends MetadataType {
|
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
// When the destinationObjectTypeId is 584 is refers to Mobile Connect which is not supported as an Import Type
|
|
150
|
-
metadata.destinationObjectTypeId =
|
|
151
|
-
metadata.c__destinationType
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
metadata.c__subscriberImportType
|
|
155
|
-
];
|
|
150
|
+
metadata.destinationObjectTypeId =
|
|
151
|
+
this.definition.destinationObjectTypeMapping[metadata.c__destinationType];
|
|
152
|
+
metadata.subscriberImportTypeId =
|
|
153
|
+
this.definition.subscriberImportTypeMapping[metadata.c__subscriberImportType];
|
|
156
154
|
metadata.updateTypeId = this.definition.updateTypeMapping[metadata.c__dataAction];
|
|
157
155
|
return metadata;
|
|
158
156
|
}
|
|
@@ -194,16 +194,26 @@ class MetadataType {
|
|
|
194
194
|
/**
|
|
195
195
|
* Gets metadata from Marketing Cloud
|
|
196
196
|
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
197
|
-
* @param {string[]} [
|
|
197
|
+
* @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true
|
|
198
198
|
* @param {Util.BuObject} buObject properties for auth
|
|
199
199
|
* @param {string} [subType] optionally limit to a single subtype
|
|
200
200
|
* @returns {Promise<{metadata:MetadataTypeMap,type:string}>} metadata
|
|
201
201
|
*/
|
|
202
|
-
static retrieve(retrieveDir,
|
|
202
|
+
static retrieve(retrieveDir, additionalFields, buObject, subType) {
|
|
203
203
|
Util.metadataLogger('error', this.definition.type, 'retrieve', `Not Supported`);
|
|
204
204
|
const metadata = {};
|
|
205
205
|
return { metadata: null, type: this.definition.type };
|
|
206
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Gets metadata from Marketing Cloud
|
|
209
|
+
* @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true
|
|
210
|
+
* @param {Util.BuObject} buObject properties for auth
|
|
211
|
+
* @param {string} [subType] optionally limit to a single subtype
|
|
212
|
+
* @returns {Promise<{metadata:MetadataTypeMap,type:string}>} metadata
|
|
213
|
+
*/
|
|
214
|
+
static retrieveChangelog(additionalFields, buObject, subType) {
|
|
215
|
+
return this.retrieve(null, additionalFields, buObject, subType);
|
|
216
|
+
}
|
|
207
217
|
|
|
208
218
|
/**
|
|
209
219
|
* Gets metadata cache with limited fields and does not store value to disk
|
|
@@ -304,9 +314,10 @@ class MetadataType {
|
|
|
304
314
|
});
|
|
305
315
|
} else if (this.cache[this.definition.type][normalizedKey]) {
|
|
306
316
|
// normal way of processing update files
|
|
307
|
-
metadata[metadataKey][this.definition.idField] =
|
|
308
|
-
this.definition.type
|
|
309
|
-
|
|
317
|
+
metadata[metadataKey][this.definition.idField] =
|
|
318
|
+
this.cache[this.definition.type][normalizedKey][
|
|
319
|
+
this.definition.idField
|
|
320
|
+
];
|
|
310
321
|
metadataToUpdate.push({
|
|
311
322
|
before: this.cache[this.definition.type][normalizedKey],
|
|
312
323
|
after: metadata[metadataKey],
|
|
@@ -403,31 +414,54 @@ class MetadataType {
|
|
|
403
414
|
/**
|
|
404
415
|
* Creates a single metadata entry via fuel-soap (generic lib not wrapper)
|
|
405
416
|
* @param {MetadataTypeItem} metadataEntry single metadata entry
|
|
417
|
+
* @param {string} [overrideType] can be used if the API type differs from the otherwise used type identifier
|
|
418
|
+
* @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method
|
|
406
419
|
* @returns {Promise} Promise
|
|
407
420
|
*/
|
|
408
|
-
static async createSOAP(metadataEntry) {
|
|
421
|
+
static async createSOAP(metadataEntry, overrideType, handleOutside) {
|
|
409
422
|
try {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
metadataEntry
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
423
|
+
this.removeNotCreateableFields(metadataEntry);
|
|
424
|
+
let response;
|
|
425
|
+
await Util.retryOnError(
|
|
426
|
+
`Retrying to create ${this.definition.type}: ${
|
|
427
|
+
metadataEntry[this.definition.nameField]
|
|
428
|
+
}`,
|
|
429
|
+
async () =>
|
|
430
|
+
(response = await new Promise((resolve, reject) => {
|
|
431
|
+
this.client.SoapClient.create(
|
|
432
|
+
overrideType ||
|
|
433
|
+
this.definition.type.charAt(0).toUpperCase() +
|
|
434
|
+
this.definition.type.slice(1),
|
|
435
|
+
metadataEntry,
|
|
436
|
+
null,
|
|
437
|
+
(error, response) => (error ? reject(error) : resolve(response))
|
|
438
|
+
);
|
|
439
|
+
}))
|
|
421
440
|
);
|
|
422
|
-
|
|
441
|
+
if (!handleOutside) {
|
|
442
|
+
Util.logger.info(
|
|
443
|
+
`- created ${this.definition.type}: ${metadataEntry[this.definition.keyField]}`
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
return response;
|
|
423
447
|
} catch (ex) {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
448
|
+
if (!handleOutside) {
|
|
449
|
+
let errorMsg;
|
|
450
|
+
if (ex.results && ex.results.length) {
|
|
451
|
+
errorMsg = `${ex.results[0].StatusMessage} (Code ${ex.results[0].ErrorCode})`;
|
|
452
|
+
} else {
|
|
453
|
+
errorMsg = ex.message;
|
|
454
|
+
}
|
|
455
|
+
Util.logger.error(
|
|
456
|
+
`- error creating ${this.definition.type} '${
|
|
457
|
+
metadataEntry[this.definition.keyField]
|
|
458
|
+
}': ${errorMsg}`
|
|
459
|
+
);
|
|
460
|
+
} else {
|
|
461
|
+
throw ex;
|
|
462
|
+
}
|
|
429
463
|
|
|
430
|
-
return
|
|
464
|
+
return {};
|
|
431
465
|
}
|
|
432
466
|
}
|
|
433
467
|
|
|
@@ -451,8 +485,12 @@ class MetadataType {
|
|
|
451
485
|
async () => (response = await this.client.RestClient.patch(options))
|
|
452
486
|
);
|
|
453
487
|
this.checkForErrors(response);
|
|
488
|
+
// some times, e.g. automation dont return a key in their update response and hence we need to fall back to name
|
|
454
489
|
Util.logger.info(
|
|
455
|
-
`- updated ${this.definition.type}: ${
|
|
490
|
+
`- updated ${this.definition.type}: ${
|
|
491
|
+
metadataEntry[this.definition.keyField] ||
|
|
492
|
+
metadataEntry[this.definition.nameField]
|
|
493
|
+
}`
|
|
456
494
|
);
|
|
457
495
|
return response;
|
|
458
496
|
} catch (ex) {
|
|
@@ -468,31 +506,54 @@ class MetadataType {
|
|
|
468
506
|
/**
|
|
469
507
|
* Updates a single metadata entry via fuel-soap (generic lib not wrapper)
|
|
470
508
|
* @param {MetadataTypeItem} metadataEntry single metadata entry
|
|
509
|
+
* @param {string} [overrideType] can be used if the API type differs from the otherwise used type identifier
|
|
510
|
+
* @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method
|
|
471
511
|
* @returns {Promise} Promise
|
|
472
512
|
*/
|
|
473
|
-
static async updateSOAP(metadataEntry) {
|
|
513
|
+
static async updateSOAP(metadataEntry, overrideType, handleOutside) {
|
|
514
|
+
let response;
|
|
474
515
|
try {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
this.
|
|
478
|
-
this.definition.
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
(
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
516
|
+
this.removeNotUpdateableFields(metadataEntry);
|
|
517
|
+
await Util.retryOnError(
|
|
518
|
+
`Retrying to update ${this.definition.type}: ${
|
|
519
|
+
metadataEntry[this.definition.nameField]
|
|
520
|
+
}`,
|
|
521
|
+
async () =>
|
|
522
|
+
(response = await new Promise((resolve, reject) => {
|
|
523
|
+
this.client.SoapClient.update(
|
|
524
|
+
overrideType ||
|
|
525
|
+
this.definition.type.charAt(0).toUpperCase() +
|
|
526
|
+
this.definition.type.slice(1),
|
|
527
|
+
metadataEntry,
|
|
528
|
+
null,
|
|
529
|
+
(error, response) => (error ? reject(error) : resolve(response))
|
|
530
|
+
);
|
|
531
|
+
}))
|
|
486
532
|
);
|
|
487
|
-
|
|
533
|
+
if (!handleOutside) {
|
|
534
|
+
Util.logger.info(
|
|
535
|
+
`- updated ${this.definition.type}: ${metadataEntry[this.definition.keyField]}`
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
return response;
|
|
488
539
|
} catch (ex) {
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
540
|
+
if (!handleOutside) {
|
|
541
|
+
let errorMsg;
|
|
542
|
+
if (ex.results && ex.results.length) {
|
|
543
|
+
errorMsg = `${ex.results[0].StatusMessage} (Code ${ex.results[0].ErrorCode})`;
|
|
544
|
+
} else {
|
|
545
|
+
errorMsg = ex.message;
|
|
546
|
+
}
|
|
547
|
+
Util.logger.error(
|
|
548
|
+
`- error updating ${this.definition.type} '${
|
|
549
|
+
metadataEntry[this.definition.keyField]
|
|
550
|
+
}': ${errorMsg}`
|
|
551
|
+
);
|
|
552
|
+
} else {
|
|
553
|
+
throw ex;
|
|
554
|
+
}
|
|
494
555
|
|
|
495
|
-
return
|
|
556
|
+
return {};
|
|
496
557
|
}
|
|
497
558
|
}
|
|
498
559
|
/**
|
|
@@ -501,18 +562,24 @@ class MetadataType {
|
|
|
501
562
|
* @param {Util.BuObject} buObject properties for auth
|
|
502
563
|
* @param {Object} [options] required for the specific request (filter for example)
|
|
503
564
|
* @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true
|
|
565
|
+
* @param {string} [overrideType] can be used if the API type differs from the otherwise used type identifier
|
|
504
566
|
* @returns {Promise<{metadata:MetadataTypeMap,type:string}>} Promise of item map
|
|
505
567
|
*/
|
|
506
|
-
static async retrieveSOAPgeneric(
|
|
568
|
+
static async retrieveSOAPgeneric(
|
|
569
|
+
retrieveDir,
|
|
570
|
+
buObject,
|
|
571
|
+
options,
|
|
572
|
+
additionalFields,
|
|
573
|
+
overrideType
|
|
574
|
+
) {
|
|
507
575
|
const fields = this.getFieldNamesToRetrieve(additionalFields);
|
|
508
576
|
|
|
509
|
-
const metadata = await this.retrieveSOAPBody(fields, options);
|
|
577
|
+
const metadata = await this.retrieveSOAPBody(fields, options, overrideType);
|
|
510
578
|
if (retrieveDir) {
|
|
511
579
|
const savedMetadata = await this.saveResults(metadata, retrieveDir, null);
|
|
512
580
|
Util.logger.info(
|
|
513
581
|
`Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})`
|
|
514
582
|
);
|
|
515
|
-
|
|
516
583
|
if (
|
|
517
584
|
buObject &&
|
|
518
585
|
this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)
|
|
@@ -536,23 +603,27 @@ class MetadataType {
|
|
|
536
603
|
options = options || {};
|
|
537
604
|
let metadata = {};
|
|
538
605
|
do {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
606
|
+
let resultsBatch;
|
|
607
|
+
await Util.retryOnError(`Retrying ${this.definition.type}`, async () => {
|
|
608
|
+
resultsBatch = await new Promise((resolve, reject) => {
|
|
609
|
+
this.client.SoapClient.retrieve(
|
|
610
|
+
type || this.definition.type,
|
|
611
|
+
fields,
|
|
612
|
+
options || {},
|
|
613
|
+
(error, response) => {
|
|
614
|
+
if (error) {
|
|
615
|
+
Util.logger.debug(`SOAP.retrieve Error: ${error.message}`);
|
|
616
|
+
reject(error);
|
|
617
|
+
}
|
|
618
|
+
if (response) {
|
|
619
|
+
resolve(response.body);
|
|
620
|
+
} else {
|
|
621
|
+
// fallback, lets make sure surrounding methods know we got an empty result back
|
|
622
|
+
resolve({});
|
|
623
|
+
}
|
|
547
624
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
} else {
|
|
551
|
-
// fallback, lets make sure surrounding methods know we got an empty result back
|
|
552
|
-
resolve({});
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
);
|
|
625
|
+
);
|
|
626
|
+
});
|
|
556
627
|
});
|
|
557
628
|
status = resultsBatch.OverallStatus;
|
|
558
629
|
if (status === 'MoreDataAvailable') {
|
|
@@ -591,11 +662,9 @@ class MetadataType {
|
|
|
591
662
|
do {
|
|
592
663
|
options.uri = this.paginate(options.uri, lastPage);
|
|
593
664
|
let response;
|
|
594
|
-
|
|
665
|
+
await Util.retryOnError(`Retrying ${this.definition.type}`, async () => {
|
|
595
666
|
response = await this.client.RestClient.get(options);
|
|
596
|
-
}
|
|
597
|
-
Util.logger.debug(ex.message);
|
|
598
|
-
}
|
|
667
|
+
});
|
|
599
668
|
const metadata = this.parseResponseBody(response.body);
|
|
600
669
|
results = Object.assign(results, metadata);
|
|
601
670
|
if (
|
|
@@ -144,9 +144,8 @@ class Query extends MetadataType {
|
|
|
144
144
|
} catch (ex) {
|
|
145
145
|
throw new Error(`Query '${metadata.key}': ${ex.message}`);
|
|
146
146
|
}
|
|
147
|
-
metadata.targetUpdateTypeId =
|
|
148
|
-
metadata.targetUpdateTypeName
|
|
149
|
-
];
|
|
147
|
+
metadata.targetUpdateTypeId =
|
|
148
|
+
this.definition.targetUpdateTypeMapping[metadata.targetUpdateTypeName];
|
|
150
149
|
return metadata;
|
|
151
150
|
}
|
|
152
151
|
|
|
@@ -107,14 +107,19 @@ class Role extends MetadataType {
|
|
|
107
107
|
return;
|
|
108
108
|
}
|
|
109
109
|
if (!metadata) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
try {
|
|
111
|
+
metadata = this.readBUMetadataForType(
|
|
112
|
+
File.normalizePath([
|
|
113
|
+
this.properties.directories.retrieve,
|
|
114
|
+
buObject.credential,
|
|
115
|
+
Util.parentBuName,
|
|
116
|
+
]),
|
|
117
|
+
true
|
|
118
|
+
).role;
|
|
119
|
+
} catch (ex) {
|
|
120
|
+
Util.logger.error(ex.message);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
118
123
|
}
|
|
119
124
|
const directory = this.properties.directories.roles;
|
|
120
125
|
|