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.
Files changed (134) hide show
  1. package/.eslintrc.json +67 -7
  2. package/.github/ISSUE_TEMPLATE/bug.yml +2 -1
  3. package/.github/PULL_REQUEST_TEMPLATE.md +5 -3
  4. package/.github/dependabot.yml +14 -0
  5. package/.github/workflows/code-analysis.yml +57 -0
  6. package/.husky/commit-msg +10 -0
  7. package/.husky/post-checkout +5 -0
  8. package/.husky/pre-commit +2 -1
  9. package/.prettierrc +8 -0
  10. package/.vscode/settings.json +1 -1
  11. package/LICENSE +2 -2
  12. package/README.md +134 -45
  13. package/boilerplate/config.json +5 -11
  14. package/boilerplate/files/.prettierrc +8 -0
  15. package/boilerplate/files/.vscode/extensions.json +0 -1
  16. package/boilerplate/files/.vscode/settings.json +30 -2
  17. package/boilerplate/files/README.md +2 -2
  18. package/boilerplate/forcedUpdates.json +10 -0
  19. package/boilerplate/npm-dependencies.json +5 -5
  20. package/docs/dist/documentation.md +2807 -1730
  21. package/jsconfig.json +1 -1
  22. package/lib/Builder.js +171 -74
  23. package/lib/Deployer.js +244 -96
  24. package/lib/MetadataTypeDefinitions.js +2 -0
  25. package/lib/MetadataTypeInfo.js +2 -0
  26. package/lib/Retriever.js +61 -84
  27. package/lib/cli.js +116 -11
  28. package/lib/index.js +241 -561
  29. package/lib/metadataTypes/AccountUser.js +117 -103
  30. package/lib/metadataTypes/Asset.js +705 -255
  31. package/lib/metadataTypes/AttributeGroup.js +23 -12
  32. package/lib/metadataTypes/Automation.js +489 -392
  33. package/lib/metadataTypes/Campaign.js +33 -93
  34. package/lib/metadataTypes/ContentArea.js +31 -11
  35. package/lib/metadataTypes/DataExtension.js +387 -372
  36. package/lib/metadataTypes/DataExtensionField.js +131 -54
  37. package/lib/metadataTypes/DataExtensionTemplate.js +22 -4
  38. package/lib/metadataTypes/DataExtract.js +61 -48
  39. package/lib/metadataTypes/DataExtractType.js +14 -8
  40. package/lib/metadataTypes/Discovery.js +21 -16
  41. package/lib/metadataTypes/Email.js +32 -12
  42. package/lib/metadataTypes/EmailSendDefinition.js +85 -80
  43. package/lib/metadataTypes/EventDefinition.js +61 -43
  44. package/lib/metadataTypes/FileTransfer.js +72 -52
  45. package/lib/metadataTypes/Filter.js +11 -4
  46. package/lib/metadataTypes/Folder.js +149 -117
  47. package/lib/metadataTypes/FtpLocation.js +14 -8
  48. package/lib/metadataTypes/ImportFile.js +61 -64
  49. package/lib/metadataTypes/Interaction.js +19 -4
  50. package/lib/metadataTypes/List.js +54 -13
  51. package/lib/metadataTypes/MetadataType.js +664 -454
  52. package/lib/metadataTypes/MobileCode.js +46 -0
  53. package/lib/metadataTypes/MobileKeyword.js +114 -0
  54. package/lib/metadataTypes/Query.js +206 -105
  55. package/lib/metadataTypes/Role.js +76 -61
  56. package/lib/metadataTypes/Script.js +147 -83
  57. package/lib/metadataTypes/SetDefinition.js +20 -8
  58. package/lib/metadataTypes/TriggeredSendDefinition.js +78 -58
  59. package/lib/metadataTypes/definitions/Asset.definition.js +21 -10
  60. package/lib/metadataTypes/definitions/AttributeGroup.definition.js +12 -0
  61. package/lib/metadataTypes/definitions/Automation.definition.js +10 -5
  62. package/lib/metadataTypes/definitions/Campaign.definition.js +44 -1
  63. package/lib/metadataTypes/definitions/DataExtension.definition.js +4 -0
  64. package/lib/metadataTypes/definitions/DataExtensionTemplate.definition.js +6 -0
  65. package/lib/metadataTypes/definitions/DataExtract.definition.js +18 -14
  66. package/lib/metadataTypes/definitions/Discovery.definition.js +12 -0
  67. package/lib/metadataTypes/definitions/EmailSendDefinition.definition.js +4 -0
  68. package/lib/metadataTypes/definitions/EventDefinition.definition.js +22 -0
  69. package/lib/metadataTypes/definitions/FileTransfer.definition.js +4 -0
  70. package/lib/metadataTypes/definitions/Filter.definition.js +4 -0
  71. package/lib/metadataTypes/definitions/Folder.definition.js +6 -0
  72. package/lib/metadataTypes/definitions/FtpLocation.definition.js +4 -0
  73. package/lib/metadataTypes/definitions/ImportFile.definition.js +10 -5
  74. package/lib/metadataTypes/definitions/Interaction.definition.js +4 -0
  75. package/lib/metadataTypes/definitions/MobileCode.definition.js +163 -0
  76. package/lib/metadataTypes/definitions/MobileKeyword.definition.js +253 -0
  77. package/lib/metadataTypes/definitions/Query.definition.js +4 -0
  78. package/lib/metadataTypes/definitions/Role.definition.js +5 -0
  79. package/lib/metadataTypes/definitions/Script.definition.js +4 -0
  80. package/lib/metadataTypes/definitions/SetDefinition.definition.js +28 -0
  81. package/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js +4 -0
  82. package/lib/retrieveChangelog.js +7 -6
  83. package/lib/util/auth.js +117 -0
  84. package/lib/util/businessUnit.js +55 -66
  85. package/lib/util/cache.js +194 -0
  86. package/lib/util/cli.js +90 -116
  87. package/lib/util/config.js +302 -0
  88. package/lib/util/devops.js +250 -50
  89. package/lib/util/file.js +141 -201
  90. package/lib/util/init.config.js +208 -75
  91. package/lib/util/init.git.js +45 -50
  92. package/lib/util/init.js +72 -59
  93. package/lib/util/init.npm.js +48 -39
  94. package/lib/util/util.js +280 -564
  95. package/package.json +45 -34
  96. package/test/dataExtension.test.js +152 -0
  97. package/test/mockRoot/.mcdev-auth.json +8 -0
  98. package/test/mockRoot/.mcdevrc.json +67 -0
  99. package/test/mockRoot/deploy/testInstance/testBU/dataExtension/childBU_dataextension_test.dataExtension-meta.json +39 -0
  100. package/test/mockRoot/deploy/testInstance/testBU/dataExtension/testDataExtension.dataExtension-meta.json +23 -0
  101. package/test/mockRoot/deploy/testInstance/testBU/query/testExistingQuery.query-meta.json +11 -0
  102. package/test/mockRoot/deploy/testInstance/testBU/query/testExistingQuery.query-meta.sql +4 -0
  103. package/test/mockRoot/deploy/testInstance/testBU/query/testQuery.query-meta.json +11 -0
  104. package/test/mockRoot/deploy/testInstance/testBU/query/testQuery.query-meta.sql +4 -0
  105. package/test/query.test.js +149 -0
  106. package/test/resourceFactory.js +142 -0
  107. package/test/resources/1111111/dataFolder/retrieve-response.xml +43 -0
  108. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/patch-response.json +18 -0
  109. package/test/resources/9999999/automation/v1/queries/get-response.json +24 -0
  110. package/test/resources/9999999/automation/v1/queries/post-response.json +18 -0
  111. package/test/resources/9999999/dataExtension/build-expected.json +51 -0
  112. package/test/resources/9999999/dataExtension/create-expected.json +23 -0
  113. package/test/resources/9999999/dataExtension/create-response.xml +54 -0
  114. package/test/resources/9999999/dataExtension/retrieve-expected.json +51 -0
  115. package/test/resources/9999999/dataExtension/retrieve-response.xml +47 -0
  116. package/test/resources/9999999/dataExtension/template-expected.json +51 -0
  117. package/test/resources/9999999/dataExtension/update-expected.json +55 -0
  118. package/test/resources/9999999/dataExtension/update-response.xml +52 -0
  119. package/test/resources/9999999/dataExtensionField/retrieve-response.xml +93 -0
  120. package/test/resources/9999999/dataExtensionTemplate/retrieve-response.xml +303 -0
  121. package/test/resources/9999999/dataFolder/retrieve-response.xml +65 -0
  122. package/test/resources/9999999/query/build-expected.json +8 -0
  123. package/test/resources/9999999/query/get-expected.json +11 -0
  124. package/test/resources/9999999/query/patch-expected.json +11 -0
  125. package/test/resources/9999999/query/post-expected.json +11 -0
  126. package/test/resources/9999999/query/template-expected.json +8 -0
  127. package/test/resources/auth.json +32 -0
  128. package/test/resources/rest404-response.json +5 -0
  129. package/test/resources/retrieve-response.xml +21 -0
  130. package/test/utils.js +107 -0
  131. package/types/mcdev.d.js +301 -0
  132. package/CHANGELOG.md +0 -126
  133. package/PULL_REQUEST_TEMPLATE.md +0 -19
  134. package/test/util/file.js +0 -51
