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/jsconfig.json
CHANGED
package/lib/Builder.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const TYPE = require('../types/mcdev.d');
|
|
3
4
|
const Util = require('./util/util');
|
|
4
|
-
|
|
5
|
+
const File = require('./util/file');
|
|
6
|
+
const config = require('./util/config');
|
|
7
|
+
const Cli = require('./util/cli');
|
|
8
|
+
const auth = require('./util/auth');
|
|
5
9
|
const MetadataTypeInfo = require('./MetadataTypeInfo');
|
|
6
10
|
// @ts-ignore
|
|
7
11
|
|
|
@@ -12,50 +16,46 @@ class Builder {
|
|
|
12
16
|
/**
|
|
13
17
|
* Creates a Builder, uses v2 auth if v2AuthOptions are passed.
|
|
14
18
|
*
|
|
15
|
-
* @param {
|
|
16
|
-
|
|
17
|
-
* @param {
|
|
18
|
-
* @param {Object} properties.directories list of default directories
|
|
19
|
-
* @param {String} properties.directories.template where templates are saved
|
|
20
|
-
* @param {String} properties.directories.templateBuilds where template-based deployment definitions are saved
|
|
21
|
-
* @param {String} properties.tenant v2 Auth Tenant Information
|
|
22
|
-
* @param {String} properties.businessUnits ID of Business Unit to authenticate with
|
|
23
|
-
* @param {Object} buObject properties for auth
|
|
24
|
-
* @param {String} buObject.clientId clientId for FuelSDK auth
|
|
25
|
-
* @param {String} buObject.clientSecret clientSecret for FuelSDK auth
|
|
26
|
-
* @param {Object} buObject.credential clientId for FuelSDK auth
|
|
27
|
-
* @param {String} buObject.tenant v2 Auth Tenant Information
|
|
28
|
-
* @param {String} buObject.mid ID of Business Unit to authenticate with
|
|
29
|
-
* @param {String} buObject.businessUnit name of Business Unit to authenticate with
|
|
30
|
-
* @param {Util.ET_Client} client fuel client
|
|
19
|
+
* @param {TYPE.Mcdevrc} properties properties for auth
|
|
20
|
+
saved
|
|
21
|
+
* @param {TYPE.BuObject} buObject properties for auth
|
|
31
22
|
*/
|
|
32
|
-
constructor(properties, buObject
|
|
33
|
-
this.client = client;
|
|
23
|
+
constructor(properties, buObject) {
|
|
34
24
|
this.properties = properties;
|
|
35
25
|
this.templateDir = properties.directories.template;
|
|
26
|
+
this.retrieveDir = File.normalizePath([
|
|
27
|
+
properties.directories.retrieve,
|
|
28
|
+
buObject.credential,
|
|
29
|
+
buObject.businessUnit,
|
|
30
|
+
]);
|
|
31
|
+
this.buObject = buObject;
|
|
36
32
|
|
|
37
33
|
// allow multiple target directories
|
|
38
34
|
const templateBuildsArr = Array.isArray(properties.directories.templateBuilds)
|
|
39
35
|
? properties.directories.templateBuilds
|
|
40
36
|
: [properties.directories.templateBuilds];
|
|
41
|
-
|
|
42
37
|
this.targetDir = templateBuildsArr.map(
|
|
43
38
|
(directoriesTemplateBuilds) =>
|
|
44
39
|
directoriesTemplateBuilds + buObject.credential + '/' + buObject.businessUnit
|
|
45
40
|
);
|
|
46
41
|
|
|
42
|
+
/**
|
|
43
|
+
* @type {TYPE.MultiMetadataTypeList}
|
|
44
|
+
*/
|
|
47
45
|
this.metadata = {};
|
|
48
46
|
}
|
|
49
47
|
|
|
50
48
|
/**
|
|
51
49
|
* Builds a specific metadata file by name
|
|
52
|
-
*
|
|
53
|
-
* @param {
|
|
54
|
-
* @param {
|
|
55
|
-
* @
|
|
50
|
+
*
|
|
51
|
+
* @param {string} metadataType metadata type to build
|
|
52
|
+
* @param {string} name name of metadata to build
|
|
53
|
+
* @param {TYPE.TemplateMap} templateVariables variables to be replaced in the metadata
|
|
54
|
+
* @returns {Promise.<TYPE.MultiMetadataTypeList>} Promise
|
|
56
55
|
*/
|
|
57
|
-
async
|
|
56
|
+
async _buildDefinition(metadataType, name, templateVariables) {
|
|
58
57
|
let nameArr;
|
|
58
|
+
/* eslint-disable unicorn/prefer-ternary */
|
|
59
59
|
if (name.includes(',')) {
|
|
60
60
|
nameArr = name.split(',').map((item) =>
|
|
61
61
|
// allow whitespace in comma-separated lists
|
|
@@ -64,6 +64,8 @@ class Builder {
|
|
|
64
64
|
} else {
|
|
65
65
|
nameArr = [name.trim()];
|
|
66
66
|
}
|
|
67
|
+
/* eslint-enable unicorn/prefer-ternary */
|
|
68
|
+
|
|
67
69
|
const type = metadataType;
|
|
68
70
|
try {
|
|
69
71
|
const result = await Promise.all(
|
|
@@ -72,78 +74,173 @@ class Builder {
|
|
|
72
74
|
// we hence require users to put %20 in their stead and have to convert that back
|
|
73
75
|
name = name.split('%20').join(' ');
|
|
74
76
|
|
|
75
|
-
MetadataTypeInfo[type].
|
|
76
|
-
MetadataTypeInfo[type].client = this.client;
|
|
77
|
+
MetadataTypeInfo[type].client = auth.getSDK(this.buObject);
|
|
77
78
|
MetadataTypeInfo[type].properties = this.properties;
|
|
79
|
+
MetadataTypeInfo[type].buObject = this.buObject;
|
|
78
80
|
return MetadataTypeInfo[type].buildDefinition(
|
|
79
81
|
this.templateDir,
|
|
80
82
|
this.targetDir,
|
|
81
83
|
name,
|
|
82
|
-
|
|
84
|
+
templateVariables
|
|
83
85
|
);
|
|
84
86
|
})
|
|
85
87
|
);
|
|
86
88
|
if (result) {
|
|
87
89
|
this.metadata[result[0].type] = [];
|
|
88
|
-
|
|
90
|
+
for (const element of result) {
|
|
89
91
|
this.metadata[result[0].type].push(element.metadata);
|
|
90
|
-
}
|
|
92
|
+
}
|
|
91
93
|
}
|
|
92
94
|
} catch (ex) {
|
|
93
|
-
Util.logger.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
Util.logger.errorStack(ex, 'mcdev.buildDefinition');
|
|
96
|
+
}
|
|
97
|
+
return this.metadata;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Build a template based on a list of metadata files in the retrieve folder.
|
|
101
|
+
*
|
|
102
|
+
* @param {string} businessUnit references credentials from properties.json
|
|
103
|
+
* @param {string} selectedType supported metadata type
|
|
104
|
+
* @param {string[]} keyArr customerkey of the metadata
|
|
105
|
+
* @param {string} market market localizations
|
|
106
|
+
* @returns {Promise.<TYPE.MultiMetadataTypeList>} -
|
|
107
|
+
*/
|
|
108
|
+
static async buildTemplate(businessUnit, selectedType, keyArr, market) {
|
|
109
|
+
const properties = await config.getProperties();
|
|
110
|
+
if (!(await config.checkProperties(properties))) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
if (!Util._isValidType(selectedType)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (selectedType.includes('-')) {
|
|
117
|
+
Util.logger.error(
|
|
118
|
+
`:: '${selectedType}' is not a valid metadata type. Please don't include subtypes.`
|
|
119
|
+
);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const buObject = await Cli.getCredentialObject(properties, businessUnit);
|
|
123
|
+
if (buObject !== null) {
|
|
124
|
+
const builder = new Builder(properties, buObject);
|
|
125
|
+
if (Util.checkMarket(market, properties)) {
|
|
126
|
+
return builder._buildTemplate(selectedType, keyArr, properties.markets[market]);
|
|
97
127
|
}
|
|
98
128
|
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Build a template based on a list of metadata files in the retrieve folder.
|
|
132
|
+
*
|
|
133
|
+
* @param {string} metadataType metadata type to create a template of
|
|
134
|
+
* @param {string[]} keyArr customerkey of metadata to create a template of
|
|
135
|
+
* @param {TYPE.TemplateMap} templateVariables variables to be replaced in the metadata
|
|
136
|
+
* @returns {Promise.<TYPE.MultiMetadataTypeList>} Promise
|
|
137
|
+
*/
|
|
138
|
+
async _buildTemplate(metadataType, keyArr, templateVariables) {
|
|
139
|
+
const type = metadataType;
|
|
140
|
+
try {
|
|
141
|
+
/** @type {TYPE.MetadataTypeItemObj[]} */
|
|
142
|
+
const result = await Promise.all(
|
|
143
|
+
keyArr.map((key) => {
|
|
144
|
+
MetadataTypeInfo[type].client = this.client;
|
|
145
|
+
MetadataTypeInfo[type].properties = this.properties;
|
|
146
|
+
MetadataTypeInfo[type].buObject = this.buObject;
|
|
147
|
+
|
|
148
|
+
/** @type {TYPE.MetadataTypeItemObj} */
|
|
149
|
+
return MetadataTypeInfo[type].buildTemplate(
|
|
150
|
+
this.retrieveDir,
|
|
151
|
+
this.templateDir,
|
|
152
|
+
key,
|
|
153
|
+
templateVariables
|
|
154
|
+
);
|
|
155
|
+
})
|
|
156
|
+
);
|
|
157
|
+
if (result) {
|
|
158
|
+
this.metadata[result[0].type] = result.map((element) => element.metadata);
|
|
159
|
+
}
|
|
160
|
+
} catch (ex) {
|
|
161
|
+
Util.logger.errorStack(ex, 'mcdev.buildTemplate');
|
|
162
|
+
}
|
|
99
163
|
return this.metadata;
|
|
100
164
|
}
|
|
101
165
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
* @param {
|
|
105
|
-
* @param {
|
|
106
|
-
* @param {
|
|
107
|
-
* @param {
|
|
108
|
-
* @returns {
|
|
166
|
+
* Build a specific metadata file based on a template.
|
|
167
|
+
*
|
|
168
|
+
* @param {string} businessUnit references credentials from properties.json
|
|
169
|
+
* @param {string} selectedType supported metadata type
|
|
170
|
+
* @param {string} name name of the metadata
|
|
171
|
+
* @param {string} market market localizations
|
|
172
|
+
* @returns {Promise.<TYPE.MultiMetadataTypeList>} -
|
|
109
173
|
*/
|
|
110
|
-
static
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
174
|
+
static async buildDefinition(businessUnit, selectedType, name, market) {
|
|
175
|
+
const properties = await config.getProperties();
|
|
176
|
+
if (!(await config.checkProperties(properties))) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
if (!Util._isValidType(selectedType)) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (selectedType.includes('-')) {
|
|
183
|
+
Util.logger.error(
|
|
184
|
+
`:: '${selectedType}' is not a valid metadata type. Please don't include subtypes.`
|
|
185
|
+
);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const buObject = await Cli.getCredentialObject(properties, businessUnit);
|
|
189
|
+
if (buObject !== null) {
|
|
190
|
+
const builder = new Builder(properties, buObject);
|
|
191
|
+
if (Util.checkMarket(market, properties)) {
|
|
192
|
+
return builder._buildDefinition(selectedType, name, properties.markets[market]);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Build a specific metadata file based on a template using a list of bu-market combos
|
|
198
|
+
*
|
|
199
|
+
* @param {string} listName name of list of BU-market combos
|
|
200
|
+
* @param {string} type supported metadata type
|
|
201
|
+
* @param {string} name name of the metadata
|
|
202
|
+
* @returns {Promise.<TYPE.MultiMetadataTypeList[]>} -
|
|
203
|
+
*/
|
|
204
|
+
static async buildDefinitionBulk(listName, type, name) {
|
|
205
|
+
const properties = await config.getProperties();
|
|
206
|
+
if (!(await config.checkProperties(properties))) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
Util.verifyMarketList(listName, properties);
|
|
210
|
+
if (type && !MetadataTypeInfo[type]) {
|
|
211
|
+
Util.logger.error(`:: '${type}' is not a valid metadata type`);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
let i = 0;
|
|
215
|
+
const bdPromises = [];
|
|
116
216
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// check if markets are valid
|
|
130
|
-
let marketArr = properties.marketList[mlName][businessUnit];
|
|
131
|
-
if ('string' === typeof marketArr) {
|
|
132
|
-
marketArr = [marketArr];
|
|
133
|
-
}
|
|
134
|
-
for (const market of marketArr) {
|
|
135
|
-
if (!properties.markets[market]) {
|
|
136
|
-
throw new Error(`Market '${market}' is not defined.`);
|
|
137
|
-
} else {
|
|
138
|
-
// * markets can be empty or include variables. Nothing we can test here
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
217
|
+
for (const businessUnit in properties.marketList[listName]) {
|
|
218
|
+
if (businessUnit === 'description') {
|
|
219
|
+
// skip, it's just a metadata on this list and not a BU
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
i++;
|
|
223
|
+
const market = properties.marketList[listName][businessUnit];
|
|
224
|
+
let marketList = [];
|
|
225
|
+
if ('string' === typeof market) {
|
|
226
|
+
marketList.push(market);
|
|
227
|
+
} else {
|
|
228
|
+
marketList = market;
|
|
142
229
|
}
|
|
143
|
-
|
|
144
|
-
|
|
230
|
+
for (const market of marketList) {
|
|
231
|
+
if (Util.checkMarket(market, properties)) {
|
|
232
|
+
Util.logger.info(`Executing for '${businessUnit}': '${market}'`);
|
|
233
|
+
// omitting "await" to speed up creation
|
|
234
|
+
bdPromises.push(this.buildDefinition(businessUnit, type, name, market));
|
|
235
|
+
}
|
|
145
236
|
}
|
|
146
237
|
}
|
|
238
|
+
const response = await Promise.all(bdPromises);
|
|
239
|
+
|
|
240
|
+
if (!i) {
|
|
241
|
+
Util.logger.error('Please define properties.marketList in your config');
|
|
242
|
+
}
|
|
243
|
+
return response;
|
|
147
244
|
}
|
|
148
245
|
}
|
|
149
246
|
|