mcdev 3.0.1 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +1 -1
- package/.github/ISSUE_TEMPLATE/bug.yml +72 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- package/.github/ISSUE_TEMPLATE/task.md +10 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +11 -0
- package/.issuetracker +11 -3
- package/.vscode/settings.json +3 -3
- package/CHANGELOG.md +103 -1
- package/README.md +245 -141
- package/boilerplate/config.json +3 -2
- package/docs/dist/documentation.md +803 -337
- package/lib/Deployer.js +4 -1
- package/lib/MetadataTypeDefinitions.js +1 -0
- package/lib/MetadataTypeInfo.js +1 -0
- package/lib/Retriever.js +32 -17
- package/lib/cli.js +295 -0
- package/lib/index.js +774 -1019
- package/lib/metadataTypes/AccountUser.js +389 -0
- package/lib/metadataTypes/Asset.js +20 -12
- package/lib/metadataTypes/Automation.js +115 -52
- package/lib/metadataTypes/DataExtension.js +159 -113
- package/lib/metadataTypes/DataExtensionField.js +134 -4
- package/lib/metadataTypes/Folder.js +66 -69
- package/lib/metadataTypes/ImportFile.js +4 -6
- package/lib/metadataTypes/MetadataType.js +136 -67
- package/lib/metadataTypes/Query.js +2 -3
- package/lib/metadataTypes/Role.js +13 -8
- package/lib/metadataTypes/definitions/AccountUser.definition.js +227 -0
- package/lib/metadataTypes/definitions/Asset.definition.js +1 -0
- package/lib/metadataTypes/definitions/Campaign.definition.js +1 -1
- package/lib/metadataTypes/definitions/DataExtension.definition.js +1 -1
- package/lib/metadataTypes/definitions/DataExtensionField.definition.js +1 -1
- package/lib/metadataTypes/definitions/Folder.definition.js +1 -1
- package/lib/metadataTypes/definitions/ImportFile.definition.js +2 -1
- package/lib/metadataTypes/definitions/Script.definition.js +5 -5
- package/lib/retrieveChangelog.js +96 -0
- package/lib/util/cli.js +4 -6
- package/lib/util/init.git.js +2 -1
- package/lib/util/util.js +31 -15
- package/package.json +19 -23
- package/img/README.md/troubleshoot-nodejs-postinstall.jpg +0 -0
- package/postinstall.js +0 -41
package/lib/Deployer.js
CHANGED
|
@@ -81,7 +81,10 @@ class Deployer {
|
|
|
81
81
|
MetadataTypeInfo[type].client = this.client;
|
|
82
82
|
MetadataTypeInfo[type].properties = this.properties;
|
|
83
83
|
Util.logger.info('Caching dependent Metadata: ' + metadataType);
|
|
84
|
-
|
|
84
|
+
let result;
|
|
85
|
+
await Util.retryOnError(`Retrying ${type}`, async () => {
|
|
86
|
+
result = await MetadataTypeInfo[type].retrieveForCache(this.buObject, subType);
|
|
87
|
+
});
|
|
85
88
|
this.cache[type] = result.metadata;
|
|
86
89
|
}
|
|
87
90
|
// deploy metadata files, extending cache once deploys
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Provides access to all metadataType classes
|
|
5
5
|
*/
|
|
6
6
|
const MetadataTypeDefinitions = {
|
|
7
|
+
accountUser: require('./metadataTypes/definitions/AccountUser.definition'),
|
|
7
8
|
asset: require('./metadataTypes/definitions/Asset.definition'),
|
|
8
9
|
attributeGroup: require('./metadataTypes/definitions/AttributeGroup.definition'),
|
|
9
10
|
automation: require('./metadataTypes/definitions/Automation.definition'),
|
package/lib/MetadataTypeInfo.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Provides access to all metadataType classes
|
|
5
5
|
*/
|
|
6
6
|
const MetadataTypeInfo = {
|
|
7
|
+
accountUser: require('./metadataTypes/AccountUser'),
|
|
7
8
|
asset: require('./metadataTypes/Asset'),
|
|
8
9
|
attributeGroup: require('./metadataTypes/AttributeGroup'),
|
|
9
10
|
automation: require('./metadataTypes/Automation'),
|
package/lib/Retriever.js
CHANGED
|
@@ -32,7 +32,6 @@ class Retriever {
|
|
|
32
32
|
buObject.credential,
|
|
33
33
|
buObject.businessUnit,
|
|
34
34
|
]);
|
|
35
|
-
|
|
36
35
|
this.metadata = {};
|
|
37
36
|
}
|
|
38
37
|
|
|
@@ -41,9 +40,11 @@ class Retriever {
|
|
|
41
40
|
* @param {String[]} metadataTypes String list of metadata types to retrieve
|
|
42
41
|
* @param {String} [name] name of Metadata to retrieve (in case of templating)
|
|
43
42
|
* @param {Object} [templateVariables] Object of values which can be replaced (in case of templating)
|
|
44
|
-
* @
|
|
43
|
+
* @param {boolean} [changelogOnly] skip saving, only create json in memory
|
|
44
|
+
* @returns {Promise<Object<string,Object>>} Promise
|
|
45
45
|
*/
|
|
46
|
-
async retrieve(metadataTypes, name, templateVariables) {
|
|
46
|
+
async retrieve(metadataTypes, name, templateVariables, changelogOnly) {
|
|
47
|
+
const retrieveChangelog = {};
|
|
47
48
|
for (const metadataType of Util.getMetadataHierachy(metadataTypes)) {
|
|
48
49
|
let result;
|
|
49
50
|
const [type, subType] = metadataType.split('-');
|
|
@@ -53,7 +54,11 @@ class Retriever {
|
|
|
53
54
|
MetadataTypeInfo[type].properties = this.properties;
|
|
54
55
|
|
|
55
56
|
try {
|
|
56
|
-
if (!metadataTypes.includes(type)) {
|
|
57
|
+
if (!metadataTypes.includes(type) && !metadataTypes.includes(metadataType)) {
|
|
58
|
+
if (changelogOnly) {
|
|
59
|
+
// no extra caching needed for list view
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
57
62
|
Util.logger.info(`Caching dependent Metadata: ${metadataType}`);
|
|
58
63
|
await Util.retryOnError(
|
|
59
64
|
`Retrying to cache ${metadataType}`,
|
|
@@ -62,12 +67,8 @@ class Retriever {
|
|
|
62
67
|
this.buObject,
|
|
63
68
|
subType
|
|
64
69
|
);
|
|
65
|
-
if (type == 'list') {
|
|
66
|
-
Util.logger.debug('==list==');
|
|
67
|
-
Util.logger.debug(JSON.stringify(result));
|
|
68
|
-
}
|
|
69
70
|
},
|
|
70
|
-
|
|
71
|
+
false
|
|
71
72
|
);
|
|
72
73
|
} else if (templateVariables) {
|
|
73
74
|
Util.logger.info(`Retrieving as Template: ${metadataType}`);
|
|
@@ -98,14 +99,24 @@ class Retriever {
|
|
|
98
99
|
});
|
|
99
100
|
} else {
|
|
100
101
|
Util.logger.info('Retrieving: ' + metadataType);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
102
|
+
if (changelogOnly) {
|
|
103
|
+
await Util.retryOnError(`Retrying ${metadataType}`, async () => {
|
|
104
|
+
result = await MetadataTypeInfo[type].retrieveChangelog(
|
|
105
|
+
null,
|
|
106
|
+
this.buObject,
|
|
107
|
+
subType
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
} else {
|
|
111
|
+
await Util.retryOnError(`Retrying ${metadataType}`, async () => {
|
|
112
|
+
result = await MetadataTypeInfo[type].retrieve(
|
|
113
|
+
this.savePath,
|
|
114
|
+
null,
|
|
115
|
+
this.buObject,
|
|
116
|
+
subType
|
|
117
|
+
);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
109
120
|
}
|
|
110
121
|
if (result) {
|
|
111
122
|
if (templateVariables && Array.isArray(result)) {
|
|
@@ -113,6 +124,9 @@ class Retriever {
|
|
|
113
124
|
this.metadata[type] = result.map((element) => element.metadata);
|
|
114
125
|
} else {
|
|
115
126
|
this.metadata[type] = result.metadata;
|
|
127
|
+
if (metadataTypes.includes(type) || metadataTypes.includes(metadataType)) {
|
|
128
|
+
retrieveChangelog[type] = result.metadata;
|
|
129
|
+
}
|
|
116
130
|
}
|
|
117
131
|
}
|
|
118
132
|
} catch (ex) {
|
|
@@ -123,6 +137,7 @@ class Retriever {
|
|
|
123
137
|
}
|
|
124
138
|
}
|
|
125
139
|
}
|
|
140
|
+
return retrieveChangelog;
|
|
126
141
|
}
|
|
127
142
|
}
|
|
128
143
|
|
package/lib/cli.js
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* CLI entry for SFMC DevTools
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const Util = require('./util/util');
|
|
9
|
+
const yargs = require('yargs');
|
|
10
|
+
const Mcdev = require('./index');
|
|
11
|
+
|
|
12
|
+
yargs
|
|
13
|
+
.scriptName('mcdev')
|
|
14
|
+
.usage('$0 <command> [options]')
|
|
15
|
+
.command({
|
|
16
|
+
command: 'retrieve [BU] [TYPE]',
|
|
17
|
+
aliases: ['r'],
|
|
18
|
+
desc: 'retrieves metadata of a business unit',
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
builder: (yargs) => {
|
|
21
|
+
yargs
|
|
22
|
+
.positional('BU', {
|
|
23
|
+
type: 'string',
|
|
24
|
+
describe:
|
|
25
|
+
'the business unit to retrieve from (in format "credential name/BU name")',
|
|
26
|
+
})
|
|
27
|
+
.positional('TYPE', {
|
|
28
|
+
type: 'string',
|
|
29
|
+
describe: 'metadata type that shall be exclusively downloaded',
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
handler: (argv) => {
|
|
33
|
+
Mcdev._setLoggingLevel(argv);
|
|
34
|
+
Mcdev.retrieve(argv.BU, argv.TYPE);
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
.command({
|
|
38
|
+
command: 'deploy [BU] [TYPE]',
|
|
39
|
+
aliases: ['d'],
|
|
40
|
+
desc: 'deploys local metadata to a business unit',
|
|
41
|
+
builder: (yargs) => {
|
|
42
|
+
yargs
|
|
43
|
+
.positional('BU', {
|
|
44
|
+
type: 'string',
|
|
45
|
+
describe:
|
|
46
|
+
'the business unit to deploy to (in format "credential name/BU name")',
|
|
47
|
+
})
|
|
48
|
+
.positional('TYPE', {
|
|
49
|
+
type: 'string',
|
|
50
|
+
describe: 'metadata type that shall be exclusively uploaded',
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
handler: (argv) => {
|
|
54
|
+
Mcdev._setLoggingLevel(argv);
|
|
55
|
+
Mcdev.deploy(argv.BU, argv.TYPE);
|
|
56
|
+
},
|
|
57
|
+
})
|
|
58
|
+
.command({
|
|
59
|
+
command: 'init [credentialsName]',
|
|
60
|
+
desc: `creates '${Util.configFileName}' in your root or adds additional credentials to the existing one`,
|
|
61
|
+
builder: (yargs) => {
|
|
62
|
+
yargs.positional('credentialsName', {
|
|
63
|
+
type: 'string',
|
|
64
|
+
describe: 'name of your installed package',
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
handler: (argv) => {
|
|
68
|
+
Mcdev._setLoggingLevel(argv);
|
|
69
|
+
Mcdev.initProject(argv.credentialsName, argv.skipInteraction);
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
.command({
|
|
73
|
+
command: 'reloadBUs [credentialsName]',
|
|
74
|
+
aliases: ['rb'],
|
|
75
|
+
desc: 'loads the list of available BUs from the server and saves it to your config',
|
|
76
|
+
builder: (yargs) => {
|
|
77
|
+
yargs.positional('credentialsName', {
|
|
78
|
+
type: 'string',
|
|
79
|
+
describe: 'name of your installed package',
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
handler: (argv) => {
|
|
83
|
+
Mcdev._setLoggingLevel(argv);
|
|
84
|
+
Mcdev.findBUs(argv.credentialsName);
|
|
85
|
+
},
|
|
86
|
+
})
|
|
87
|
+
.command({
|
|
88
|
+
command: 'badKeys [BU]',
|
|
89
|
+
desc: 'lists metadata with random API names in specified Business Unit directory',
|
|
90
|
+
builder: (yargs) => {
|
|
91
|
+
yargs.positional('BU', {
|
|
92
|
+
type: 'string',
|
|
93
|
+
describe: 'the business unit to deploy to',
|
|
94
|
+
});
|
|
95
|
+
},
|
|
96
|
+
handler: (argv) => {
|
|
97
|
+
Mcdev._setLoggingLevel(argv);
|
|
98
|
+
Mcdev.badKeys(argv.BU);
|
|
99
|
+
},
|
|
100
|
+
})
|
|
101
|
+
.command({
|
|
102
|
+
command: 'document <BU> <TYPE>',
|
|
103
|
+
aliases: ['doc'],
|
|
104
|
+
desc: 'Creates Markdown or HTML documentation for the selected type',
|
|
105
|
+
builder: (yargs) => {
|
|
106
|
+
yargs
|
|
107
|
+
.positional('TYPE', {
|
|
108
|
+
type: 'string',
|
|
109
|
+
describe:
|
|
110
|
+
'metadata type to generate docs for; currently supported: dataExtension, role',
|
|
111
|
+
})
|
|
112
|
+
.positional('BU', {
|
|
113
|
+
type: 'string',
|
|
114
|
+
describe:
|
|
115
|
+
'the business unit to generate docs for (in format "credential name/BU name")',
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
handler: (argv) => {
|
|
119
|
+
Mcdev._setLoggingLevel(argv);
|
|
120
|
+
Mcdev.document(argv.BU, argv.TYPE);
|
|
121
|
+
},
|
|
122
|
+
})
|
|
123
|
+
.command({
|
|
124
|
+
command: 'delete <BU> <TYPE> <EXTERNALKEY>',
|
|
125
|
+
aliases: ['del'],
|
|
126
|
+
desc: 'deletes metadata of selected type and external key',
|
|
127
|
+
builder: (yargs) => {
|
|
128
|
+
yargs
|
|
129
|
+
.positional('BU', {
|
|
130
|
+
type: 'string',
|
|
131
|
+
describe:
|
|
132
|
+
'the business unit to delete from (in format "credential name/BU name")',
|
|
133
|
+
})
|
|
134
|
+
.positional('TYPE', {
|
|
135
|
+
type: 'string',
|
|
136
|
+
describe: 'metadata type to delete from; currently supported: dataExtension',
|
|
137
|
+
})
|
|
138
|
+
.positional('EXTERNALKEY', {
|
|
139
|
+
type: 'string',
|
|
140
|
+
describe: 'the key to delete',
|
|
141
|
+
});
|
|
142
|
+
},
|
|
143
|
+
handler: (argv) => {
|
|
144
|
+
Mcdev._setLoggingLevel(argv);
|
|
145
|
+
Mcdev.deleteByKey(argv.BU, argv.TYPE, argv.EXTERNALKEY);
|
|
146
|
+
},
|
|
147
|
+
})
|
|
148
|
+
.command({
|
|
149
|
+
command: 'retrieveAsTemplate <BU> <TYPE> <NAME> <MARKET>',
|
|
150
|
+
aliases: ['rt'],
|
|
151
|
+
desc: 'Retrieves a specific metadata file by name for templating',
|
|
152
|
+
builder: (yargs) => {
|
|
153
|
+
yargs
|
|
154
|
+
.positional('BU', {
|
|
155
|
+
type: 'string',
|
|
156
|
+
describe:
|
|
157
|
+
'the business unit to deploy to (in format "credential name/BU name")',
|
|
158
|
+
})
|
|
159
|
+
.positional('TYPE', {
|
|
160
|
+
type: 'string',
|
|
161
|
+
describe: 'metadata type',
|
|
162
|
+
})
|
|
163
|
+
.positional('NAME', {
|
|
164
|
+
type: 'string',
|
|
165
|
+
describe: 'name of the metadata component',
|
|
166
|
+
})
|
|
167
|
+
.positional('MARKET', {
|
|
168
|
+
type: 'string',
|
|
169
|
+
describe: 'market used for reverse building template',
|
|
170
|
+
});
|
|
171
|
+
},
|
|
172
|
+
handler: (argv) => {
|
|
173
|
+
Mcdev._setLoggingLevel(argv);
|
|
174
|
+
Mcdev.retrieveAsTemplate(argv.BU, argv.TYPE, argv.NAME, argv.MARKET);
|
|
175
|
+
},
|
|
176
|
+
})
|
|
177
|
+
.command({
|
|
178
|
+
command: 'buildDefinition <BU> <TYPE> <NAME> <MARKET>',
|
|
179
|
+
aliases: ['bd'],
|
|
180
|
+
desc: 'builds metadata definition based on template',
|
|
181
|
+
builder: (yargs) => {
|
|
182
|
+
yargs
|
|
183
|
+
.positional('BU', {
|
|
184
|
+
type: 'string',
|
|
185
|
+
describe: 'the business unit to deploy to',
|
|
186
|
+
})
|
|
187
|
+
.positional('TYPE', {
|
|
188
|
+
type: 'string',
|
|
189
|
+
describe: 'metadata type',
|
|
190
|
+
})
|
|
191
|
+
.positional('NAME', {
|
|
192
|
+
type: 'string',
|
|
193
|
+
describe: 'name of the metadata component',
|
|
194
|
+
})
|
|
195
|
+
.positional('MARKET', {
|
|
196
|
+
type: 'string',
|
|
197
|
+
describe: 'the business unit to deploy to',
|
|
198
|
+
});
|
|
199
|
+
},
|
|
200
|
+
handler: (argv) => {
|
|
201
|
+
Mcdev._setLoggingLevel(argv);
|
|
202
|
+
Mcdev.buildDefinition(argv.BU, argv.TYPE, argv.NAME, argv.MARKET);
|
|
203
|
+
},
|
|
204
|
+
})
|
|
205
|
+
.command({
|
|
206
|
+
command: 'buildDefinitionBulk <LISTNAME> <TYPE> <NAME>',
|
|
207
|
+
aliases: ['bdb'],
|
|
208
|
+
desc: 'builds metadata definition based on template en bulk',
|
|
209
|
+
builder: (yargs) => {
|
|
210
|
+
yargs
|
|
211
|
+
.positional('LISTNAME', {
|
|
212
|
+
type: 'string',
|
|
213
|
+
describe: 'name of list of BU-market combos',
|
|
214
|
+
})
|
|
215
|
+
.positional('TYPE', {
|
|
216
|
+
type: 'string',
|
|
217
|
+
describe: 'metadata type',
|
|
218
|
+
})
|
|
219
|
+
.positional('NAME', {
|
|
220
|
+
type: 'string',
|
|
221
|
+
describe: 'name of the metadata component',
|
|
222
|
+
});
|
|
223
|
+
},
|
|
224
|
+
handler: (argv) => {
|
|
225
|
+
Mcdev._setLoggingLevel(argv);
|
|
226
|
+
Mcdev.buildDefinitionBulk(argv.LISTNAME, argv.TYPE, argv.NAME);
|
|
227
|
+
},
|
|
228
|
+
})
|
|
229
|
+
.command({
|
|
230
|
+
command: 'selectTypes',
|
|
231
|
+
aliases: ['st'],
|
|
232
|
+
desc: 'lets you choose what metadata types to retrieve',
|
|
233
|
+
handler: (argv) => {
|
|
234
|
+
Mcdev._setLoggingLevel(argv);
|
|
235
|
+
Mcdev.selectTypes();
|
|
236
|
+
},
|
|
237
|
+
})
|
|
238
|
+
.command({
|
|
239
|
+
command: 'explainTypes',
|
|
240
|
+
aliases: ['et'],
|
|
241
|
+
desc: 'explains metadata types that can be retrieved',
|
|
242
|
+
handler: (argv) => {
|
|
243
|
+
Mcdev._setLoggingLevel(argv);
|
|
244
|
+
Mcdev.explainTypes();
|
|
245
|
+
},
|
|
246
|
+
})
|
|
247
|
+
.command({
|
|
248
|
+
command: 'createDeltaPkg [range] [filter]',
|
|
249
|
+
aliases: ['cdp'],
|
|
250
|
+
desc: 'Copies commit-based file delta into deploy folder',
|
|
251
|
+
builder: (yargs) => {
|
|
252
|
+
yargs
|
|
253
|
+
.positional('range', {
|
|
254
|
+
type: 'string',
|
|
255
|
+
describe: 'Pull Request target branch or git commit range',
|
|
256
|
+
})
|
|
257
|
+
.positional('filter', {
|
|
258
|
+
type: 'string',
|
|
259
|
+
describe:
|
|
260
|
+
'Disable templating & instead filter by the specified file path (comma separated)',
|
|
261
|
+
});
|
|
262
|
+
},
|
|
263
|
+
handler: Mcdev.createDeltaPkg,
|
|
264
|
+
})
|
|
265
|
+
.command({
|
|
266
|
+
command: 'upgrade',
|
|
267
|
+
aliases: ['up'],
|
|
268
|
+
desc: 'Add NPM dependencies and IDE configuration files to your project',
|
|
269
|
+
handler: (argv) => {
|
|
270
|
+
Mcdev._setLoggingLevel(argv);
|
|
271
|
+
Mcdev.upgrade(argv.skipInteraction);
|
|
272
|
+
},
|
|
273
|
+
})
|
|
274
|
+
.option('verbose', {
|
|
275
|
+
type: 'boolean',
|
|
276
|
+
description: 'Run with verbose CLI output',
|
|
277
|
+
})
|
|
278
|
+
.option('debug', {
|
|
279
|
+
type: 'boolean',
|
|
280
|
+
description: 'Enable developer & edge-case features',
|
|
281
|
+
})
|
|
282
|
+
.option('silent', {
|
|
283
|
+
type: 'boolean',
|
|
284
|
+
description: 'Only output errors to CLI',
|
|
285
|
+
})
|
|
286
|
+
.option('skipInteraction', {
|
|
287
|
+
alias: ['yes', 'y'],
|
|
288
|
+
description: 'Interactive questions where possible and go with defaults instead',
|
|
289
|
+
})
|
|
290
|
+
.demandCommand(1, 'Please enter a valid command')
|
|
291
|
+
.strict()
|
|
292
|
+
.recommendCommands()
|
|
293
|
+
.wrap(yargs.terminalWidth())
|
|
294
|
+
.epilog('Copyright 2021. Accenture.')
|
|
295
|
+
.help().argv;
|