mcdev 3.0.0 → 3.1.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/.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/.github/workflows/npm-publish.yml +33 -0
- package/.issuetracker +11 -3
- package/.vscode/extensions.json +1 -2
- package/.vscode/settings.json +19 -4
- package/CHANGELOG.md +98 -0
- package/README.md +247 -142
- package/boilerplate/config.json +3 -2
- package/docs/dist/considerations.md +66 -0
- package/docs/dist/documentation.md +5794 -0
- 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 +140 -116
- package/lib/metadataTypes/Automation.js +119 -54
- package/lib/metadataTypes/DataExtension.js +172 -131
- 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 +168 -80
- package/lib/metadataTypes/Query.js +54 -25
- package/lib/metadataTypes/Role.js +13 -8
- package/lib/metadataTypes/Script.js +43 -24
- 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.config.js +3 -0
- package/lib/util/init.git.js +2 -1
- package/lib/util/util.js +35 -18
- package/package.json +20 -24
- package/test/util/file.js +51 -0
- package/img/README.md/troubleshoot-nodejs-postinstall.jpg +0 -0
- package/postinstall.js +0 -41
- package/test/deployer.js +0 -16
- package/test/util.js +0 -26
|
@@ -7,6 +7,19 @@ const bluebird = require('bluebird');
|
|
|
7
7
|
const cliProgress = require('cli-progress');
|
|
8
8
|
const Mustache = require('mustache');
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {Object.<string, any>} AssetItem
|
|
12
|
+
*
|
|
13
|
+
* @typedef {Object.<string, AssetItem>} AssetMap
|
|
14
|
+
*
|
|
15
|
+
* @typedef {'archive'|'asset'|'audio'|'block'|'code'|'document'|'image'|'message'|'other'|'rawimage'|'template'|'textfile'|'video'} AssetSubType
|
|
16
|
+
*
|
|
17
|
+
* @typedef {Object} CodeExtractItem
|
|
18
|
+
* @property {AssetItem} json metadata of one item w/o code
|
|
19
|
+
* @property {MetadataType.CodeExtract[]} codeArr list of code snippets in this item
|
|
20
|
+
* @property {string[]} subFolder mostly set to null, otherwise list of subfolders
|
|
21
|
+
*/
|
|
22
|
+
|
|
10
23
|
/**
|
|
11
24
|
* FileTransfer MetadataType
|
|
12
25
|
* @augments MetadataType
|
|
@@ -14,11 +27,11 @@ const Mustache = require('mustache');
|
|
|
14
27
|
class Asset extends MetadataType {
|
|
15
28
|
/**
|
|
16
29
|
* Retrieves Metadata of Asset
|
|
17
|
-
* @param {
|
|
30
|
+
* @param {string} retrieveDir Directory where retrieved metadata directory will be saved
|
|
18
31
|
* @param {void} _ -
|
|
19
32
|
* @param {void} __ -
|
|
20
|
-
* @param {
|
|
21
|
-
* @returns {Promise} Promise
|
|
33
|
+
* @param {AssetSubType} [selectedSubType] optionally limit to a single subtype
|
|
34
|
+
* @returns {Promise<{metadata:AssetMap,type:string}>} Promise
|
|
22
35
|
*/
|
|
23
36
|
static async retrieve(retrieveDir, _, __, selectedSubType) {
|
|
24
37
|
const items = [];
|
|
@@ -48,8 +61,8 @@ class Asset extends MetadataType {
|
|
|
48
61
|
/**
|
|
49
62
|
* Retrieves asset metadata for caching
|
|
50
63
|
* @param {void} _ -
|
|
51
|
-
* @param {
|
|
52
|
-
* @returns {Promise} Promise
|
|
64
|
+
* @param {string} [selectedSubType] optionally limit to a single subtype
|
|
65
|
+
* @returns {Promise<{metadata:AssetMap,type:string}>} Promise
|
|
53
66
|
*/
|
|
54
67
|
static retrieveForCache(_, selectedSubType) {
|
|
55
68
|
return this.retrieve(null, null, null, selectedSubType);
|
|
@@ -57,13 +70,13 @@ class Asset extends MetadataType {
|
|
|
57
70
|
|
|
58
71
|
/**
|
|
59
72
|
* Retrieves asset metadata for caching
|
|
60
|
-
* @param {
|
|
61
|
-
* @param {
|
|
62
|
-
* @param {
|
|
63
|
-
* @param {
|
|
64
|
-
* @returns {Promise} Promise
|
|
73
|
+
* @param {string} templateDir Directory where retrieved metadata directory will be saved
|
|
74
|
+
* @param {string} name name of the metadata file
|
|
75
|
+
* @param {Util.TemplateMap} templateVariables variables to be replaced in the metadata
|
|
76
|
+
* @param {AssetSubType} [selectedSubType] optionally limit to a single subtype
|
|
77
|
+
* @returns {Promise<{metadata:AssetMap,type:string}>} Promise
|
|
65
78
|
*/
|
|
66
|
-
static async retrieveAsTemplate(templateDir,
|
|
79
|
+
static async retrieveAsTemplate(templateDir, name, templateVariables, selectedSubType) {
|
|
67
80
|
const items = [];
|
|
68
81
|
const subTypes = selectedSubType ? [selectedSubType] : this._getSubTypes();
|
|
69
82
|
await File.initPrettier();
|
|
@@ -76,12 +89,15 @@ class Asset extends MetadataType {
|
|
|
76
89
|
subType,
|
|
77
90
|
this.definition.extendedSubTypes[subType],
|
|
78
91
|
templateDir,
|
|
79
|
-
|
|
92
|
+
name,
|
|
80
93
|
templateVariables
|
|
81
94
|
))
|
|
82
95
|
);
|
|
83
96
|
}
|
|
84
97
|
const metadata = this.parseResponseBody({ items: items });
|
|
98
|
+
if (!Object.keys(metadata).length) {
|
|
99
|
+
Util.logger.error(`${this.definition.type} '${name}' not found on server.`);
|
|
100
|
+
}
|
|
85
101
|
Util.logger.info(`Downloaded: ${this.definition.type} (${Object.keys(metadata).length})`);
|
|
86
102
|
|
|
87
103
|
return { metadata: metadata, type: this.definition.type };
|
|
@@ -89,22 +105,26 @@ class Asset extends MetadataType {
|
|
|
89
105
|
/**
|
|
90
106
|
* helper for retrieve + retrieveAsTemplate
|
|
91
107
|
* @private
|
|
92
|
-
* @returns {
|
|
108
|
+
* @returns {AssetSubType[]} subtype array
|
|
93
109
|
*/
|
|
94
110
|
static _getSubTypes() {
|
|
95
|
-
|
|
111
|
+
const selectedSubTypeArr = this.properties.metaDataTypes.retrieve.filter((type) =>
|
|
112
|
+
type.startsWith('asset-')
|
|
113
|
+
);
|
|
114
|
+
if (
|
|
115
|
+
this.properties.metaDataTypes.retrieve.includes('asset') ||
|
|
116
|
+
!selectedSubTypeArr.length
|
|
117
|
+
) {
|
|
96
118
|
// if "asset" is found in config assume to download the default subtypes only
|
|
97
119
|
return this.definition.typeRetrieveByDefault;
|
|
98
120
|
} else {
|
|
99
|
-
return
|
|
100
|
-
.filter((type) => type.startsWith('asset-'))
|
|
101
|
-
.map((type) => type.replace('asset-', ''));
|
|
121
|
+
return selectedSubTypeArr.map((type) => type.replace('asset-', ''));
|
|
102
122
|
}
|
|
103
123
|
}
|
|
104
124
|
|
|
105
125
|
/**
|
|
106
126
|
* Creates a single asset
|
|
107
|
-
* @param {
|
|
127
|
+
* @param {AssetItem} metadata a single asset
|
|
108
128
|
* @returns {Promise} Promise
|
|
109
129
|
*/
|
|
110
130
|
static create(metadata) {
|
|
@@ -114,7 +134,7 @@ class Asset extends MetadataType {
|
|
|
114
134
|
|
|
115
135
|
/**
|
|
116
136
|
* Updates a single asset
|
|
117
|
-
* @param {
|
|
137
|
+
* @param {AssetItem} metadata a single asset
|
|
118
138
|
* @returns {Promise} Promise
|
|
119
139
|
*/
|
|
120
140
|
static update(metadata) {
|
|
@@ -123,11 +143,11 @@ class Asset extends MetadataType {
|
|
|
123
143
|
}
|
|
124
144
|
/**
|
|
125
145
|
* Retrieves Metadata of a specific asset type
|
|
126
|
-
* @param {
|
|
127
|
-
* @param {
|
|
128
|
-
* @param {
|
|
129
|
-
* @param {
|
|
130
|
-
* @param {
|
|
146
|
+
* @param {AssetSubType} subType group of similar assets to put in a folder (ie. images)
|
|
147
|
+
* @param {AssetSubType[]} subTypeArray list of all asset types within this subtype
|
|
148
|
+
* @param {string} [retrieveDir] target directory for saving assets
|
|
149
|
+
* @param {string} [templateName] name of the metadata file
|
|
150
|
+
* @param {Util.TemplateMap} [templateVariables] variables to be replaced in the metadata
|
|
131
151
|
* @returns {Promise} Promise
|
|
132
152
|
*/
|
|
133
153
|
static async requestSubType(
|
|
@@ -142,6 +162,7 @@ class Asset extends MetadataType {
|
|
|
142
162
|
} else {
|
|
143
163
|
Util.logger.info(`- Caching Subtype: ${subType}`);
|
|
144
164
|
}
|
|
165
|
+
const subtypeIds = subTypeArray?.map(subTypeItemName => Asset.definition.typeMapping[subTypeItemName]);
|
|
145
166
|
const uri = 'asset/v1/content/assets/';
|
|
146
167
|
const options = {
|
|
147
168
|
uri: uri + 'query',
|
|
@@ -158,9 +179,9 @@ class Asset extends MetadataType {
|
|
|
158
179
|
if (templateName) {
|
|
159
180
|
options.json.query = {
|
|
160
181
|
leftOperand: {
|
|
161
|
-
property: 'assetType.
|
|
182
|
+
property: 'assetType.id',
|
|
162
183
|
simpleOperator: 'in',
|
|
163
|
-
value:
|
|
184
|
+
value: subtypeIds,
|
|
164
185
|
},
|
|
165
186
|
logicalOperator: 'AND',
|
|
166
187
|
rightOperand: {
|
|
@@ -171,9 +192,9 @@ class Asset extends MetadataType {
|
|
|
171
192
|
};
|
|
172
193
|
} else {
|
|
173
194
|
options.json.query = {
|
|
174
|
-
property: 'assetType.
|
|
195
|
+
property: 'assetType.id',
|
|
175
196
|
simpleOperator: 'in',
|
|
176
|
-
value:
|
|
197
|
+
value: subtypeIds,
|
|
177
198
|
};
|
|
178
199
|
options.json.sort = [{ property: 'id', direction: 'ASC' }];
|
|
179
200
|
}
|
|
@@ -197,7 +218,10 @@ class Asset extends MetadataType {
|
|
|
197
218
|
let items = [];
|
|
198
219
|
do {
|
|
199
220
|
options.json.page.page = lastPage + 1;
|
|
200
|
-
|
|
221
|
+
let response;
|
|
222
|
+
await Util.retryOnError(`Retrying Subtype: ${subType}`, async () => {
|
|
223
|
+
response = await this.client.RestClient.post(options);
|
|
224
|
+
});
|
|
201
225
|
if (response && response.body && response.body.items && response.body.items.length) {
|
|
202
226
|
// sometimes the api will return a payload without items
|
|
203
227
|
// --> ensure we only add proper items-arrays here
|
|
@@ -209,9 +233,9 @@ class Asset extends MetadataType {
|
|
|
209
233
|
// Since we sort by ID, we can get the last ID then run new requests from there
|
|
210
234
|
options.json.query = {
|
|
211
235
|
leftOperand: {
|
|
212
|
-
property: 'assetType.
|
|
236
|
+
property: 'assetType.id',
|
|
213
237
|
simpleOperator: 'in',
|
|
214
|
-
value:
|
|
238
|
+
value: subtypeIds,
|
|
215
239
|
},
|
|
216
240
|
logicalOperator: 'AND',
|
|
217
241
|
rightOperand: {
|
|
@@ -239,9 +263,9 @@ class Asset extends MetadataType {
|
|
|
239
263
|
/**
|
|
240
264
|
* Retrieves extended metadata (files or extended content) of asset
|
|
241
265
|
* @param {Array} items array of items to retrieve
|
|
242
|
-
* @param {
|
|
243
|
-
* @param {
|
|
244
|
-
* @param {
|
|
266
|
+
* @param {AssetSubType} subType group of similar assets to put in a folder (ie. images)
|
|
267
|
+
* @param {string} retrieveDir target directory for saving assets
|
|
268
|
+
* @param {Util.TemplateMap} [templateVariables] variables to be replaced in the metadata
|
|
245
269
|
* @returns {Promise} Promise
|
|
246
270
|
*/
|
|
247
271
|
static async requestAndSaveExtended(items, subType, retrieveDir, templateVariables) {
|
|
@@ -274,7 +298,7 @@ class Asset extends MetadataType {
|
|
|
274
298
|
) {
|
|
275
299
|
metadata[item.customerKey] = item;
|
|
276
300
|
if (templateVariables) {
|
|
277
|
-
// do this here already because otherwise the extended file could be saved with wrong
|
|
301
|
+
// do this here already because otherwise the extended file could be saved with wrong fileName
|
|
278
302
|
const warningMsg =
|
|
279
303
|
'Ensure that Code that might be loading this via ContentBlockByKey is updated with the new key before deployment.';
|
|
280
304
|
this.overrideKeyWithName(item, warningMsg);
|
|
@@ -320,9 +344,9 @@ class Asset extends MetadataType {
|
|
|
320
344
|
/**
|
|
321
345
|
* Some metadata types store their actual content as a separate file, e.g. images
|
|
322
346
|
* This method retrieves these and saves them alongside the metadata json
|
|
323
|
-
* @param {
|
|
324
|
-
* @param {
|
|
325
|
-
* @param {
|
|
347
|
+
* @param {AssetItem} metadata a single asset
|
|
348
|
+
* @param {AssetSubType} subType group of similar assets to put in a folder (ie. images)
|
|
349
|
+
* @param {string} retrieveDir target directory for saving assets
|
|
326
350
|
* @returns {Promise<void>} -
|
|
327
351
|
*/
|
|
328
352
|
static async _retrieveExtendedFile(metadata, subType, retrieveDir) {
|
|
@@ -330,14 +354,14 @@ class Asset extends MetadataType {
|
|
|
330
354
|
uri: 'asset/v1/content/assets/' + metadata.id + '/file',
|
|
331
355
|
});
|
|
332
356
|
|
|
333
|
-
// to handle uploaded files that bear the same name, SFMC engineers decided to add a number after the
|
|
357
|
+
// to handle uploaded files that bear the same name, SFMC engineers decided to add a number after the fileName
|
|
334
358
|
// however, their solution was not following standards: fileName="header.png (4) " and then extension="png (4) "
|
|
335
|
-
const
|
|
359
|
+
const fileExt = metadata.fileProperties.extension.split(' ')[0];
|
|
336
360
|
|
|
337
361
|
File.writeToFile(
|
|
338
362
|
[retrieveDir, this.definition.type, subType],
|
|
339
363
|
metadata.customerKey,
|
|
340
|
-
|
|
364
|
+
fileExt,
|
|
341
365
|
file.body,
|
|
342
366
|
'base64'
|
|
343
367
|
);
|
|
@@ -346,31 +370,31 @@ class Asset extends MetadataType {
|
|
|
346
370
|
* helper for this.preDeployTasks()
|
|
347
371
|
* Some metadata types store their actual content as a separate file, e.g. images
|
|
348
372
|
* This method reads these from the local FS stores them in the metadata object allowing to deploy it
|
|
349
|
-
* @param {
|
|
350
|
-
* @param {
|
|
351
|
-
* @param {
|
|
373
|
+
* @param {AssetItem} metadata a single asset
|
|
374
|
+
* @param {AssetSubType} subType group of similar assets to put in a folder (ie. images)
|
|
375
|
+
* @param {string} deployDir directory of deploy files
|
|
352
376
|
* @returns {Promise<void>} -
|
|
353
377
|
*/
|
|
354
378
|
static async _readExtendedFileFromFS(metadata, subType, deployDir) {
|
|
355
379
|
if (metadata.fileProperties && metadata.fileProperties.extension) {
|
|
356
|
-
// to handle uploaded files that bear the same name, SFMC engineers decided to add a number after the
|
|
380
|
+
// to handle uploaded files that bear the same name, SFMC engineers decided to add a number after the fileName
|
|
357
381
|
// however, their solution was not following standards: fileName="header.png (4) " and then extension="png (4) "
|
|
358
|
-
const
|
|
382
|
+
const fileExt = metadata.fileProperties.extension.split(' ')[0];
|
|
359
383
|
|
|
360
384
|
metadata.file = await File.readFile(
|
|
361
385
|
[deployDir, this.definition.type, subType],
|
|
362
386
|
metadata.customerKey,
|
|
363
|
-
|
|
387
|
+
fileExt,
|
|
364
388
|
'base64'
|
|
365
389
|
);
|
|
366
390
|
}
|
|
367
391
|
}
|
|
368
392
|
/**
|
|
369
393
|
* manages post retrieve steps
|
|
370
|
-
* @param {
|
|
371
|
-
* @param {
|
|
394
|
+
* @param {AssetItem} metadata a single asset
|
|
395
|
+
* @param {string} [_] unused
|
|
372
396
|
* @param {Boolean} isTemplating signals that we are retrieving templates
|
|
373
|
-
* @returns {
|
|
397
|
+
* @returns {CodeExtractItem} metadata
|
|
374
398
|
*/
|
|
375
399
|
static postRetrieveTasks(metadata, _, isTemplating) {
|
|
376
400
|
// if retrieving template, replace the name with customer key if that wasn't already the case
|
|
@@ -384,9 +408,9 @@ class Asset extends MetadataType {
|
|
|
384
408
|
|
|
385
409
|
/**
|
|
386
410
|
* prepares an asset definition for deployment
|
|
387
|
-
* @param {
|
|
388
|
-
* @param {
|
|
389
|
-
* @returns {Promise} Promise
|
|
411
|
+
* @param {AssetItem} metadata a single asset
|
|
412
|
+
* @param {string} deployDir directory of deploy files
|
|
413
|
+
* @returns {Promise<AssetItem>} Promise
|
|
390
414
|
*/
|
|
391
415
|
static async preDeployTasks(metadata, deployDir) {
|
|
392
416
|
// additonalattributes fail where the value is "" so we need to remove them from deploy
|
|
@@ -418,14 +442,14 @@ class Asset extends MetadataType {
|
|
|
418
442
|
await this._mergeCode(metadata, deployDir, subType);
|
|
419
443
|
|
|
420
444
|
// #2 get file from local disk and insert as base64
|
|
421
|
-
await this._readExtendedFileFromFS(metadata,
|
|
445
|
+
await this._readExtendedFileFromFS(metadata, subType, deployDir);
|
|
422
446
|
|
|
423
447
|
return metadata;
|
|
424
448
|
}
|
|
425
449
|
/**
|
|
426
450
|
* determines the subtype of the current asset
|
|
427
|
-
* @param {
|
|
428
|
-
* @returns {
|
|
451
|
+
* @param {AssetItem} metadata a single asset
|
|
452
|
+
* @returns {AssetSubType} subtype
|
|
429
453
|
*/
|
|
430
454
|
static getSubtype(metadata) {
|
|
431
455
|
for (const sub in this.definition.extendedSubTypes) {
|
|
@@ -438,12 +462,12 @@ class Asset extends MetadataType {
|
|
|
438
462
|
/**
|
|
439
463
|
* helper for buildDefinition
|
|
440
464
|
* handles extracted code if any are found for complex types
|
|
441
|
-
* @param {
|
|
442
|
-
* @param {
|
|
443
|
-
* @param {
|
|
444
|
-
* @param {
|
|
445
|
-
* @param {
|
|
446
|
-
* @returns {Promise} Promise
|
|
465
|
+
* @param {string} templateDir Directory where metadata templates are stored
|
|
466
|
+
* @param {string} targetDir Directory where built definitions will be saved
|
|
467
|
+
* @param {AssetItem} metadata main JSON file that was read from file system
|
|
468
|
+
* @param {Util.TemplateMap} variables variables to be replaced in the metadata
|
|
469
|
+
* @param {string} templateName name of the template to be built
|
|
470
|
+
* @returns {Promise<void>} Promise
|
|
447
471
|
*/
|
|
448
472
|
static async buildDefinitionForExtracts(
|
|
449
473
|
templateDir,
|
|
@@ -468,27 +492,27 @@ class Asset extends MetadataType {
|
|
|
468
492
|
throw new Error(
|
|
469
493
|
`${this.definition.type}:: Error applying template variables on ${
|
|
470
494
|
metadata[this.definition.keyField]
|
|
471
|
-
}: ${extractedFile.
|
|
495
|
+
}: ${extractedFile.fileName}.${extractedFile.fileExt}.`
|
|
472
496
|
);
|
|
473
497
|
}
|
|
474
498
|
}
|
|
475
499
|
|
|
476
500
|
// #2 binary extracts
|
|
477
501
|
if (metadata.fileProperties && metadata.fileProperties.extension) {
|
|
478
|
-
// to handle uploaded files that bear the same name, SFMC engineers decided to add a number after the
|
|
502
|
+
// to handle uploaded files that bear the same name, SFMC engineers decided to add a number after the fileName
|
|
479
503
|
// however, their solution was not following standards: fileName="header.png (4) " and then extension="png (4) "
|
|
480
|
-
const
|
|
504
|
+
const fileExt = metadata.fileProperties.extension.split(' ')[0];
|
|
481
505
|
|
|
482
506
|
const filecontent = await File.readFile(
|
|
483
507
|
[templateDir, this.definition.type, subType],
|
|
484
508
|
metadata.customerKey,
|
|
485
|
-
|
|
509
|
+
fileExt,
|
|
486
510
|
'base64'
|
|
487
511
|
);
|
|
488
512
|
fileList.push({
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
513
|
+
subFolder: [this.definition.type, subType],
|
|
514
|
+
fileName: metadata.customerKey,
|
|
515
|
+
fileExt: fileExt,
|
|
492
516
|
content: filecontent,
|
|
493
517
|
encoding: 'base64',
|
|
494
518
|
});
|
|
@@ -499,9 +523,9 @@ class Asset extends MetadataType {
|
|
|
499
523
|
for (const targetDir of targetDirArr) {
|
|
500
524
|
for (const extractedFile of fileList) {
|
|
501
525
|
File.writeToFile(
|
|
502
|
-
[targetDir, ...extractedFile.
|
|
503
|
-
extractedFile.
|
|
504
|
-
extractedFile.
|
|
526
|
+
[targetDir, ...extractedFile.subFolder],
|
|
527
|
+
extractedFile.fileName,
|
|
528
|
+
extractedFile.fileExt,
|
|
505
529
|
extractedFile.content,
|
|
506
530
|
extractedFile.encoding || null
|
|
507
531
|
);
|
|
@@ -511,8 +535,8 @@ class Asset extends MetadataType {
|
|
|
511
535
|
|
|
512
536
|
/**
|
|
513
537
|
* parses retrieved Metadata before saving
|
|
514
|
-
* @param {
|
|
515
|
-
* @returns {
|
|
538
|
+
* @param {AssetItem} metadata a single asset definition
|
|
539
|
+
* @returns {CodeExtractItem} parsed metadata definition
|
|
516
540
|
*/
|
|
517
541
|
static parseMetadata(metadata) {
|
|
518
542
|
// folder
|
|
@@ -538,11 +562,11 @@ class Asset extends MetadataType {
|
|
|
538
562
|
}
|
|
539
563
|
/**
|
|
540
564
|
* helper for this.preDeployTasks() that loads extracted code content back into JSON
|
|
541
|
-
* @param {
|
|
542
|
-
* @param {
|
|
543
|
-
* @param {
|
|
544
|
-
* @param {
|
|
545
|
-
* @returns {Promise<
|
|
565
|
+
* @param {AssetItem} metadata a single asset definition
|
|
566
|
+
* @param {string} deployDir directory of deploy files
|
|
567
|
+
* @param {AssetSubType} subType asset-subtype name
|
|
568
|
+
* @param {string} [templateName] name of the template used to built defintion (prior applying templating)
|
|
569
|
+
* @returns {Promise<MetadataType.CodeExtract[]>} fileList for templating (disregarded during deployment)
|
|
546
570
|
*/
|
|
547
571
|
static async _mergeCode(metadata, deployDir, subType, templateName) {
|
|
548
572
|
const subtypeExtension = `.${this.definition.type}-${subType}-meta`;
|
|
@@ -578,9 +602,9 @@ class Asset extends MetadataType {
|
|
|
578
602
|
if (templateName) {
|
|
579
603
|
// to use this method in templating, store a copy of the info in fileList
|
|
580
604
|
fileList.push({
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
605
|
+
subFolder: [...subDirArr, metadata.customerKey],
|
|
606
|
+
fileName: 'index' + subtypeExtension,
|
|
607
|
+
fileExt: 'html',
|
|
584
608
|
content: metadata.views.html.content,
|
|
585
609
|
});
|
|
586
610
|
}
|
|
@@ -623,9 +647,9 @@ class Asset extends MetadataType {
|
|
|
623
647
|
if (templateName) {
|
|
624
648
|
// to use this method in templating, store a copy of the info in fileList
|
|
625
649
|
fileList.push({
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
650
|
+
subFolder: subDirArr,
|
|
651
|
+
fileName: metadata.customerKey + subtypeExtension,
|
|
652
|
+
fileExt: 'html',
|
|
629
653
|
content: metadata.views.text.content,
|
|
630
654
|
});
|
|
631
655
|
}
|
|
@@ -658,9 +682,9 @@ class Asset extends MetadataType {
|
|
|
658
682
|
if (templateName) {
|
|
659
683
|
// to use this method in templating, store a copy of the info in fileList
|
|
660
684
|
fileList.push({
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
685
|
+
subFolder: subDirArr,
|
|
686
|
+
fileName: metadata.customerKey + subtypeExtension,
|
|
687
|
+
fileExt: 'html',
|
|
664
688
|
content: metadata.content,
|
|
665
689
|
});
|
|
666
690
|
}
|
|
@@ -672,12 +696,12 @@ class Asset extends MetadataType {
|
|
|
672
696
|
/**
|
|
673
697
|
* helper for this.preDeployTasks() that loads extracted code content back into JSON
|
|
674
698
|
* @param {Object} metadataSlots metadata.views.html.slots or deeper slots.<>.blocks.<>.slots
|
|
675
|
-
* @param {
|
|
676
|
-
* @param {
|
|
677
|
-
* @param {
|
|
699
|
+
* @param {string[]} readDirArr directory of deploy files
|
|
700
|
+
* @param {string} subtypeExtension asset-subtype name ending on -meta
|
|
701
|
+
* @param {string[]} subDirArr directory of files w/o leading deploy dir
|
|
678
702
|
* @param {Object[]} fileList directory of files w/o leading deploy dir
|
|
679
|
-
* @param {
|
|
680
|
-
* @param {
|
|
703
|
+
* @param {string} customerKey external key of template (could have been changed if used during templating)
|
|
704
|
+
* @param {string} [templateName] name of the template used to built defintion (prior applying templating)
|
|
681
705
|
* @returns {Promise<void>} -
|
|
682
706
|
*/
|
|
683
707
|
static async _mergeCode_slots(
|
|
@@ -696,13 +720,13 @@ class Asset extends MetadataType {
|
|
|
696
720
|
if (slotObj.blocks) {
|
|
697
721
|
for (const block in slotObj.blocks) {
|
|
698
722
|
if (Object.prototype.hasOwnProperty.call(slotObj.blocks, block)) {
|
|
699
|
-
const
|
|
723
|
+
const fileName = `${slot}-${block}${subtypeExtension}`;
|
|
700
724
|
if (
|
|
701
725
|
File.existsSync(
|
|
702
726
|
File.normalizePath([
|
|
703
727
|
...readDirArr,
|
|
704
728
|
'blocks',
|
|
705
|
-
`${
|
|
729
|
+
`${fileName}.html`,
|
|
706
730
|
])
|
|
707
731
|
)
|
|
708
732
|
) {
|
|
@@ -710,15 +734,15 @@ class Asset extends MetadataType {
|
|
|
710
734
|
// if an extracted block was found, save it back into JSON
|
|
711
735
|
slotObj.blocks[block].content = await File.readFile(
|
|
712
736
|
[...readDirArr, 'blocks'],
|
|
713
|
-
|
|
737
|
+
fileName,
|
|
714
738
|
'html'
|
|
715
739
|
);
|
|
716
740
|
if (templateName) {
|
|
717
741
|
// to use this method in templating, store a copy of the info in fileList
|
|
718
742
|
fileList.push({
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
743
|
+
subFolder: [...subDirArr, customerKey, 'blocks'],
|
|
744
|
+
fileName: fileName,
|
|
745
|
+
fileExt: 'html',
|
|
722
746
|
content: slotObj.blocks[block].content,
|
|
723
747
|
});
|
|
724
748
|
}
|
|
@@ -744,8 +768,8 @@ class Asset extends MetadataType {
|
|
|
744
768
|
/**
|
|
745
769
|
* helper for this.parseMetadata() that finds code content in JSON and extracts it
|
|
746
770
|
* to allow saving that separately and formatted
|
|
747
|
-
* @param {
|
|
748
|
-
* @returns {
|
|
771
|
+
* @param {AssetItem} metadata a single asset definition
|
|
772
|
+
* @returns {CodeExtractItem} { json: metadata, codeArr: object[], subFolder: string[] }
|
|
749
773
|
*/
|
|
750
774
|
static _extractCode(metadata) {
|
|
751
775
|
const codeArr = [];
|
|
@@ -835,8 +859,8 @@ class Asset extends MetadataType {
|
|
|
835
859
|
}
|
|
836
860
|
}
|
|
837
861
|
/**
|
|
838
|
-
* Returns file contents mapped to their
|
|
839
|
-
* @param {
|
|
862
|
+
* Returns file contents mapped to their fileName without '.json' ending
|
|
863
|
+
* @param {string} dir directory that contains '.json' files to be read
|
|
840
864
|
* @returns {Object} fileName => fileContent map
|
|
841
865
|
*/
|
|
842
866
|
static getJsonFromFS(dir) {
|
|
@@ -850,7 +874,7 @@ class Asset extends MetadataType {
|
|
|
850
874
|
files.forEach((dirent) => {
|
|
851
875
|
try {
|
|
852
876
|
let thisDir = currentdir;
|
|
853
|
-
let
|
|
877
|
+
let fileName = dirent.name;
|
|
854
878
|
if (dirent.isDirectory()) {
|
|
855
879
|
// complex types with more than one extracted piece of code are saved in their
|
|
856
880
|
// own subfolder (with folder name = CustomerKey)
|
|
@@ -860,20 +884,20 @@ class Asset extends MetadataType {
|
|
|
860
884
|
);
|
|
861
885
|
subfolderFiles.forEach((subFileName) => {
|
|
862
886
|
if (subFileName.endsWith('-meta.json')) {
|
|
863
|
-
|
|
887
|
+
fileName = subFileName;
|
|
864
888
|
thisDir = File.normalizePath([currentdir, dirent.name]);
|
|
865
889
|
}
|
|
866
890
|
});
|
|
867
891
|
}
|
|
868
|
-
if (
|
|
892
|
+
if (fileName.endsWith('-meta.json')) {
|
|
869
893
|
const fileContent = File.readJSONFile(
|
|
870
894
|
thisDir,
|
|
871
|
-
|
|
895
|
+
fileName,
|
|
872
896
|
true,
|
|
873
897
|
false
|
|
874
898
|
);
|
|
875
899
|
// subtype will change the metadata suffix length
|
|
876
|
-
const fileNameWithoutEnding =
|
|
900
|
+
const fileNameWithoutEnding = fileName.slice(
|
|
877
901
|
0,
|
|
878
902
|
-17 - subtype.length
|
|
879
903
|
);
|
|
@@ -895,9 +919,9 @@ class Asset extends MetadataType {
|
|
|
895
919
|
}
|
|
896
920
|
/**
|
|
897
921
|
* check template directory for complex types that open subfolders for their subtypes
|
|
898
|
-
* @param {
|
|
899
|
-
* @param {
|
|
900
|
-
* @returns {
|
|
922
|
+
* @param {string} templateDir Directory where metadata templates are stored
|
|
923
|
+
* @param {string} templateName name of the metadata file
|
|
924
|
+
* @returns {AssetSubType} subtype name
|
|
901
925
|
*/
|
|
902
926
|
static findSubType(templateDir, templateName) {
|
|
903
927
|
const typeDirArr = [this.definition.type];
|
|
@@ -928,11 +952,11 @@ class Asset extends MetadataType {
|
|
|
928
952
|
}
|
|
929
953
|
/**
|
|
930
954
|
* optional method used for some types to try a different folder structure
|
|
931
|
-
* @param {
|
|
932
|
-
* @param {
|
|
933
|
-
* @param {
|
|
934
|
-
* @param {
|
|
935
|
-
* @returns {
|
|
955
|
+
* @param {string} templateDir Directory where metadata templates are stored
|
|
956
|
+
* @param {string[]} typeDirArr current subdir for this type
|
|
957
|
+
* @param {string} templateName name of the metadata template
|
|
958
|
+
* @param {string} fileName name of the metadata template file w/o extension
|
|
959
|
+
* @returns {AssetItem} metadata
|
|
936
960
|
*/
|
|
937
961
|
static async readSecondaryFolder(templateDir, typeDirArr, templateName, fileName) {
|
|
938
962
|
// handles subtypes that create 1 folder per asset -> currently causes the below File.ReadFile to error out
|