package/lib/Retriever.js CHANGED
@@ -1,8 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ const TYPE = require('../types/mcdev.d');
3
4
  const MetadataTypeInfo = require('./MetadataTypeInfo');
4
5
  const Util = require('./util/util');
5
6
  const File = require('./util/file');
7
+ const cache = require('./util/cache');
8
+ const auth = require('./util/auth');
6
9
  /**
7
10
  * Retrieves metadata from a business unit and saves it to the local filesystem.
8
11
  */
@@ -10,20 +13,11 @@ class Retriever {
10
13
  /**
11
14
  * Creates a Retriever, uses v2 auth if v2AuthOptions are passed.
12
15
  *
13
- * @param {Object} properties General configuration to be used in retrieve
14
- * @param {Object} properties.directories Directories to be used when interacting with FS
15
- * @param {Object} buObject properties for auth
16
- * @param {String} buObject.clientId clientId for FuelSDK auth
17
- * @param {String} buObject.clientSecret clientSecret for FuelSDK auth
18
- * @param {Object} buObject.credential clientId for FuelSDK auth
19
- * @param {String} buObject.tenant v2 Auth Tenant Information
20
- * @param {String} [buObject.mid] ID of Business Unit to authenticate with
21
- * @param {String} [buObject.businessUnit] name of Business Unit to authenticate with
22
- * @param {Util.ET_Client} client fuel client
16
+ * @param {TYPE.Mcdevrc} properties General configuration to be used in retrieve
17
+ * @param {TYPE.BuObject} buObject properties for auth
23
18
  */
24
- constructor(properties, buObject, client) {
19
+ constructor(properties, buObject) {
25
20
  this.buObject = buObject;
26
- this.client = client;
27
21
  this.properties = properties;
28
22
  this.retrieveDir = properties.directories.retrieve;
29
23
  this.templateDir = properties.directories.template;
@@ -32,109 +26,92 @@ class Retriever {
32
26
  buObject.credential,
33
27
  buObject.businessUnit,
34
28
  ]);
35
- this.metadata = {};
36
29
  }
37
30
 
38
31
  /**
39
32
  * Retrieve metadata of specified types into local file system and Retriever.metadata
40
- * @param {String[]} metadataTypes String list of metadata types to retrieve
41
- * @param {String} [name] name of Metadata to retrieve (in case of templating)
42
- * @param {Object} [templateVariables] Object of values which can be replaced (in case of templating)
33
+ *
34
+ * @param {string[]} metadataTypes String list of metadata types to retrieve
35
+ * @param {string[]} [namesOrKeys] name of Metadata to retrieveAsTemplate or list of keys for normal retrieval
36
+ * @param {TYPE.TemplateMap} [templateVariables] Object of values which can be replaced (in case of templating)
43
37
  * @param {boolean} [changelogOnly] skip saving, only create json in memory
44
- * @returns {Promise<Object<string,Object>>} Promise
38
+ * @returns {Promise.<TYPE.MultiMetadataTypeList>} Promise of a list of retrieved items grouped by type {automation:[...], query:[...]}
45
39
  */
46
- async retrieve(metadataTypes, name, templateVariables, changelogOnly) {
40
+ async retrieve(metadataTypes, namesOrKeys, templateVariables, changelogOnly) {
41
+ /**
42
+ * @type {TYPE.MultiMetadataTypeList}
43
+ */
47
44
  const retrieveChangelog = {};
45
+ if (!namesOrKeys || !namesOrKeys.length) {
46
+ // make iterating over namesOrKeys easier
47
+ namesOrKeys = [null];
48
+ }
48
49
  for (const metadataType of Util.getMetadataHierachy(metadataTypes)) {
49
- let result;
50
50
  const [type, subType] = metadataType.split('-');
51
- // add metadata & client to metadata process class instead of passing cache/mapping every time
52
- MetadataTypeInfo[type].cache = this.metadata;
53
- MetadataTypeInfo[type].client = this.client;
51
+ // add client to metadata process class instead of passing every time
52
+ MetadataTypeInfo[type].client = auth.getSDK(this.buObject);
54
53
  MetadataTypeInfo[type].properties = this.properties;
55
-
54
+ MetadataTypeInfo[type].buObject = this.buObject;
56
55
  try {
56
+ let result;
57
57
  if (!metadataTypes.includes(type) && !metadataTypes.includes(metadataType)) {
58
58
  if (changelogOnly) {
59
59
  // no extra caching needed for list view
60
60
  continue;
61
61
  }
62
62
  Util.logger.info(`Caching dependent Metadata: ${metadataType}`);
63
- await Util.retryOnError(
64
- `Retrying to cache ${metadataType}`,
65
- async () => {
66
- result = await MetadataTypeInfo[type].retrieveForCache(
67
- this.buObject,
68
- subType
69
- );
70
- },
71
- false
72
- );
63
+ result = await MetadataTypeInfo[type].retrieveForCache(this.buObject, subType);
73
64
  } else if (templateVariables) {
74
65
  Util.logger.info(`Retrieving as Template: ${metadataType}`);
75
- let nameArr;
76
- if (name.includes(',')) {
77
- nameArr = name.split(',').map((item) =>
78
- // allow whitespace in comma-separated lists
79
- item.trim()
80
- );
81
- } else {
82
- nameArr = [name.trim()];
83
- }
84
- await Util.retryOnError(`Retrying ${metadataType}`, async () => {
85
- result = await Promise.all(
86
- nameArr.map((name) => {
87
- // with npx and powershell spaces are not parsed correctly as part of a string
88
- // we hence require users to put %20 in their stead and have to convert that back
89
- name = name.split('%20').join(' ');
90
66
 
91
- return MetadataTypeInfo[type].retrieveAsTemplate(
92
- this.templateDir,
93
- name,
94
- templateVariables,
95
- subType
96
- );
97
- })
98
- );
99
- });
67
+ result = await Promise.all(
68
+ namesOrKeys.map((name) =>
69
+ MetadataTypeInfo[type].retrieveAsTemplate(
70
+ this.templateDir,
71
+ name,
72
+ templateVariables,
73
+ subType
74
+ )
75
+ )
76
+ );
100
77
  } else {
101
78
  Util.logger.info('Retrieving: ' + metadataType);
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
- }
79
+ result = await (changelogOnly
80
+ ? MetadataTypeInfo[type].retrieveChangelog(this.buObject, null, subType)
81
+ : Promise.all(
82
+ namesOrKeys.map((key) =>
83
+ MetadataTypeInfo[type].retrieve(
84
+ this.savePath,
85
+ null,
86
+ this.buObject,
87
+ subType,
88
+ key
89
+ )
90
+ )
91
+ ));
120
92
  }
121
93
  if (result) {
122
- if (templateVariables && Array.isArray(result)) {
123
- // so far we are only doing this for templates, hence the above if-check
124
- this.metadata[type] = result.map((element) => element.metadata);
94
+ if (Array.isArray(result)) {
95
+ cache.setMetadata(
96
+ type,
97
+ result.filter((el) => !!el).map((element) => element.metadata)[0]
98
+ );
99
+ if (metadataTypes.includes(type) || metadataTypes.includes(metadataType)) {
100
+ retrieveChangelog[type] = result
101
+ .filter((el) => !!el)
102
+ .map((element) => element.metadata);
103
+ }
125
104
  } else {
126
- this.metadata[type] = result.metadata;
105
+ cache.setMetadata(type, result.metadata);
127
106
  if (metadataTypes.includes(type) || metadataTypes.includes(metadataType)) {
128
107
  retrieveChangelog[type] = result.metadata;
129
108
  }
130
109
  }
131
110
  }
132
111
  } catch (ex) {
133
- Util.logger.error(`Retriever.retrieve:: Retrieving ${metadataType} failed`);
134
- Util.logger.debug(ex.stack);
135
- if (Util.logger.level === 'debug') {
136
- console.log(ex.stack);
137
- }
112
+ Util.logger.errorStack(ex, `Retrieving ${metadataType} failed`);
113
+ // do not continue retrieving if one type failed. simply skip processing the rest of the for-loop
114
+ break;
138
115
  }
139
116
  }
140
117
  return retrieveChangelog;
package/lib/cli.js CHANGED
@@ -13,7 +13,7 @@ yargs
13
13
  .scriptName('mcdev')
14
14
  .usage('$0 <command> [options]')
15
15
  .command({
16
- command: 'retrieve [BU] [TYPE]',
16
+ command: 'retrieve [BU] [TYPE] [KEY]',
17
17
  aliases: ['r'],
18
18
  desc: 'retrieves metadata of a business unit',
19
19
  // @ts-ignore
@@ -27,15 +27,20 @@ yargs
27
27
  .positional('TYPE', {
28
28
  type: 'string',
29
29
  describe: 'metadata type that shall be exclusively downloaded',
30
+ })
31
+ .positional('KEY', {
32
+ type: 'string',
33
+ describe: 'metadata keys that shall be exclusively downloaded',
30
34
  });
31
35
  },
32
36
  handler: (argv) => {
37
+ Mcdev.setSkipInteraction(argv.skipInteraction);
33
38
  Mcdev.setLoggingLevel(argv);
34
- Mcdev.retrieve(argv.BU, argv.TYPE);
39
+ Mcdev.retrieve(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY));
35
40
  },
36
41
  })
37
42
  .command({
38
- command: 'deploy [BU] [TYPE]',
43
+ command: 'deploy [BU] [TYPE] [KEY] [fromRetrieve]',
39
44
  aliases: ['d'],
40
45
  desc: 'deploys local metadata to a business unit',
41
46
  builder: (yargs) => {
@@ -48,11 +53,20 @@ yargs
48
53
  .positional('TYPE', {
49
54
  type: 'string',
50
55
  describe: 'metadata type that shall be exclusively uploaded',
56
+ })
57
+ .positional('KEY', {
58
+ type: 'string',
59
+ describe: 'metadata key that shall be exclusively uploaded',
60
+ })
61
+ .positional('fromRetrieve', {
62
+ type: 'string',
63
+ describe: 'optionally deploy from retrieve folder',
51
64
  });
52
65
  },
53
66
  handler: (argv) => {
67
+ Mcdev.setSkipInteraction(argv.skipInteraction);
54
68
  Mcdev.setLoggingLevel(argv);
55
- Mcdev.deploy(argv.BU, argv.TYPE);
69
+ Mcdev.deploy(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY), argv.fromRetrieve);
56
70
  },
57
71
  })
