mcdev 3.1.3 → 4.0.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 +67 -7
- package/.github/ISSUE_TEMPLATE/bug.yml +2 -1
- package/.github/PULL_REQUEST_TEMPLATE.md +5 -3
- package/.github/dependabot.yml +14 -0
- package/.github/workflows/code-analysis.yml +57 -0
- package/.husky/commit-msg +10 -0
- package/.husky/post-checkout +5 -0
- package/.husky/pre-commit +2 -1
- package/.prettierrc +8 -0
- package/.vscode/settings.json +1 -1
- package/LICENSE +2 -2
- package/README.md +134 -45
- package/boilerplate/config.json +5 -11
- package/boilerplate/files/.prettierrc +8 -0
- package/boilerplate/files/.vscode/extensions.json +0 -1
- package/boilerplate/files/.vscode/settings.json +30 -2
- package/boilerplate/files/README.md +2 -2
- package/boilerplate/forcedUpdates.json +10 -0
- package/boilerplate/npm-dependencies.json +5 -5
- package/docs/dist/documentation.md +2807 -1730
- package/jsconfig.json +1 -1
- package/lib/Builder.js +171 -74
- package/lib/Deployer.js +244 -96
- package/lib/MetadataTypeDefinitions.js +2 -0
- package/lib/MetadataTypeInfo.js +2 -0
- package/lib/Retriever.js +61 -84
- package/lib/cli.js +116 -11
- package/lib/index.js +241 -561
- package/lib/metadataTypes/AccountUser.js +117 -103
- package/lib/metadataTypes/Asset.js +705 -255
- package/lib/metadataTypes/AttributeGroup.js +23 -12
- package/lib/metadataTypes/Automation.js +489 -392
- package/lib/metadataTypes/Campaign.js +33 -93
- package/lib/metadataTypes/ContentArea.js +31 -11
- package/lib/metadataTypes/DataExtension.js +387 -372
- package/lib/metadataTypes/DataExtensionField.js +131 -54
- package/lib/metadataTypes/DataExtensionTemplate.js +22 -4
- package/lib/metadataTypes/DataExtract.js +61 -48
- package/lib/metadataTypes/DataExtractType.js +14 -8
- package/lib/metadataTypes/Discovery.js +21 -16
- package/lib/metadataTypes/Email.js +32 -12
- package/lib/metadataTypes/EmailSendDefinition.js +85 -80
- package/lib/metadataTypes/EventDefinition.js +61 -43
- package/lib/metadataTypes/FileTransfer.js +72 -52
- package/lib/metadataTypes/Filter.js +11 -4
- package/lib/metadataTypes/Folder.js +149 -117
- package/lib/metadataTypes/FtpLocation.js +14 -8
- package/lib/metadataTypes/ImportFile.js +61 -64
- package/lib/metadataTypes/Interaction.js +19 -4
- package/lib/metadataTypes/List.js +54 -13
- package/lib/metadataTypes/MetadataType.js +664 -454
- package/lib/metadataTypes/MobileCode.js +46 -0
- package/lib/metadataTypes/MobileKeyword.js +114 -0
- package/lib/metadataTypes/Query.js +206 -105
- package/lib/metadataTypes/Role.js +76 -61
- package/lib/metadataTypes/Script.js +147 -83
- package/lib/metadataTypes/SetDefinition.js +20 -8
- package/lib/metadataTypes/TriggeredSendDefinition.js +78 -58
- package/lib/metadataTypes/definitions/Asset.definition.js +21 -10
- package/lib/metadataTypes/definitions/AttributeGroup.definition.js +12 -0
- package/lib/metadataTypes/definitions/Automation.definition.js +10 -5
- package/lib/metadataTypes/definitions/Campaign.definition.js +44 -1
- package/lib/metadataTypes/definitions/DataExtension.definition.js +4 -0
- package/lib/metadataTypes/definitions/DataExtensionTemplate.definition.js +6 -0
- package/lib/metadataTypes/definitions/DataExtract.definition.js +18 -14
- package/lib/metadataTypes/definitions/Discovery.definition.js +12 -0
- package/lib/metadataTypes/definitions/EmailSendDefinition.definition.js +4 -0
- package/lib/metadataTypes/definitions/EventDefinition.definition.js +22 -0
- package/lib/metadataTypes/definitions/FileTransfer.definition.js +4 -0
- package/lib/metadataTypes/definitions/Filter.definition.js +4 -0
- package/lib/metadataTypes/definitions/Folder.definition.js +6 -0
- package/lib/metadataTypes/definitions/FtpLocation.definition.js +4 -0
- package/lib/metadataTypes/definitions/ImportFile.definition.js +10 -5
- package/lib/metadataTypes/definitions/Interaction.definition.js +4 -0
- package/lib/metadataTypes/definitions/MobileCode.definition.js +163 -0
- package/lib/metadataTypes/definitions/MobileKeyword.definition.js +253 -0
- package/lib/metadataTypes/definitions/Query.definition.js +4 -0
- package/lib/metadataTypes/definitions/Role.definition.js +5 -0
- package/lib/metadataTypes/definitions/Script.definition.js +4 -0
- package/lib/metadataTypes/definitions/SetDefinition.definition.js +28 -0
- package/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js +4 -0
- package/lib/retrieveChangelog.js +7 -6
- package/lib/util/auth.js +117 -0
- package/lib/util/businessUnit.js +55 -66
- package/lib/util/cache.js +194 -0
- package/lib/util/cli.js +90 -116
- package/lib/util/config.js +302 -0
- package/lib/util/devops.js +250 -50
- package/lib/util/file.js +141 -201
- package/lib/util/init.config.js +208 -75
- package/lib/util/init.git.js +45 -50
- package/lib/util/init.js +72 -59
- package/lib/util/init.npm.js +48 -39
- package/lib/util/util.js +280 -564
- package/package.json +45 -34
- package/test/dataExtension.test.js +152 -0
- package/test/mockRoot/.mcdev-auth.json +8 -0
- package/test/mockRoot/.mcdevrc.json +67 -0
- package/test/mockRoot/deploy/testInstance/testBU/dataExtension/childBU_dataextension_test.dataExtension-meta.json +39 -0
- package/test/mockRoot/deploy/testInstance/testBU/dataExtension/testDataExtension.dataExtension-meta.json +23 -0
- package/test/mockRoot/deploy/testInstance/testBU/query/testExistingQuery.query-meta.json +11 -0
- package/test/mockRoot/deploy/testInstance/testBU/query/testExistingQuery.query-meta.sql +4 -0
- package/test/mockRoot/deploy/testInstance/testBU/query/testQuery.query-meta.json +11 -0
- package/test/mockRoot/deploy/testInstance/testBU/query/testQuery.query-meta.sql +4 -0
- package/test/query.test.js +149 -0
- package/test/resourceFactory.js +142 -0
- package/test/resources/1111111/dataFolder/retrieve-response.xml +43 -0
- package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/patch-response.json +18 -0
- package/test/resources/9999999/automation/v1/queries/get-response.json +24 -0
- package/test/resources/9999999/automation/v1/queries/post-response.json +18 -0
- package/test/resources/9999999/dataExtension/build-expected.json +51 -0
- package/test/resources/9999999/dataExtension/create-expected.json +23 -0
- package/test/resources/9999999/dataExtension/create-response.xml +54 -0
- package/test/resources/9999999/dataExtension/retrieve-expected.json +51 -0
- package/test/resources/9999999/dataExtension/retrieve-response.xml +47 -0
- package/test/resources/9999999/dataExtension/template-expected.json +51 -0
- package/test/resources/9999999/dataExtension/update-expected.json +55 -0
- package/test/resources/9999999/dataExtension/update-response.xml +52 -0
- package/test/resources/9999999/dataExtensionField/retrieve-response.xml +93 -0
- package/test/resources/9999999/dataExtensionTemplate/retrieve-response.xml +303 -0
- package/test/resources/9999999/dataFolder/retrieve-response.xml +65 -0
- package/test/resources/9999999/query/build-expected.json +8 -0
- package/test/resources/9999999/query/get-expected.json +11 -0
- package/test/resources/9999999/query/patch-expected.json +11 -0
- package/test/resources/9999999/query/post-expected.json +11 -0
- package/test/resources/9999999/query/template-expected.json +8 -0
- package/test/resources/auth.json +32 -0
- package/test/resources/rest404-response.json +5 -0
- package/test/resources/retrieve-response.xml +21 -0
- package/test/utils.js +107 -0
- package/types/mcdev.d.js +301 -0
- package/CHANGELOG.md +0 -126
- package/PULL_REQUEST_TEMPLATE.md +0 -19
- package/test/util/file.js +0 -51
package/lib/Deployer.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const TYPE = require('../types/mcdev.d');
|
|
3
4
|
const MetadataTypeInfo = require('./MetadataTypeInfo');
|
|
4
|
-
const path = require('path');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
const Cli = require('./util/cli');
|
|
5
7
|
const Util = require('./util/util');
|
|
6
8
|
const File = require('./util/file');
|
|
9
|
+
const config = require('./util/config');
|
|
10
|
+
const cache = require('./util/cache');
|
|
11
|
+
const auth = require('./util/auth');
|
|
7
12
|
|
|
8
13
|
/**
|
|
9
14
|
* Reads metadata from local directory and deploys it to specified target business unit.
|
|
@@ -14,21 +19,11 @@ class Deployer {
|
|
|
14
19
|
* Creates a Deployer, uses v2 auth if v2AuthOptions are passed.
|
|
15
20
|
*
|
|
16
21
|
*
|
|
17
|
-
* @param {
|
|
18
|
-
* @param {
|
|
19
|
-
* @param {Object} buObject properties for auth
|
|
20
|
-
* @param {String} buObject.clientId clientId for FuelSDK auth
|
|
21
|
-
* @param {String} buObject.clientSecret clientSecret for FuelSDK auth
|
|
22
|
-
* @param {Object} buObject.credential clientId for FuelSDK auth
|
|
23
|
-
* @param {String} buObject.tenant v2 Auth Tenant Information
|
|
24
|
-
* @param {String} buObject.mid ID of Business Unit to authenticate with
|
|
25
|
-
* @param {String} buObject.businessUnit name of Business Unit to authenticate with
|
|
26
|
-
* @param {Util.ET_Client} client fuel client
|
|
27
|
-
* @param {String} [type] limit deployment to given metadata type
|
|
22
|
+
* @param {TYPE.Mcdevrc} properties General configuration to be used in retrieve
|
|
23
|
+
* @param {TYPE.BuObject} buObject properties for auth
|
|
28
24
|
*/
|
|
29
|
-
constructor(properties, buObject
|
|
25
|
+
constructor(properties, buObject) {
|
|
30
26
|
this.buObject = buObject;
|
|
31
|
-
this.client = client;
|
|
32
27
|
this.properties = properties;
|
|
33
28
|
this.deployDir = File.normalizePath([
|
|
34
29
|
properties.directories.deploy,
|
|
@@ -41,70 +36,217 @@ class Deployer {
|
|
|
41
36
|
buObject.businessUnit,
|
|
42
37
|
]);
|
|
43
38
|
// prep folders for auto-creation
|
|
44
|
-
MetadataTypeInfo.folder.
|
|
45
|
-
MetadataTypeInfo.folder.client = this.client;
|
|
39
|
+
MetadataTypeInfo.folder.client = auth.getSDK(buObject);
|
|
46
40
|
MetadataTypeInfo.folder.properties = this.properties;
|
|
47
41
|
// Remove tmp folder of previous deploys
|
|
48
42
|
File.removeSync('tmp');
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Deploys all metadata located in the 'deploy' directory to the specified business unit
|
|
46
|
+
*
|
|
47
|
+
* @param {string} businessUnit references credentials from properties.json
|
|
48
|
+
* @param {string[]} [selectedTypesArr] limit deployment to given metadata type
|
|
49
|
+
* @param {string[]} [keyArr] limit deployment to given metadata keys
|
|
50
|
+
* @param {boolean} [fromRetrieve] optionally deploy whats defined via selectedTypesArr + keyArr directly from retrieve folder instead of from deploy folder
|
|
51
|
+
* @returns {Promise.<void>} -
|
|
52
|
+
*/
|
|
53
|
+
static async deploy(businessUnit, selectedTypesArr, keyArr, fromRetrieve) {
|
|
54
|
+
Util.logger.info('mcdev:: Deploy');
|
|
55
|
+
const properties = await config.getProperties();
|
|
56
|
+
if (!(await config.checkProperties(properties))) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
if (fromRetrieve) {
|
|
60
|
+
properties.directories.deploy = properties.directories.retrieve;
|
|
61
|
+
}
|
|
62
|
+
if (Array.isArray(selectedTypesArr)) {
|
|
63
|
+
// types and keys can be provided but for each type all provided keys are applied as filter
|
|
64
|
+
for (const selectedType of selectedTypesArr) {
|
|
65
|
+
if (!Util._isValidType(selectedType)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (
|
|
71
|
+
fromRetrieve &&
|
|
72
|
+
(!selectedTypesArr ||
|
|
73
|
+
!Array.isArray(selectedTypesArr) ||
|
|
74
|
+
!selectedTypesArr.length ||
|
|
75
|
+
!keyArr ||
|
|
76
|
+
!Array.isArray(keyArr) ||
|
|
77
|
+
!keyArr.length)
|
|
78
|
+
) {
|
|
79
|
+
Util.logger.error('type & key need to be defined to deploy from retrieve folder');
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
let counter_credBu = 0;
|
|
83
|
+
if (businessUnit === '*') {
|
|
84
|
+
// all credentials and all BUs shall be deployed to
|
|
85
|
+
const deployFolders = await File.readDirectories(
|
|
86
|
+
properties.directories.deploy,
|
|
87
|
+
2,
|
|
88
|
+
false
|
|
56
89
|
);
|
|
90
|
+
for (const buPath of deployFolders.filter((r) => r.includes(path.sep))) {
|
|
91
|
+
const [cred, bu] = buPath.split(path.sep);
|
|
92
|
+
await this._deployBU(cred, bu, properties, selectedTypesArr, keyArr, fromRetrieve);
|
|
93
|
+
counter_credBu++;
|
|
94
|
+
Util.logger.info('');
|
|
95
|
+
Util.restartLogger();
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
// anything but "*" passed in
|
|
99
|
+
let [cred, bu] = businessUnit ? businessUnit.split('/') : [null, null];
|
|
100
|
+
|
|
101
|
+
// to allow all-BU via user selection we need to run this here already
|
|
102
|
+
if (
|
|
103
|
+
properties.credentials &&
|
|
104
|
+
(!properties.credentials[cred] ||
|
|
105
|
+
(bu !== '*' && properties.credentials[cred].businessUnits[bu]))
|
|
106
|
+
) {
|
|
107
|
+
const buObject = await Cli.getCredentialObject(
|
|
108
|
+
properties,
|
|
109
|
+
cred !== null ? cred + '/' + bu : null,
|
|
110
|
+
null,
|
|
111
|
+
true
|
|
112
|
+
);
|
|
113
|
+
if (buObject !== null) {
|
|
114
|
+
cred = buObject.credential;
|
|
115
|
+
bu = buObject.businessUnit;
|
|
116
|
+
} else {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (bu === '*' && properties.credentials && properties.credentials[cred]) {
|
|
122
|
+
// valid credential given and -all- BUs targeted
|
|
123
|
+
Util.logger.info(`\n :: Deploying all BUs for ${cred}`);
|
|
124
|
+
let counter_credBu = 0;
|
|
125
|
+
// for (const bu in properties.credentials[cred].businessUnits) {
|
|
126
|
+
const deployFolders = await File.readDirectories(
|
|
127
|
+
File.normalizePath([properties.directories.deploy, cred]),
|
|
128
|
+
1,
|
|
129
|
+
false
|
|
130
|
+
);
|
|
131
|
+
for (const buPath of deployFolders) {
|
|
132
|
+
await this._deployBU(
|
|
133
|
+
cred,
|
|
134
|
+
buPath,
|
|
135
|
+
properties,
|
|
136
|
+
selectedTypesArr,
|
|
137
|
+
keyArr,
|
|
138
|
+
fromRetrieve
|
|
139
|
+
);
|
|
140
|
+
counter_credBu++;
|
|
141
|
+
Util.logger.info('');
|
|
142
|
+
Util.restartLogger();
|
|
143
|
+
}
|
|
144
|
+
Util.logger.info(`\n :: ${counter_credBu} BUs for ${cred}\n`);
|
|
145
|
+
} else {
|
|
146
|
+
// either bad credential or specific BU or no BU given
|
|
147
|
+
await this._deployBU(cred, bu, properties, selectedTypesArr, keyArr, fromRetrieve);
|
|
148
|
+
counter_credBu++;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (counter_credBu !== 0) {
|
|
152
|
+
Util.logger.info(`\n :: Deployed ${counter_credBu} BUs\n`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* helper for deploy()
|
|
157
|
+
*
|
|
158
|
+
* @param {string} cred name of Credential
|
|
159
|
+
* @param {string} bu name of BU
|
|
160
|
+
* @param {TYPE.Mcdevrc} properties General configuration to be used in retrieve
|
|
161
|
+
* @param {string[]} [typeArr] limit deployment to given metadata type
|
|
162
|
+
* @param {string[]} [keyArr] limit deployment to given metadata keys
|
|
163
|
+
* @param {boolean} [fromRetrieve] optionally deploy whats defined via selectedTypesArr + keyArr directly from retrieve folder instead of from deploy folder
|
|
164
|
+
* @returns {Promise} ensure that BUs are worked on sequentially
|
|
165
|
+
*/
|
|
166
|
+
static async _deployBU(cred, bu, properties, typeArr, keyArr, fromRetrieve) {
|
|
167
|
+
const buPath = `${cred}/${bu}`;
|
|
168
|
+
Util.logger.info(`::Deploying ${buPath}`);
|
|
169
|
+
const buObject = await Cli.getCredentialObject(properties, buPath, null, true);
|
|
170
|
+
if (buObject !== null) {
|
|
171
|
+
cache.initCache(buObject);
|
|
172
|
+
const deployer = new Deployer(properties, buObject);
|
|
173
|
+
try {
|
|
174
|
+
// await is required or the calls end up conflicting
|
|
175
|
+
await deployer._deploy(typeArr, keyArr, fromRetrieve);
|
|
176
|
+
} catch (ex) {
|
|
177
|
+
Util.logger.errorStack(ex, 'mcdev.deploy failed');
|
|
178
|
+
}
|
|
57
179
|
}
|
|
58
|
-
this.cache = {};
|
|
59
180
|
}
|
|
181
|
+
|
|
60
182
|
/**
|
|
61
183
|
* Deploy all metadata that is located in the deployDir
|
|
184
|
+
*
|
|
185
|
+
* @param {string[]} [typeArr] limit deployment to given metadata type (can include subtype)
|
|
186
|
+
* @param {string[]} [keyArr] limit deployment to given metadata keys
|
|
187
|
+
* @param {boolean} [fromRetrieve] if true, no folders will be updated/created
|
|
62
188
|
* @returns {Promise} Promise
|
|
63
189
|
*/
|
|
64
|
-
async
|
|
190
|
+
async _deploy(typeArr, keyArr, fromRetrieve) {
|
|
191
|
+
if (await File.pathExists(this.deployDir)) {
|
|
192
|
+
/** @type {TYPE.MultiMetadataTypeMap} */
|
|
193
|
+
this.metadata = Deployer.readBUMetadata(this.deployDir, typeArr);
|
|
194
|
+
if (typeArr) {
|
|
195
|
+
for (const selectedType of typeArr) {
|
|
196
|
+
const type = selectedType.split('-')[0];
|
|
197
|
+
this.metadata[type] = Util.filterObjByKeys(this.metadata[type], keyArr);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
this.metadata = null;
|
|
202
|
+
Util.logger.error(
|
|
203
|
+
'Deployer.constructor:: Please create a directory called deploy and include your metadata in it: ./' +
|
|
204
|
+
this.deployDir
|
|
205
|
+
);
|
|
206
|
+
}
|
|
65
207
|
if (this.metadata === null || !Object.keys(this.metadata).length) {
|
|
66
|
-
Util.logger.
|
|
208
|
+
Util.logger.error('No metadata found in deploy folder for selected BU');
|
|
67
209
|
return null;
|
|
68
210
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
211
|
+
if (!fromRetrieve) {
|
|
212
|
+
await Deployer.createFolderDefinitions(
|
|
213
|
+
this.deployDir,
|
|
214
|
+
this.metadata,
|
|
215
|
+
Object.keys(this.metadata)
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
const foundDeployTypes = Object.keys(this.metadata).map((item) =>
|
|
219
|
+
item === 'asset' && Util.includesStartsWith(typeArr, item)
|
|
220
|
+
? typeArr[Util.includesStartsWithIndex(typeArr, item)]
|
|
221
|
+
: item
|
|
73
222
|
);
|
|
74
|
-
|
|
75
|
-
const deployOrder = Util.getMetadataHierachy(Object.keys(this.metadata));
|
|
223
|
+
const deployOrder = Util.getMetadataHierachy(foundDeployTypes);
|
|
76
224
|
// build cache, including all metadata types which will be deployed (Avoids retrieve later)
|
|
77
225
|
for (const metadataType of deployOrder) {
|
|
78
226
|
const [type, subType] = metadataType.split('-');
|
|
79
227
|
// add metadata & client to metadata process class instead of passing cache/mapping every time
|
|
80
|
-
MetadataTypeInfo[type].
|
|
81
|
-
MetadataTypeInfo[type].client = this.client;
|
|
228
|
+
MetadataTypeInfo[type].client = auth.getSDK(this.buObject);
|
|
82
229
|
MetadataTypeInfo[type].properties = this.properties;
|
|
230
|
+
MetadataTypeInfo[type].buObject = this.buObject;
|
|
83
231
|
Util.logger.info('Caching dependent Metadata: ' + metadataType);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
result = await MetadataTypeInfo[type].retrieveForCache(this.buObject, subType);
|
|
87
|
-
});
|
|
88
|
-
this.cache[type] = result.metadata;
|
|
232
|
+
const result = await MetadataTypeInfo[type].retrieveForCache(this.buObject, subType);
|
|
233
|
+
cache.setMetadata(type, result.metadata);
|
|
89
234
|
}
|
|
90
235
|
// deploy metadata files, extending cache once deploys
|
|
91
236
|
for (const metadataType of deployOrder) {
|
|
92
|
-
let result;
|
|
93
237
|
// TODO rewrite to allow deploying only a specific sub-type
|
|
94
238
|
// const [type, subType] = metadataType.split('-');
|
|
95
239
|
const type = metadataType.split('-')[0];
|
|
96
240
|
if (this.metadata[type]) {
|
|
97
|
-
MetadataTypeInfo[type].cache = this.cache;
|
|
98
241
|
Util.logger.info('Deploying: ' + metadataType);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this.cache[type] = Object.assign(this.cache[type], result);
|
|
242
|
+
|
|
243
|
+
const result = await MetadataTypeInfo[type].deploy(
|
|
244
|
+
this.metadata[type],
|
|
245
|
+
this.deployDir,
|
|
246
|
+
this.retrieveDir,
|
|
247
|
+
this.buObject
|
|
248
|
+
);
|
|
249
|
+
cache.mergeMetadata(type, result);
|
|
108
250
|
this.deployCallback(result, type);
|
|
109
251
|
}
|
|
110
252
|
}
|
|
@@ -112,8 +254,9 @@ class Deployer {
|
|
|
112
254
|
|
|
113
255
|
/**
|
|
114
256
|
* Gets called for every deployed metadata entry
|
|
115
|
-
*
|
|
116
|
-
* @param {
|
|
257
|
+
*
|
|
258
|
+
* @param {object} result Deployment result
|
|
259
|
+
* @param {string} metadataType Name of metadata type
|
|
117
260
|
* @returns {void}
|
|
118
261
|
*/
|
|
119
262
|
deployCallback(result, metadataType) {
|
|
@@ -128,30 +271,35 @@ class Deployer {
|
|
|
128
271
|
|
|
129
272
|
/**
|
|
130
273
|
* Returns metadata of a business unit that is saved locally
|
|
131
|
-
*
|
|
132
|
-
* @param {
|
|
274
|
+
*
|
|
275
|
+
* @param {string} deployDir root directory of metadata.
|
|
276
|
+
* @param {string[]} [typeArr] limit deployment to given metadata type
|
|
133
277
|
* @param {boolean} [listBadKeys=false] do not print errors, used for badKeys()
|
|
134
|
-
* @returns {
|
|
278
|
+
* @returns {TYPE.MultiMetadataTypeMap} Metadata of BU in local directory
|
|
135
279
|
*/
|
|
136
|
-
static readBUMetadata(deployDir,
|
|
280
|
+
static readBUMetadata(deployDir, typeArr, listBadKeys) {
|
|
281
|
+
/** @type {TYPE.MultiMetadataTypeMap} */
|
|
137
282
|
const buMetadata = {};
|
|
138
283
|
try {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
284
|
+
File.ensureDirSync(deployDir);
|
|
285
|
+
const metadataTypes = File.readdirSync(deployDir);
|
|
286
|
+
for (const metadataType of metadataTypes) {
|
|
287
|
+
if (
|
|
288
|
+
MetadataTypeInfo[metadataType] &&
|
|
289
|
+
(!typeArr || Util.includesStartsWith(typeArr, metadataType))
|
|
290
|
+
) {
|
|
291
|
+
// check if folder name is a valid metadataType, then check if the user limited to a certain type in the command params
|
|
292
|
+
buMetadata[metadataType] = MetadataTypeInfo[metadataType].getJsonFromFS(
|
|
293
|
+
File.normalizePath([deployDir, metadataType]),
|
|
294
|
+
listBadKeys,
|
|
295
|
+
typeArr
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (Object.keys(buMetadata).length === 0) {
|
|
300
|
+
throw new Error('No metadata found in deploy folder for selected BU & type');
|
|
154
301
|
}
|
|
302
|
+
return buMetadata;
|
|
155
303
|
} catch (ex) {
|
|
156
304
|
throw new Error(ex.message);
|
|
157
305
|
}
|
|
@@ -159,24 +307,23 @@ class Deployer {
|
|
|
159
307
|
|
|
160
308
|
/**
|
|
161
309
|
* parses asset metadata to auto-create folders in target folder
|
|
162
|
-
*
|
|
163
|
-
* @param {
|
|
164
|
-
* @param {
|
|
310
|
+
*
|
|
311
|
+
* @param {string} deployDir root directory of metadata.
|
|
312
|
+
* @param {TYPE.MultiMetadataTypeMap} metadata list of metadata
|
|
313
|
+
* @param {TYPE.SupportedMetadataTypes[]} metadataTypeArr list of metadata types
|
|
165
314
|
* @returns {void}
|
|
166
315
|
*/
|
|
167
316
|
static async createFolderDefinitions(deployDir, metadata, metadataTypeArr) {
|
|
168
317
|
let i = 0;
|
|
169
318
|
const folderMetadata = {};
|
|
170
|
-
|
|
319
|
+
for (const metadataType of metadataTypeArr) {
|
|
171
320
|
if (!MetadataTypeInfo[metadataType].definition.dependencies.includes('folder')) {
|
|
172
|
-
Util.logger.debug(
|
|
173
|
-
|
|
174
|
-
);
|
|
175
|
-
return;
|
|
321
|
+
Util.logger.debug(` ☇ skipping ${metadataType}: folder not a dependency`);
|
|
322
|
+
continue;
|
|
176
323
|
}
|
|
177
324
|
if (!MetadataTypeInfo[metadataType].definition.folderType) {
|
|
178
|
-
Util.logger.debug(`
|
|
179
|
-
|
|
325
|
+
Util.logger.debug(` ☇ skipping ${metadataType}: folderType not set`);
|
|
326
|
+
continue;
|
|
180
327
|
}
|
|
181
328
|
if (
|
|
182
329
|
!MetadataTypeInfo.folder.definition.deployFolderTypes.includes(
|
|
@@ -184,9 +331,9 @@ class Deployer {
|
|
|
184
331
|
)
|
|
185
332
|
) {
|
|
186
333
|
Util.logger.warn(
|
|
187
|
-
`
|
|
334
|
+
` ☇ skipping ${metadataType}: folderType ${MetadataTypeInfo[metadataType].definition.folderType} not supported for deployment`
|
|
188
335
|
);
|
|
189
|
-
|
|
336
|
+
continue;
|
|
190
337
|
}
|
|
191
338
|
Util.logger.debug(`Creating relevant folders for ${metadataType} in deploy dir`);
|
|
192
339
|
|
|
@@ -194,6 +341,7 @@ class Deployer {
|
|
|
194
341
|
// filter out root folders (which would not have a slash in their path)
|
|
195
342
|
(key) => metadata[metadataType][key].r__folder_Path.includes('/')
|
|
196
343
|
);
|
|
344
|
+
/* eslint-disable unicorn/prefer-ternary */
|
|
197
345
|
if (metadataType === 'dataExtension') {
|
|
198
346
|
allFolders = allFolders
|
|
199
347
|
.filter(
|
|
@@ -205,44 +353,44 @@ class Deployer {
|
|
|
205
353
|
} else {
|
|
206
354
|
allFolders = allFolders.map((key) => metadata[metadataType][key].r__folder_Path);
|
|
207
355
|
}
|
|
356
|
+
/* eslint-enable unicorn/prefer-ternary */
|
|
357
|
+
|
|
208
358
|
// deduplicate
|
|
209
359
|
const folderPathSet = new Set(allFolders);
|
|
210
|
-
[...folderPathSet].sort()
|
|
360
|
+
for (const item of [...folderPathSet].sort()) {
|
|
211
361
|
let aggregatedPath = '';
|
|
212
362
|
const parts = item.split('/');
|
|
213
|
-
|
|
363
|
+
for (const pathElement of parts) {
|
|
214
364
|
if (aggregatedPath) {
|
|
215
365
|
aggregatedPath += '/';
|
|
216
366
|
}
|
|
217
367
|
aggregatedPath += pathElement;
|
|
218
368
|
folderPathSet.add(aggregatedPath);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
221
371
|
const folderPathArrExtended = [...folderPathSet]
|
|
222
372
|
// strip root folders
|
|
223
373
|
.filter((folderName) => folderName.includes('/'))
|
|
224
374
|
.sort();
|
|
225
375
|
|
|
226
|
-
|
|
376
|
+
for (const folder of folderPathArrExtended) {
|
|
227
377
|
i++;
|
|
228
378
|
folderMetadata[`on-the-fly-${i}`] = {
|
|
229
379
|
Path: folder,
|
|
230
380
|
Name: folder.split('/').pop(),
|
|
231
381
|
Description: '',
|
|
232
382
|
ContentType: MetadataTypeInfo[metadataType].definition.folderType,
|
|
233
|
-
IsActive:
|
|
234
|
-
IsEditable:
|
|
235
|
-
AllowChildren:
|
|
383
|
+
IsActive: true,
|
|
384
|
+
IsEditable: true,
|
|
385
|
+
AllowChildren: true,
|
|
236
386
|
};
|
|
237
|
-
}
|
|
238
|
-
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
239
389
|
|
|
240
390
|
if (i > 0) {
|
|
241
|
-
Util.logger.info(`Saving folders to deploy dir (${i}) - please wait`);
|
|
242
|
-
|
|
243
391
|
// await results to allow us to re-read it right after
|
|
244
392
|
await MetadataTypeInfo.folder.saveResults(folderMetadata, deployDir, null);
|
|
245
|
-
Util.logger.info(`
|
|
393
|
+
Util.logger.info(`Created folders in deploy dir: ${i}`);
|
|
246
394
|
|
|
247
395
|
// reload from file system to ensure we use the same logic for building the temporary JSON
|
|
248
396
|
metadata.folder = MetadataTypeInfo.folder.getJsonFromFS(
|
|
@@ -26,6 +26,8 @@ const MetadataTypeDefinitions = {
|
|
|
26
26
|
importFile: require('./metadataTypes/definitions/ImportFile.definition'),
|
|
27
27
|
interaction: require('./metadataTypes/definitions/Interaction.definition'),
|
|
28
28
|
list: require('./metadataTypes/definitions/List.definition'),
|
|
29
|
+
mobileCode: require('./metadataTypes/definitions/MobileCode.definition'),
|
|
30
|
+
mobileKeyword: require('./metadataTypes/definitions/MobileKeyword.definition'),
|
|
29
31
|
query: require('./metadataTypes/definitions/Query.definition'),
|
|
30
32
|
role: require('./metadataTypes/definitions/Role.definition'),
|
|
31
33
|
script: require('./metadataTypes/definitions/Script.definition'),
|
package/lib/MetadataTypeInfo.js
CHANGED
|
@@ -26,6 +26,8 @@ const MetadataTypeInfo = {
|
|
|
26
26
|
importFile: require('./metadataTypes/ImportFile'),
|
|
27
27
|
interaction: require('./metadataTypes/Interaction'),
|
|
28
28
|
list: require('./metadataTypes/List'),
|
|
29
|
+
mobileCode: require('./metadataTypes/MobileCode'),
|
|
30
|
+
mobileKeyword: require('./metadataTypes/MobileKeyword'),
|
|
29
31
|
query: require('./metadataTypes/Query'),
|
|
30
32
|
role: require('./metadataTypes/Role'),
|
|
31
33
|
script: require('./metadataTypes/Script'),
|