mcdev 5.2.0 → 6.0.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/.eslintrc.json +1 -1
- package/.fork/custom-commands.json +12 -0
- package/.github/ISSUE_TEMPLATE/bug.yml +2 -0
- package/.github/PULL_REQUEST_TEMPLATE/pr_template_release.md +19 -0
- package/.github/workflows/code-test.yml +1 -1
- package/.github/workflows/coverage-base-update.yml +1 -1
- package/.github/workflows/coverage-develop-branch.yml +2 -2
- package/.github/workflows/coverage-main-branch.yml +2 -2
- package/.github/workflows/coverage.yml +2 -2
- package/.github/workflows/npm-publish.yml +2 -2
- package/.prettierrc +7 -0
- package/docs/dist/documentation.md +388 -482
- package/jsconfig.json +5 -1
- package/lib/Builder.js +8 -8
- package/lib/Deployer.js +10 -10
- package/lib/MetadataTypeDefinitions.js +73 -38
- package/lib/MetadataTypeInfo.js +72 -37
- package/lib/Retriever.js +8 -8
- package/lib/cli.js +12 -7
- package/lib/index.js +28 -18
- package/lib/metadataTypes/Asset.js +12 -10
- package/lib/metadataTypes/AttributeGroup.js +7 -6
- package/lib/metadataTypes/AttributeSet.js +126 -18
- package/lib/metadataTypes/Automation.js +107 -78
- package/lib/metadataTypes/Campaign.js +7 -6
- package/lib/metadataTypes/ContentArea.js +7 -6
- package/lib/metadataTypes/DataExtension.js +475 -78
- package/lib/metadataTypes/DataExtensionField.js +36 -18
- package/lib/metadataTypes/DataExtensionTemplate.js +5 -4
- package/lib/metadataTypes/DataExtract.js +8 -7
- package/lib/metadataTypes/DataExtractType.js +5 -4
- package/lib/metadataTypes/Discovery.js +6 -5
- package/lib/metadataTypes/Email.js +6 -5
- package/lib/metadataTypes/EmailSend.js +7 -6
- package/lib/metadataTypes/Event.js +8 -7
- package/lib/metadataTypes/FileLocation.js +5 -4
- package/lib/metadataTypes/FileTransfer.js +8 -7
- package/lib/metadataTypes/Filter.js +5 -4
- package/lib/metadataTypes/Folder.js +9 -8
- package/lib/metadataTypes/ImportFile.js +8 -7
- package/lib/metadataTypes/Journey.js +17 -9
- package/lib/metadataTypes/List.js +9 -8
- package/lib/metadataTypes/MetadataType.js +100 -34
- package/lib/metadataTypes/MobileCode.js +5 -4
- package/lib/metadataTypes/MobileKeyword.js +9 -8
- package/lib/metadataTypes/MobileMessage.js +8 -7
- package/lib/metadataTypes/Query.js +9 -8
- package/lib/metadataTypes/Role.js +8 -7
- package/lib/metadataTypes/Script.js +7 -6
- package/lib/metadataTypes/SendClassification.js +5 -4
- package/lib/metadataTypes/TransactionalEmail.js +101 -23
- package/lib/metadataTypes/TransactionalMessage.js +9 -7
- package/lib/metadataTypes/TransactionalPush.js +7 -6
- package/lib/metadataTypes/TransactionalSMS.js +9 -8
- package/lib/metadataTypes/TriggeredSend.js +15 -12
- package/lib/metadataTypes/User.js +8 -7
- package/lib/metadataTypes/Verification.js +230 -0
- package/lib/metadataTypes/definitions/Asset.definition.js +1 -1
- package/lib/metadataTypes/definitions/AttributeGroup.definition.js +3 -3
- package/lib/metadataTypes/definitions/AttributeSet.definition.js +75 -22
- package/lib/metadataTypes/definitions/Automation.definition.js +2 -1
- package/lib/metadataTypes/definitions/Campaign.definition.js +1 -1
- package/lib/metadataTypes/definitions/ContentArea.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/DataExtensionTemplate.definition.js +1 -1
- package/lib/metadataTypes/definitions/DataExtract.definition.js +1 -1
- package/lib/metadataTypes/definitions/DataExtractType.definition.js +1 -1
- package/lib/metadataTypes/definitions/Discovery.definition.js +1 -1
- package/lib/metadataTypes/definitions/Email.definition.js +1 -1
- package/lib/metadataTypes/definitions/EmailSend.definition.js +1 -1
- package/lib/metadataTypes/definitions/Event.definition.js +1 -1
- package/lib/metadataTypes/definitions/FileLocation.definition.js +1 -1
- package/lib/metadataTypes/definitions/FileTransfer.definition.js +1 -1
- package/lib/metadataTypes/definitions/Filter.definition.js +1 -1
- package/lib/metadataTypes/definitions/Folder.definition.js +1 -1
- package/lib/metadataTypes/definitions/ImportFile.definition.js +1 -1
- package/lib/metadataTypes/definitions/Journey.definition.js +1 -1
- package/lib/metadataTypes/definitions/List.definition.js +1 -1
- package/lib/metadataTypes/definitions/MobileCode.definition.js +1 -1
- package/lib/metadataTypes/definitions/MobileKeyword.definition.js +1 -1
- package/lib/metadataTypes/definitions/MobileMessage.definition.js +1 -1
- package/lib/metadataTypes/definitions/Query.definition.js +1 -1
- package/lib/metadataTypes/definitions/Role.definition.js +1 -1
- package/lib/metadataTypes/definitions/Script.definition.js +1 -1
- package/lib/metadataTypes/definitions/SendClassification.definition.js +1 -1
- package/lib/metadataTypes/definitions/TransactionalEmail.definition.js +20 -2
- package/lib/metadataTypes/definitions/TransactionalPush.definition.js +1 -1
- package/lib/metadataTypes/definitions/TransactionalSMS.definition.js +1 -1
- package/lib/metadataTypes/definitions/TriggeredSend.definition.js +1 -1
- package/lib/metadataTypes/definitions/User.definition.js +1 -1
- package/lib/metadataTypes/definitions/Verification.definition.js +88 -0
- package/lib/retrieveChangelog.js +4 -3
- package/lib/util/auth.js +11 -8
- package/lib/util/businessUnit.js +5 -5
- package/lib/util/cache.js +3 -3
- package/lib/util/cli.js +15 -13
- package/lib/util/config.js +10 -7
- package/lib/util/devops.js +12 -11
- package/lib/util/file.js +15 -14
- package/lib/util/init.config.js +11 -9
- package/lib/util/init.git.js +8 -7
- package/lib/util/init.js +12 -12
- package/lib/util/init.npm.js +7 -5
- package/lib/util/util.js +14 -12
- package/package.json +32 -27
- package/test/general.test.js +4 -6
- package/test/mockRoot/.mcdevrc.json +1 -1
- package/test/mockRoot/deploy/testInstance/_ParentBU_/dataExtension/testExisting_dataExtensionShared.dataExtension-meta.json +59 -0
- package/test/mockRoot/deploy/testInstance/_ParentBU_/dataExtension/testNew_dataExtensionShared.dataExtension-meta.json +23 -0
- package/test/mockRoot/deploy/testInstance/testBU/automation/testNew_automation.automation-meta.json +4 -0
- package/test/mockRoot/deploy/testInstance/testBU/dataExtension/testExisting_dataExtension.dataExtension-meta.json +1 -0
- package/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json +3 -4
- package/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testNew_temail.transactionalEmail-meta.json +1 -6
- package/test/mockRoot/deploy/testInstance/testBU/verification/testExisting_39f6a488-20eb-4ba0-b0b9.verification-meta.json +11 -0
- package/test/mockRoot/deploy/testInstance/testBU/verification/testNew_39f6a488-20eb-4ba0-b0b9.verification-meta.json +11 -0
- package/test/resourceFactory.js +52 -26
- package/test/resources/1111111/data/v1/customobjectdata/key/testExisting_dataExtensionShared/rowset/get-response.json +13 -0
- package/test/resources/1111111/dataExtension/create-expected.json +23 -0
- package/test/resources/1111111/dataExtension/create-response.xml +59 -0
- package/test/resources/1111111/dataExtension/retrieve-expected.json +55 -0
- package/test/resources/1111111/dataExtension/retrieve-expected.md +18 -0
- package/test/resources/1111111/dataExtension/retrieve-response.xml +27 -1
- package/test/resources/1111111/dataExtension/update-expected.json +55 -0
- package/test/resources/1111111/dataExtension/update-response.xml +57 -0
- package/test/resources/1111111/dataExtensionField/retrieve-CustomerKey=[testExisting_dataExtensionShared].[TriggerUpdate_randomNumber_]-response.xml +45 -0
- package/test/resources/1111111/dataExtensionField/retrieve-DataExtension.CustomerKey=testExisting_dataExtensionShared-response.xml +98 -0
- package/test/resources/1111111/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_dataExtensionSharedORDataExtension.CustomerKey=testExisting_dataExtensionShared-response.xml +98 -0
- package/test/resources/1111111/dataExtensionField/retrieve-response.xml +98 -0
- package/test/resources/1111111/dataExtensionTemplate/retrieve-response.xml +303 -0
- package/test/resources/1111111/dataFolder/retrieve-ContentType=synchronizeddataextensionORContentType=shared_salesforcedataextensionORContentType=shared_dataextensionORContentType=shared_dataORContentType=salesforcedataextensionORContentType=dataextensionORContentType=hidden-response.xml +387 -0
- package/test/resources/1111111/dataFolder/retrieve-response.xml +353 -9
- package/test/resources/9999999/attributeSet/retrieve-expected.json +89 -694
- package/test/resources/9999999/automation/build-expected.json +4 -0
- package/test/resources/9999999/automation/create-expected.json +4 -0
- package/test/resources/9999999/automation/create-testNew_automation-expected.md +1 -0
- package/test/resources/9999999/automation/retrieve-expected.json +4 -0
- package/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md +1 -0
- package/test/resources/9999999/automation/template-expected.json +4 -0
- package/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json +7 -0
- package/test/resources/9999999/automation/v1/automations/post-response.json +7 -0
- package/test/resources/9999999/automation/v1/dataverifications/post-response.json +12 -0
- package/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/delete-response.json +0 -0
- package/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/get-response.json +12 -0
- package/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/patch-response.json +12 -0
- package/test/resources/9999999/dataExtension/build-expected.json +16 -0
- package/test/resources/9999999/dataExtension/delete-response.xml +42 -0
- package/test/resources/9999999/dataExtension/retrieve-expected.json +16 -0
- package/test/resources/9999999/dataExtension/retrieve-expected.md +3 -1
- package/test/resources/9999999/dataExtension/template-expected.json +16 -0
- package/test/resources/9999999/dataExtension/update-expected.json +17 -1
- package/test/resources/9999999/dataExtensionField/retrieve-CustomerKey=[testExisting_dataExtension].[LastName]-response.xml +44 -0
- package/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testExisting_dataExtension-response.xml +36 -1
- package/test/resources/9999999/dataExtensionField/retrieve-response.xml +36 -1
- package/test/resources/9999999/dataFolder/retrieve-ContentType=synchronizeddataextensionORContentType=shared_salesforcedataextensionORContentType=shared_dataextensionORContentType=shared_dataORContentType=salesforcedataextensionORContentType=dataextensionORContentType=hidden-response.xml +117 -0
- package/test/resources/9999999/hub/v1/contacts/schema/attributeGroups/get-response.json +43 -0
- package/test/resources/9999999/hub/v1/contacts/schema/setDefinitions/get-response.json +387 -0
- package/test/resources/9999999/interaction/v1/interactions/233d4413-922c-4568-85a5-e5cc77efc3be/delete-response.json +1 -0
- package/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/get-response.json +1 -1
- package/test/resources/9999999/messaging/v1/email/definitions/post-response.json +1 -1
- package/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/delete-response.json +6 -0
- package/test/resources/9999999/transactionalEmail/build-expected.json +3 -7
- package/test/resources/9999999/transactionalEmail/get-expected.json +3 -7
- package/test/resources/9999999/transactionalEmail/patch-expected.json +3 -7
- package/test/resources/9999999/transactionalEmail/post-expected.json +3 -7
- package/test/resources/9999999/transactionalEmail/template-expected.json +3 -7
- package/test/resources/9999999/verification/build-expected.json +11 -0
- package/test/resources/9999999/verification/get-expected.json +11 -0
- package/test/resources/9999999/verification/patch-expected.json +11 -0
- package/test/resources/9999999/verification/post-expected.json +11 -0
- package/test/resources/9999999/verification/template-expected.json +11 -0
- package/test/type.attributeGroup.test.js +9 -12
- package/test/type.attributeSet.test.js +10 -13
- package/test/type.automation.test.js +34 -32
- package/test/type.dataExtension.test.js +210 -54
- package/test/type.dataExtract.test.js +15 -9
- package/test/type.fileTransfer.test.js +15 -9
- package/test/type.importFile.test.js +15 -9
- package/test/type.journey.test.js +43 -17
- package/test/type.mobileKeyword.test.js +11 -11
- package/test/type.mobileMessage.test.js +11 -11
- package/test/type.query.test.js +13 -14
- package/test/type.script.test.js +11 -9
- package/test/type.transactionalEmail.test.js +17 -17
- package/test/type.transactionalPush.test.js +7 -10
- package/test/type.transactionalSMS.test.js +7 -11
- package/test/type.triggeredSend.test.js +11 -10
- package/test/type.user.test.js +6 -8
- package/test/type.verification.test.js +172 -0
- package/test/utils.js +68 -48
- package/types/mcdev.d.js +16 -2
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
import jsonToTable from 'json-to-table';
|
|
4
|
+
import TYPE from '../../types/mcdev.d.js';
|
|
5
|
+
import MetadataType from './MetadataType.js';
|
|
6
|
+
import AttributeSet from './AttributeSet.js';
|
|
7
|
+
import DataExtensionField from './DataExtensionField.js';
|
|
8
|
+
import Folder from './Folder.js';
|
|
9
|
+
import { Util } from '../util/util.js';
|
|
10
|
+
import File from '../util/file.js';
|
|
11
|
+
import auth from '../util/auth.js';
|
|
12
|
+
import cache from '../util/cache.js';
|
|
13
|
+
import pLimit from 'p-limit';
|
|
14
|
+
import inquirer from 'inquirer';
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* DataExtension MetadataType
|
|
@@ -45,7 +47,7 @@ class DataExtension extends MetadataType {
|
|
|
45
47
|
};
|
|
46
48
|
}
|
|
47
49
|
Util.logger.info(` - Caching dependent Metadata: dataExtensionField`);
|
|
48
|
-
await this
|
|
50
|
+
await this.#attachFields(metadataMap, fieldOptions);
|
|
49
51
|
|
|
50
52
|
/** @type {object[]} */
|
|
51
53
|
const metadataToCreate = [];
|
|
@@ -283,7 +285,7 @@ class DataExtension extends MetadataType {
|
|
|
283
285
|
* @param {{created: number, updated: number}} createdUpdated counter representing successful creates/updates
|
|
284
286
|
* @returns {void}
|
|
285
287
|
*/
|
|
286
|
-
static postDeployTasks(upsertedMetadata, originalMetadata, createdUpdated) {
|
|
288
|
+
static async postDeployTasks(upsertedMetadata, originalMetadata, createdUpdated) {
|
|
287
289
|
for (const key in upsertedMetadata) {
|
|
288
290
|
const item = upsertedMetadata[key];
|
|
289
291
|
|
|
@@ -354,6 +356,376 @@ class DataExtension extends MetadataType {
|
|
|
354
356
|
DataExtensionField.postRetrieveTasks(field, true);
|
|
355
357
|
}
|
|
356
358
|
}
|
|
359
|
+
await this.#fixShared(upsertedMetadata, originalMetadata, createdUpdated);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* takes care of updating attribute groups on child BUs after an update to Shared DataExtensions
|
|
364
|
+
* helper for {@link DataExtension.postDeployTasks}
|
|
365
|
+
* fixes an issue where shared data extensions are not visible in data designer on child BU; SF known issue: https://issues.salesforce.com/#q=W-11031095
|
|
366
|
+
*
|
|
367
|
+
* @param {TYPE.DataExtensionMap} upsertedMetadata metadata mapped by their keyField
|
|
368
|
+
* @param {TYPE.DataExtensionMap} originalMetadata metadata to be updated (contains additioanl fields)
|
|
369
|
+
* @param {{created: number, updated: number}} createdUpdated counter representing successful creates/updates
|
|
370
|
+
* @returns {void}
|
|
371
|
+
*/
|
|
372
|
+
static async #fixShared(upsertedMetadata, originalMetadata, createdUpdated) {
|
|
373
|
+
if (this.buObject.eid !== this.buObject.mid) {
|
|
374
|
+
// only if we were executing a deploy on parent bu could we be deploying shared data extensions
|
|
375
|
+
Util.logger.debug(`Skipping fixShared logic because we are not executing on Parent BU`);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
if (createdUpdated.updated === 0) {
|
|
379
|
+
// only if updates were made could the issue in https://issues.salesforce.com/#q=W-11031095 affect data designer
|
|
380
|
+
Util.logger.debug(`Skipping fixShared logic because nothing was updated`);
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// find all shared data extensions
|
|
385
|
+
if (!this.deployedSharedKeys.length) {
|
|
386
|
+
Util.logger.debug(
|
|
387
|
+
`Skipping fixShared logic because no Shared Data Extensions were updated`
|
|
388
|
+
);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const sharedDataExtensionsKeys = this.deployedSharedKeys;
|
|
393
|
+
this.deployedSharedKeys = null;
|
|
394
|
+
|
|
395
|
+
if (Util.OPTIONS.fixShared) {
|
|
396
|
+
// select which BUs to run this for
|
|
397
|
+
const selectedBuNames = await this.#fixShared_getBUs();
|
|
398
|
+
|
|
399
|
+
// backup settings
|
|
400
|
+
const buObjectBak = this.buObject;
|
|
401
|
+
const clientBak = this.client;
|
|
402
|
+
|
|
403
|
+
// get dataExtension ID-Key relationship
|
|
404
|
+
const sharedDataExtensionMap = {};
|
|
405
|
+
for (const key of sharedDataExtensionsKeys) {
|
|
406
|
+
try {
|
|
407
|
+
const id = cache.searchForField(
|
|
408
|
+
'dataExtension',
|
|
409
|
+
key,
|
|
410
|
+
'CustomerKey',
|
|
411
|
+
'ObjectID',
|
|
412
|
+
this.buObject.eid
|
|
413
|
+
);
|
|
414
|
+
sharedDataExtensionMap[id] = key;
|
|
415
|
+
} catch {
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// run the fix-data-model logic
|
|
421
|
+
Util.logger.info(
|
|
422
|
+
`Fixing Shared Data Extensions details in data models of child BUs` +
|
|
423
|
+
Util.getKeysString(sharedDataExtensionsKeys)
|
|
424
|
+
);
|
|
425
|
+
|
|
426
|
+
for (const buName of selectedBuNames) {
|
|
427
|
+
await this.#fixShared_onBU(buName, buObjectBak, clientBak, sharedDataExtensionMap);
|
|
428
|
+
}
|
|
429
|
+
Util.logger.info(`Finished fixing Shared Data Extensions details in data models`);
|
|
430
|
+
|
|
431
|
+
// restore settings
|
|
432
|
+
this.buObject = buObjectBak;
|
|
433
|
+
this.client = clientBak;
|
|
434
|
+
} else {
|
|
435
|
+
Util.logger.warn(
|
|
436
|
+
'Shared Data Extensions were updated but --fixShared option is not set. This can result in your changes not being visible in attribute groups on child BUs.'
|
|
437
|
+
);
|
|
438
|
+
Util.logger.info(
|
|
439
|
+
'We recommend to re-run your deployment with the --fixShared option unless you are sure your Shared Data Extension is not used in attribute groups on any child BU.'
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* helper for {@link DataExtension.#fixShared}
|
|
446
|
+
*
|
|
447
|
+
* @returns {string[]} list of selected BU names
|
|
448
|
+
*/
|
|
449
|
+
static async #fixShared_getBUs() {
|
|
450
|
+
const buListObj = this.properties.credentials[this.buObject.credential].businessUnits;
|
|
451
|
+
const fixBuPreselected = [];
|
|
452
|
+
const availableBuNames = Object.keys(buListObj).filter(
|
|
453
|
+
(buName) => buName !== Util.parentBuName
|
|
454
|
+
);
|
|
455
|
+
if (typeof Util.OPTIONS.fixShared === 'string') {
|
|
456
|
+
if (Util.OPTIONS.fixShared === '*') {
|
|
457
|
+
// pre-select all BUs
|
|
458
|
+
fixBuPreselected.push(...availableBuNames);
|
|
459
|
+
} else {
|
|
460
|
+
// pre-select BUs from comma-separated list
|
|
461
|
+
fixBuPreselected.push(
|
|
462
|
+
...Util.OPTIONS.fixShared
|
|
463
|
+
.split(',')
|
|
464
|
+
.filter(Boolean)
|
|
465
|
+
.map((bu) => bu.trim())
|
|
466
|
+
.filter((bu) => availableBuNames.includes(bu))
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
if (Util.skipInteraction && fixBuPreselected.length) {
|
|
471
|
+
// assume programmatic use case or user that wants to skip the wizard. Use pre-selected BUs
|
|
472
|
+
return fixBuPreselected;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const buList = availableBuNames.map((name) => ({
|
|
476
|
+
name,
|
|
477
|
+
value: name,
|
|
478
|
+
checked: fixBuPreselected.includes(name),
|
|
479
|
+
}));
|
|
480
|
+
const questions = {
|
|
481
|
+
type: 'checkbox',
|
|
482
|
+
name: 'businessUnits',
|
|
483
|
+
message: 'Please select BUs that have access to the updated Shared Data Extensions:',
|
|
484
|
+
pageSize: 10,
|
|
485
|
+
choices: buList,
|
|
486
|
+
};
|
|
487
|
+
let responses = null;
|
|
488
|
+
|
|
489
|
+
try {
|
|
490
|
+
responses = await inquirer.prompt(questions);
|
|
491
|
+
} catch (ex) {
|
|
492
|
+
Util.logger.info(ex);
|
|
493
|
+
}
|
|
494
|
+
return responses.businessUnits;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* helper for {@link DataExtension.#fixShared}
|
|
499
|
+
*
|
|
500
|
+
* @param {string} childBuName name of child BU to fix
|
|
501
|
+
* @param {TYPE.BuObject} buObjectParent bu object for parent BU
|
|
502
|
+
* @param {object} clientParent SDK for parent BU
|
|
503
|
+
* @param {Object.<string, string>} sharedDataExtensionMap ID-Key relationship of shared data extensions
|
|
504
|
+
* @returns {Promise.<string[]>} updated shared DE keys on BU
|
|
505
|
+
*/
|
|
506
|
+
static async #fixShared_onBU(
|
|
507
|
+
childBuName,
|
|
508
|
+
buObjectParent,
|
|
509
|
+
clientParent,
|
|
510
|
+
sharedDataExtensionMap
|
|
511
|
+
) {
|
|
512
|
+
/** @type {TYPE.BuObject} */
|
|
513
|
+
const buObjectChildBu = {
|
|
514
|
+
eid: this.properties.credentials[buObjectParent.credential].eid,
|
|
515
|
+
mid: this.properties.credentials[buObjectParent.credential].businessUnits[childBuName],
|
|
516
|
+
businessUnit: childBuName,
|
|
517
|
+
credential: this.buObject.credential,
|
|
518
|
+
};
|
|
519
|
+
const clientChildBu = auth.getSDK(buObjectChildBu);
|
|
520
|
+
|
|
521
|
+
try {
|
|
522
|
+
// check if shared data Extension is used in an attributeSet on current BU
|
|
523
|
+
AttributeSet.properties = this.properties;
|
|
524
|
+
AttributeSet.buObject = buObjectChildBu;
|
|
525
|
+
AttributeSet.client = clientChildBu;
|
|
526
|
+
const sharedDeIdsUsedOnBU = await AttributeSet.fixShared_retrieve(
|
|
527
|
+
sharedDataExtensionMap,
|
|
528
|
+
DataExtensionField.fixShared_fields
|
|
529
|
+
);
|
|
530
|
+
if (sharedDeIdsUsedOnBU.length) {
|
|
531
|
+
let sharedDataExtensionsKeys = sharedDeIdsUsedOnBU.map(
|
|
532
|
+
(deId) => sharedDataExtensionMap[deId]
|
|
533
|
+
);
|
|
534
|
+
Util.logger.info(
|
|
535
|
+
` - Fixing dataExtensions on BU ${childBuName} ` +
|
|
536
|
+
Util.getKeysString(sharedDataExtensionsKeys)
|
|
537
|
+
);
|
|
538
|
+
|
|
539
|
+
for (const deId of sharedDeIdsUsedOnBU) {
|
|
540
|
+
// dont use Promise.all to ensure order of execution; otherwise, switched BU contexts in one step will affect the next
|
|
541
|
+
const fixed = await this.#fixShared_item(
|
|
542
|
+
deId,
|
|
543
|
+
sharedDataExtensionMap[deId],
|
|
544
|
+
buObjectChildBu,
|
|
545
|
+
clientChildBu,
|
|
546
|
+
buObjectParent,
|
|
547
|
+
clientParent
|
|
548
|
+
);
|
|
549
|
+
if (!fixed) {
|
|
550
|
+
// remove from list of shared DEs that were fixed
|
|
551
|
+
sharedDataExtensionsKeys = sharedDataExtensionsKeys.filter(
|
|
552
|
+
(key) => key !== sharedDataExtensionMap[deId]
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
if (sharedDataExtensionsKeys.length) {
|
|
557
|
+
Util.logger.debug(
|
|
558
|
+
` - Fixed ${sharedDataExtensionsKeys.length}/${
|
|
559
|
+
sharedDeIdsUsedOnBU.length
|
|
560
|
+
}: ${sharedDataExtensionsKeys.join(', ')}`
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
return sharedDataExtensionsKeys;
|
|
564
|
+
} else {
|
|
565
|
+
Util.logger.info(
|
|
566
|
+
Util.getGrayMsg(
|
|
567
|
+
` - No matching attributeSet found for given Shared Data Extensions keys found on BU ${childBuName}`
|
|
568
|
+
)
|
|
569
|
+
);
|
|
570
|
+
return [];
|
|
571
|
+
}
|
|
572
|
+
} catch (ex) {
|
|
573
|
+
Util.logger.error(ex.message);
|
|
574
|
+
return [];
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* method that actually takes care of triggering the update for a particular BU-sharedDe combo
|
|
580
|
+
* helper for {@link DataExtension.#fixShared_onBU}
|
|
581
|
+
*
|
|
582
|
+
* @param {string} deId data extension ObjectID
|
|
583
|
+
* @param {string} deKey dataExtension key
|
|
584
|
+
* @param {TYPE.BuObject} buObjectChildBu BU object for Child BU
|
|
585
|
+
* @param {object} clientChildBu SDK for child BU
|
|
586
|
+
* @param {TYPE.BuObject} buObjectParent BU object for Parent BU
|
|
587
|
+
* @param {object} clientParent SDK for parent BU
|
|
588
|
+
* @returns {Promise.<boolean>} flag that signals if the fix was successful
|
|
589
|
+
*/
|
|
590
|
+
static async #fixShared_item(
|
|
591
|
+
deId,
|
|
592
|
+
deKey,
|
|
593
|
+
buObjectChildBu,
|
|
594
|
+
clientChildBu,
|
|
595
|
+
buObjectParent,
|
|
596
|
+
clientParent
|
|
597
|
+
) {
|
|
598
|
+
try {
|
|
599
|
+
// add field via child BU
|
|
600
|
+
const randomSuffix = await DataExtension.#fixShared_item_addField(
|
|
601
|
+
buObjectChildBu,
|
|
602
|
+
clientChildBu,
|
|
603
|
+
deKey,
|
|
604
|
+
deId
|
|
605
|
+
);
|
|
606
|
+
|
|
607
|
+
// get field ID from parent BU (it is not returned on child BU)
|
|
608
|
+
const fieldObjectID = await DataExtension.#fixShared_item_getFieldId(
|
|
609
|
+
randomSuffix,
|
|
610
|
+
buObjectParent,
|
|
611
|
+
clientParent,
|
|
612
|
+
deKey
|
|
613
|
+
);
|
|
614
|
+
|
|
615
|
+
// delete field via child BU
|
|
616
|
+
await DataExtension.#fixShared_item_deleteField(
|
|
617
|
+
randomSuffix,
|
|
618
|
+
buObjectChildBu,
|
|
619
|
+
clientChildBu,
|
|
620
|
+
deKey,
|
|
621
|
+
fieldObjectID
|
|
622
|
+
);
|
|
623
|
+
|
|
624
|
+
Util.logger.info(
|
|
625
|
+
` - Fixed dataExtension ${deKey} on BU ${buObjectChildBu.businessUnit}`
|
|
626
|
+
);
|
|
627
|
+
|
|
628
|
+
return true;
|
|
629
|
+
} catch (ex) {
|
|
630
|
+
Util.logger.error(
|
|
631
|
+
`- error fixing dataExtension ${deKey} on BU ${buObjectChildBu.businessUnit}: ${ex.message}`
|
|
632
|
+
);
|
|
633
|
+
return false;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* add a new field to the shared DE to trigger an update to the data model
|
|
639
|
+
* helper for {@link DataExtension.#fixShared_item}
|
|
640
|
+
*
|
|
641
|
+
* @param {TYPE.BuObject} buObjectChildBu BU object for Child BU
|
|
642
|
+
* @param {object} clientChildBu SDK for child BU
|
|
643
|
+
* @param {string} deKey dataExtension key
|
|
644
|
+
* @param {string} deId dataExtension ObjectID
|
|
645
|
+
* @returns {Promise.<string>} randomSuffix
|
|
646
|
+
*/
|
|
647
|
+
static async #fixShared_item_addField(buObjectChildBu, clientChildBu, deKey, deId) {
|
|
648
|
+
this.buObject = buObjectChildBu;
|
|
649
|
+
this.client = clientChildBu;
|
|
650
|
+
const randomSuffix = Util.OPTIONS._runningTest
|
|
651
|
+
? '_randomNumber_'
|
|
652
|
+
: Math.floor(Math.random() * 9999999999);
|
|
653
|
+
// add a new field to the shared DE to trigger an update to the data model
|
|
654
|
+
const soapType = this.definition.soapType || this.definition.type;
|
|
655
|
+
await this.client.soap.update(
|
|
656
|
+
Util.capitalizeFirstLetter(soapType),
|
|
657
|
+
{
|
|
658
|
+
CustomerKey: deKey,
|
|
659
|
+
ObjectID: deId,
|
|
660
|
+
Fields: {
|
|
661
|
+
Field: [
|
|
662
|
+
{
|
|
663
|
+
Name: 'TriggerUpdate' + randomSuffix,
|
|
664
|
+
IsRequired: false,
|
|
665
|
+
IsPrimaryKey: false,
|
|
666
|
+
FieldType: 'Boolean',
|
|
667
|
+
ObjectID: null,
|
|
668
|
+
},
|
|
669
|
+
],
|
|
670
|
+
},
|
|
671
|
+
},
|
|
672
|
+
null
|
|
673
|
+
);
|
|
674
|
+
return randomSuffix;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* get ID of the field added by {@link DataExtension.#fixShared_item_addField} on the shared DE via parent BU
|
|
679
|
+
* helper for {@link DataExtension.#fixShared_item}
|
|
680
|
+
*
|
|
681
|
+
* @param {string} randomSuffix -
|
|
682
|
+
* @param {TYPE.BuObject} buObjectParent BU object for Parent BU
|
|
683
|
+
* @param {object} clientParent SDK for parent BU
|
|
684
|
+
* @param {string} deKey dataExtension key
|
|
685
|
+
* @returns {Promise.<string>} fieldObjectID
|
|
686
|
+
*/
|
|
687
|
+
static async #fixShared_item_getFieldId(randomSuffix, buObjectParent, clientParent, deKey) {
|
|
688
|
+
DataExtensionField.buObject = buObjectParent;
|
|
689
|
+
DataExtensionField.client = clientParent;
|
|
690
|
+
const fieldKey = `[${deKey}].[TriggerUpdate${randomSuffix}]`;
|
|
691
|
+
const fieldResponse = await DataExtensionField.retrieveForCache(
|
|
692
|
+
{
|
|
693
|
+
filter: {
|
|
694
|
+
leftOperand: 'CustomerKey',
|
|
695
|
+
operator: 'equals',
|
|
696
|
+
rightOperand: fieldKey,
|
|
697
|
+
},
|
|
698
|
+
},
|
|
699
|
+
['Name', 'ObjectID']
|
|
700
|
+
);
|
|
701
|
+
const fieldObjectID = fieldResponse.metadata[fieldKey]?.ObjectID;
|
|
702
|
+
return fieldObjectID;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* delete the field added by {@link DataExtension.#fixShared_item_addField}
|
|
707
|
+
* helper for {@link DataExtension.#fixShared_item}
|
|
708
|
+
*
|
|
709
|
+
* @param {string} randomSuffix -
|
|
710
|
+
* @param {TYPE.BuObject} buObjectChildBu BU object for Child BU
|
|
711
|
+
* @param {object} clientChildBu SDK for child BU
|
|
712
|
+
* @param {string} deKey dataExtension key
|
|
713
|
+
* @param {string} fieldObjectID field ObjectID
|
|
714
|
+
* @returns {Promise} -
|
|
715
|
+
*/
|
|
716
|
+
static async #fixShared_item_deleteField(
|
|
717
|
+
randomSuffix,
|
|
718
|
+
buObjectChildBu,
|
|
719
|
+
clientChildBu,
|
|
720
|
+
deKey,
|
|
721
|
+
fieldObjectID
|
|
722
|
+
) {
|
|
723
|
+
DataExtensionField.buObject = buObjectChildBu;
|
|
724
|
+
DataExtensionField.client = clientChildBu;
|
|
725
|
+
await DataExtensionField.deleteByKeySOAP(
|
|
726
|
+
deKey + '.TriggerUpdate' + randomSuffix,
|
|
727
|
+
fieldObjectID
|
|
728
|
+
);
|
|
357
729
|
}
|
|
358
730
|
|
|
359
731
|
/**
|
|
@@ -390,70 +762,10 @@ class DataExtension extends MetadataType {
|
|
|
390
762
|
// in case of cache dont get fields
|
|
391
763
|
if (metadata && retrieveDir) {
|
|
392
764
|
// get fields from API
|
|
393
|
-
await this
|
|
765
|
+
await this.#attachFields(metadata, fieldOptions, additionalFields);
|
|
394
766
|
}
|
|
395
767
|
if (!retrieveDir && this.buObject.eid !== this.buObject.mid) {
|
|
396
|
-
|
|
397
|
-
Util.logger.info(
|
|
398
|
-
' - Caching dependent Metadata: dataExtension (shared via _ParentBU_)'
|
|
399
|
-
);
|
|
400
|
-
/** @type {TYPE.BuObject} */
|
|
401
|
-
const buObjectParentBu = {
|
|
402
|
-
eid: this.properties.credentials[this.buObject.credential].eid,
|
|
403
|
-
mid: this.properties.credentials[this.buObject.credential].eid,
|
|
404
|
-
businessUnit: Util.parentBuName,
|
|
405
|
-
credential: this.buObject.credential,
|
|
406
|
-
};
|
|
407
|
-
try {
|
|
408
|
-
this.client = auth.getSDK(buObjectParentBu);
|
|
409
|
-
} catch (ex) {
|
|
410
|
-
Util.logger.error(ex.message);
|
|
411
|
-
return;
|
|
412
|
-
}
|
|
413
|
-
const metadataParentBu = await this._retrieveAll(additionalFields);
|
|
414
|
-
|
|
415
|
-
// get shared folders to match our shared / synched Data Extensions
|
|
416
|
-
const subTypeArr = this.definition.dependencies
|
|
417
|
-
.filter((item) => item.startsWith('folder-'))
|
|
418
|
-
.map((item) => item.slice(7));
|
|
419
|
-
Util.logger.info(' - Caching dependent Metadata: folder (shared via _ParentBU_)');
|
|
420
|
-
Util.logSubtypes(subTypeArr);
|
|
421
|
-
Folder.client = this.client;
|
|
422
|
-
Folder.buObject = buObjectParentBu;
|
|
423
|
-
Folder.properties = this.properties;
|
|
424
|
-
const result = await Folder.retrieveForCache(null, subTypeArr);
|
|
425
|
-
cache.mergeMetadata('folder', result.metadata, this.buObject.eid);
|
|
426
|
-
|
|
427
|
-
// get the types and clean out non-shared ones
|
|
428
|
-
const folderTypesFromParent = require('../MetadataTypeDefinitions').folder
|
|
429
|
-
.folderTypesFromParent;
|
|
430
|
-
for (const metadataEntry in metadataParentBu) {
|
|
431
|
-
try {
|
|
432
|
-
// get the data extension type from the folder
|
|
433
|
-
const folderContentType = cache.searchForField(
|
|
434
|
-
'folder',
|
|
435
|
-
metadataParentBu[metadataEntry].CategoryID,
|
|
436
|
-
'ID',
|
|
437
|
-
'ContentType',
|
|
438
|
-
this.buObject.eid
|
|
439
|
-
);
|
|
440
|
-
if (!folderTypesFromParent.includes(folderContentType)) {
|
|
441
|
-
Util.logger.verbose(
|
|
442
|
-
`removing ${metadataEntry} because r__folder_ContentType '${folderContentType}' identifies this DE as not being shared`
|
|
443
|
-
);
|
|
444
|
-
delete metadataParentBu[metadataEntry];
|
|
445
|
-
}
|
|
446
|
-
} catch (ex) {
|
|
447
|
-
Util.logger.debug(
|
|
448
|
-
`removing ${metadataEntry} because of error while retrieving r__folder_ContentType: ${ex.message}`
|
|
449
|
-
);
|
|
450
|
-
delete metadataParentBu[metadataEntry];
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
// revert client to current default
|
|
455
|
-
this.client = auth.getSDK(this.buObject);
|
|
456
|
-
Folder.client = auth.getSDK(this.buObject);
|
|
768
|
+
const metadataParentBu = await this.retrieveSharedForCache(additionalFields);
|
|
457
769
|
|
|
458
770
|
// make sure to overwrite parent bu DEs with local ones
|
|
459
771
|
metadata = { ...metadataParentBu, ...metadata };
|
|
@@ -469,6 +781,81 @@ class DataExtension extends MetadataType {
|
|
|
469
781
|
return { metadata: metadata, type: 'dataExtension' };
|
|
470
782
|
}
|
|
471
783
|
|
|
784
|
+
/**
|
|
785
|
+
* get shared dataExtensions from parent BU and merge them into the cache
|
|
786
|
+
* helper for {@link DataExtension.retrieve} and for AttributeSet.fixShared_retrieve
|
|
787
|
+
*
|
|
788
|
+
* @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true
|
|
789
|
+
* @returns {Promise.<TYPE.DataExtensionMap>} keyField => metadata map
|
|
790
|
+
*/
|
|
791
|
+
static async retrieveSharedForCache(additionalFields = []) {
|
|
792
|
+
// for caching, we want to retrieve shared DEs as well from the instance parent BU
|
|
793
|
+
Util.logger.info(' - Caching dependent Metadata: dataExtension (shared via _ParentBU_)');
|
|
794
|
+
const buObjectBak = this.buObject;
|
|
795
|
+
const clientBak = this.client;
|
|
796
|
+
/** @type {TYPE.BuObject} */
|
|
797
|
+
const buObjectParentBu = {
|
|
798
|
+
eid: this.properties.credentials[this.buObject.credential].eid,
|
|
799
|
+
mid: this.properties.credentials[this.buObject.credential].eid,
|
|
800
|
+
businessUnit: Util.parentBuName,
|
|
801
|
+
credential: this.buObject.credential,
|
|
802
|
+
};
|
|
803
|
+
try {
|
|
804
|
+
this.buObject = buObjectParentBu;
|
|
805
|
+
this.client = auth.getSDK(buObjectParentBu);
|
|
806
|
+
} catch (ex) {
|
|
807
|
+
Util.logger.error(ex.message);
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
const metadataParentBu = await this._retrieveAll(additionalFields);
|
|
811
|
+
|
|
812
|
+
// get shared folders to match our shared / synched Data Extensions
|
|
813
|
+
const subTypeArr = this.definition.dependencies
|
|
814
|
+
.filter((item) => item.startsWith('folder-'))
|
|
815
|
+
.map((item) => item.slice(7));
|
|
816
|
+
Util.logger.info(' - Caching dependent Metadata: folder (shared via _ParentBU_)');
|
|
817
|
+
Util.logSubtypes(subTypeArr);
|
|
818
|
+
Folder.client = this.client;
|
|
819
|
+
Folder.buObject = this.buObject;
|
|
820
|
+
Folder.properties = this.properties;
|
|
821
|
+
const result = await Folder.retrieveForCache(null, subTypeArr);
|
|
822
|
+
cache.mergeMetadata('folder', result.metadata, this.buObject.eid);
|
|
823
|
+
|
|
824
|
+
// get the types and clean out non-shared ones
|
|
825
|
+
const folderTypesFromParent = MetadataTypeDefinitions.folder.folderTypesFromParent;
|
|
826
|
+
for (const metadataEntry in metadataParentBu) {
|
|
827
|
+
try {
|
|
828
|
+
// get the data extension type from the folder
|
|
829
|
+
const folderContentType = cache.searchForField(
|
|
830
|
+
'folder',
|
|
831
|
+
metadataParentBu[metadataEntry].CategoryID,
|
|
832
|
+
'ID',
|
|
833
|
+
'ContentType',
|
|
834
|
+
this.buObject.eid
|
|
835
|
+
);
|
|
836
|
+
if (!folderTypesFromParent.includes(folderContentType)) {
|
|
837
|
+
// Util.logger.verbose(
|
|
838
|
+
// `removing ${metadataEntry} because r__folder_ContentType '${folderContentType}' identifies this DE as not being shared`
|
|
839
|
+
// );
|
|
840
|
+
delete metadataParentBu[metadataEntry];
|
|
841
|
+
}
|
|
842
|
+
} catch (ex) {
|
|
843
|
+
Util.logger.debug(
|
|
844
|
+
`removing ${metadataEntry} because of error while retrieving r__folder_ContentType: ${ex.message}`
|
|
845
|
+
);
|
|
846
|
+
delete metadataParentBu[metadataEntry];
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// revert client to current default
|
|
851
|
+
this.client = clientBak;
|
|
852
|
+
this.buObject = buObjectBak;
|
|
853
|
+
Folder.client = clientBak;
|
|
854
|
+
Folder.buObject = buObjectBak;
|
|
855
|
+
|
|
856
|
+
return metadataParentBu;
|
|
857
|
+
}
|
|
858
|
+
|
|
472
859
|
/**
|
|
473
860
|
* helper to retrieve all dataExtension fields and attach them to the dataExtension metadata
|
|
474
861
|
*
|
|
@@ -478,7 +865,7 @@ class DataExtension extends MetadataType {
|
|
|
478
865
|
* @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true
|
|
479
866
|
* @returns {Promise.<void>} -
|
|
480
867
|
*/
|
|
481
|
-
static async
|
|
868
|
+
static async #attachFields(metadata, fieldOptions, additionalFields) {
|
|
482
869
|
const fieldsObj = await this._retrieveFields(fieldOptions, additionalFields);
|
|
483
870
|
const fieldKeys = Object.keys(fieldsObj);
|
|
484
871
|
// add fields to corresponding DE
|
|
@@ -628,11 +1015,16 @@ class DataExtension extends MetadataType {
|
|
|
628
1015
|
throw new Error(`Cannot Upsert Strongly Typed Data Extensions`);
|
|
629
1016
|
}
|
|
630
1017
|
if (
|
|
1018
|
+
!Util.OPTIONS._fixSharedOnBu &&
|
|
631
1019
|
this.buObject.eid !== this.buObject.mid &&
|
|
632
1020
|
metadata.r__folder_Path?.startsWith('Shared Items')
|
|
633
1021
|
) {
|
|
634
1022
|
throw new Error(`Cannot Create/Update a Shared Data Extension from the Child BU`);
|
|
635
1023
|
}
|
|
1024
|
+
if (metadata.r__folder_ContentType === 'shared_dataextension') {
|
|
1025
|
+
this.deployedSharedKeys ||= [];
|
|
1026
|
+
this.deployedSharedKeys.push(metadata.CustomerKey);
|
|
1027
|
+
}
|
|
636
1028
|
if (metadata.r__folder_Path?.startsWith('Synchronized Data Extensions')) {
|
|
637
1029
|
throw new Error(
|
|
638
1030
|
`Cannot Create/Update a Synchronized Data Extension. Please use Contact Builder to maintain these`
|
|
@@ -822,7 +1214,11 @@ class DataExtension extends MetadataType {
|
|
|
822
1214
|
for (const element of fieldsJson) {
|
|
823
1215
|
const newJsonElement = {};
|
|
824
1216
|
for (const field of fieldsToKeep) {
|
|
825
|
-
|
|
1217
|
+
if (field === 'MaxLength' && element.FieldType === 'Decimal') {
|
|
1218
|
+
newJsonElement.MaxLength = `${element.MaxLength},${element.Scale}`;
|
|
1219
|
+
} else {
|
|
1220
|
+
newJsonElement[field] = element[field];
|
|
1221
|
+
}
|
|
826
1222
|
}
|
|
827
1223
|
newJson.push(newJsonElement);
|
|
828
1224
|
}
|
|
@@ -1113,6 +1509,7 @@ class DataExtension extends MetadataType {
|
|
|
1113
1509
|
}
|
|
1114
1510
|
|
|
1115
1511
|
// Assign definition to static attributes
|
|
1116
|
-
|
|
1512
|
+
import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js';
|
|
1513
|
+
DataExtension.definition = MetadataTypeDefinitions.dataExtension;
|
|
1117
1514
|
|
|
1118
|
-
|
|
1515
|
+
export default DataExtension;
|