58
72
  .command({
@@ -65,6 +79,7 @@ yargs
65
79
  });
66
80
  },
67
81
  handler: (argv) => {
82
+ Mcdev.setSkipInteraction(argv.skipInteraction);
68
83
  Mcdev.setLoggingLevel(argv);
69
84
  Mcdev.initProject(argv.credentialsName, argv.skipInteraction);
70
85
  },
@@ -80,6 +95,7 @@ yargs
80
95
  });
81
96
  },
82
97
  handler: (argv) => {
98
+ Mcdev.setSkipInteraction(argv.skipInteraction);
83
99
  Mcdev.setLoggingLevel(argv);
84
100
  Mcdev.findBUs(argv.credentialsName);
85
101
  },
@@ -94,6 +110,7 @@ yargs
94
110
  });
95
111
  },
96
112
  handler: (argv) => {
113
+ Mcdev.setSkipInteraction(argv.skipInteraction);
97
114
  Mcdev.setLoggingLevel(argv);
98
115
  Mcdev.badKeys(argv.BU);
99
116
  },
@@ -104,18 +121,19 @@ yargs
104
121
  desc: 'Creates Markdown or HTML documentation for the selected type',
105
122
  builder: (yargs) => {
106
123
  yargs
107
- .positional('TYPE', {
124
+ .positional('BU', {
108
125
  type: 'string',
109
126
  describe:
110
- 'metadata type to generate docs for; currently supported: dataExtension, role',
127
+ 'the business unit to generate docs for (in format "credential name/BU name")',
111
128
  })
112
- .positional('BU', {
129
+ .positional('TYPE', {
113
130
  type: 'string',
114
131
  describe:
115
- 'the business unit to generate docs for (in format "credential name/BU name")',
132
+ 'metadata type to generate docs for; currently supported: dataExtension, role',
116
133
  });
117
134
  },
118
135
  handler: (argv) => {
136
+ Mcdev.setSkipInteraction(argv.skipInteraction);
119
137
  Mcdev.setLoggingLevel(argv);
120
138
  Mcdev.document(argv.BU, argv.TYPE);
121
139
  },
@@ -141,6 +159,7 @@ yargs
141
159
  });
142
160
  },
143
161
  handler: (argv) => {
162
+ Mcdev.setSkipInteraction(argv.skipInteraction);
144
163
  Mcdev.setLoggingLevel(argv);
145
164
  Mcdev.deleteByKey(argv.BU, argv.TYPE, argv.EXTERNALKEY);
146
165
  },
@@ -148,7 +167,7 @@ yargs
148
167
  .command({
149
168
  command: 'retrieveAsTemplate <BU> <TYPE> <NAME> <MARKET>',
150
169
  aliases: ['rt'],
151
- desc: 'Retrieves a specific metadata file by name for templating',
170
+ desc: 'Retrieves a specific metadata file by name from the server for templating',
152
171
  builder: (yargs) => {
153
172
  yargs
154
173
  .positional('BU', {
@@ -170,8 +189,41 @@ yargs
170
189
  });
171
190
  },
172
191
  handler: (argv) => {
192
+ Mcdev.setSkipInteraction(argv.skipInteraction);
173
193
  Mcdev.setLoggingLevel(argv);
174
- Mcdev.retrieveAsTemplate(argv.BU, argv.TYPE, argv.NAME, argv.MARKET);
194
+ Mcdev.retrieveAsTemplate(argv.BU, argv.TYPE, csvToArray(argv.NAME), argv.MARKET);
195
+ },
196
+ })
197
+ .command({
198
+ command: 'buildTemplate <BU> <TYPE> <KEY> <MARKET>',
199
+ aliases: ['bt'],
200
+ desc: 'builds a template out of a specific metadata file already in your retrieve folder',
201
+ builder: (yargs) => {
202
+ yargs
203
+ .positional('BU', {
204
+ type: 'string',
205
+ describe:
206
+ 'the business unit to deploy to (in format "credential name/BU name")',
207
+ })
208
+ .positional('TYPE', {
209
+ type: 'string',
210
+ describe: 'metadata type',
211
+ })
212
+ .positional('KEY', {
213
+ type: 'string',
214
+ describe: 'key(s) of the metadata component(s)',
215
+ })
216
+ .positional('MARKET', {
217
+ type: 'string',
218
+ describe: 'market used for reverse building template',
219
+ });
220
+ },
221
+ handler: (argv) => {
222
+ Mcdev.setSkipInteraction(argv.skipInteraction);
223
+ Mcdev.setLoggingLevel(argv);
224
+ const keyArr = csvToArray(argv.KEY);
225
+
226
+ Mcdev.buildTemplate(argv.BU, argv.TYPE, keyArr, argv.MARKET);
175
227
  },
176
228
  })
177
229
  .command({
@@ -198,6 +250,7 @@ yargs
198
250
  });
199
251
  },
200
252
  handler: (argv) => {
253
+ Mcdev.setSkipInteraction(argv.skipInteraction);
201
254
  Mcdev.setLoggingLevel(argv);
202
255
  Mcdev.buildDefinition(argv.BU, argv.TYPE, argv.NAME, argv.MARKET);
203
256
  },
@@ -222,6 +275,7 @@ yargs
222
275
  });
223
276
  },
224
277
  handler: (argv) => {
278
+ Mcdev.setSkipInteraction(argv.skipInteraction);
225
279
  Mcdev.setLoggingLevel(argv);
226
280
  Mcdev.buildDefinitionBulk(argv.LISTNAME, argv.TYPE, argv.NAME);
227
281
  },
@@ -231,6 +285,7 @@ yargs
231
285
  aliases: ['st'],
232
286
  desc: 'lets you choose what metadata types to retrieve',
233
287
  handler: (argv) => {
288
+ Mcdev.setSkipInteraction(argv.skipInteraction);
234
289
  Mcdev.setLoggingLevel(argv);
235
290
  Mcdev.selectTypes();
236
291
  },
@@ -240,6 +295,7 @@ yargs
240
295
  aliases: ['et'],
241
296
  desc: 'explains metadata types that can be retrieved',
242
297
  handler: (argv) => {
298
+ Mcdev.setSkipInteraction(argv.skipInteraction);
243
299
  Mcdev.setLoggingLevel(argv);
244
300
  Mcdev.explainTypes();
245
301
  },
@@ -261,15 +317,45 @@ yargs
261
317
  });
262
318
  },
263
319
  handler: (argv) => {
320
+ Mcdev.setSkipInteraction(argv.skipInteraction);
264
321
  Mcdev.setLoggingLevel(argv);
265
322
  Mcdev.createDeltaPkg(argv);
266
323
  },
267
324
  })
325
+ .command({
326
+ command: 'getFilesToCommit <BU> <TYPE> <KEY>',
327
+ aliases: ['fc'],
328
+ desc: 'returns a list of relative paths to files one needs to include in a commit',
329
+ builder: (yargs) => {
330
+ yargs
331
+ .positional('BU', {
332
+ type: 'string',
333
+ describe:
334
+ 'the business unit to deploy to (in format "credential name/BU name")',
335
+ })
336
+ .positional('TYPE', {
337
+ type: 'string',
338
+ describe: 'metadata type',
339
+ })
340
+ .positional('KEY', {
341
+ type: 'string',
342
+ describe: 'key(s) of the metadata component(s)',
343
+ });
344
+ },
345
+ handler: (argv) => {
346
+ Mcdev.setSkipInteraction(argv.skipInteraction);
347
+ Mcdev.setLoggingLevel(argv);
348
+ const keyArr = csvToArray(argv.KEY);
349
+
350
+ Mcdev.getFilesToCommit(argv.BU, argv.TYPE, keyArr);
351
+ },
352
+ })
268
353
  .command({
269
354
  command: 'upgrade',
270
355
  aliases: ['up'],
271
356
  desc: 'Add NPM dependencies and IDE configuration files to your project',
272
357
  handler: (argv) => {
358
+ Mcdev.setSkipInteraction(argv.skipInteraction);
273
359
  Mcdev.setLoggingLevel(argv);
274
360
  Mcdev.upgrade(argv.skipInteraction);
275
361
  },
@@ -294,5 +380,24 @@ yargs
294
380
  .strict()
295
381
  .recommendCommands()
296
382
  .wrap(yargs.terminalWidth())
297
- .epilog('Copyright 2021. Accenture.')
383
+ .epilog(
384
+ 'Copyright 2022. Accenture. Get support at https://github.com/Accenture/sfmc-devtools/issues'
385
+ )
298
386
  .help().argv;
387
+
388
+ /**
389
+ * helper to convert CSVs into an array. if only one value was given, it's also returned as an array
390
+ *
391
+ * @param {string} csv potentially comma-separated value or null
392
+ * @returns {string[]} values split into an array.
393
+ */
394
+ function csvToArray(csv) {
395
+ return !csv
396
+ ? null
397
+ : csv.includes(',')
398
+ ? csv.split(',').map((item) =>
399
+ // allow whitespace in comma-separated lists
400
+ item.trim()
401
+ )
402
+ : [csv.trim()];
403
+ }