mcdev 4.2.1 → 4.3.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.
Files changed (95) hide show
  1. package/.github/ISSUE_TEMPLATE/bug.yml +2 -0
  2. package/.github/PULL_REQUEST_TEMPLATE.md +1 -2
  3. package/.github/pr-labeler.yml +3 -0
  4. package/.github/workflows/close_issues_on_merge.yml +18 -0
  5. package/.github/workflows/pr-labeler.yml +19 -0
  6. package/LICENSE +1 -1
  7. package/README.md +1 -1
  8. package/docs/dist/documentation.md +700 -281
  9. package/lib/Deployer.js +21 -15
  10. package/lib/Retriever.js +23 -19
  11. package/lib/cli.js +36 -6
  12. package/lib/index.js +56 -10
  13. package/lib/metadataTypes/AccountUser.js +17 -23
  14. package/lib/metadataTypes/Asset.js +28 -21
  15. package/lib/metadataTypes/AttributeGroup.js +1 -2
  16. package/lib/metadataTypes/Automation.js +75 -37
  17. package/lib/metadataTypes/Campaign.js +4 -3
  18. package/lib/metadataTypes/ContentArea.js +2 -3
  19. package/lib/metadataTypes/DataExtension.js +56 -47
  20. package/lib/metadataTypes/DataExtensionField.js +9 -12
  21. package/lib/metadataTypes/DataExtensionTemplate.js +2 -3
  22. package/lib/metadataTypes/DataExtract.js +1 -2
  23. package/lib/metadataTypes/DataExtractType.js +1 -2
  24. package/lib/metadataTypes/Discovery.js +3 -4
  25. package/lib/metadataTypes/Email.js +20 -6
  26. package/lib/metadataTypes/EmailSendDefinition.js +5 -8
  27. package/lib/metadataTypes/EventDefinition.js +29 -2
  28. package/lib/metadataTypes/FileTransfer.js +1 -2
  29. package/lib/metadataTypes/Filter.js +1 -2
  30. package/lib/metadataTypes/Folder.js +12 -14
  31. package/lib/metadataTypes/FtpLocation.js +1 -2
  32. package/lib/metadataTypes/ImportFile.js +1 -2
  33. package/lib/metadataTypes/Interaction.js +678 -12
  34. package/lib/metadataTypes/List.js +36 -33
  35. package/lib/metadataTypes/MetadataType.js +170 -124
  36. package/lib/metadataTypes/MobileCode.js +1 -2
  37. package/lib/metadataTypes/MobileKeyword.js +1 -2
  38. package/lib/metadataTypes/Query.js +15 -6
  39. package/lib/metadataTypes/Role.js +10 -11
  40. package/lib/metadataTypes/Script.js +2 -5
  41. package/lib/metadataTypes/SetDefinition.js +1 -2
  42. package/lib/metadataTypes/TransactionalMessage.js +25 -32
  43. package/lib/metadataTypes/TransactionalSMS.js +3 -4
  44. package/lib/metadataTypes/TriggeredSendDefinition.js +232 -56
  45. package/lib/metadataTypes/definitions/Asset.definition.js +1 -1
  46. package/lib/metadataTypes/definitions/Automation.definition.js +1 -1
  47. package/lib/metadataTypes/definitions/DataExtension.definition.js +10 -1
  48. package/lib/metadataTypes/definitions/Email.definition.js +1 -1
  49. package/lib/metadataTypes/definitions/EmailSendDefinition.definition.js +1 -1
  50. package/lib/metadataTypes/definitions/EventDefinition.definition.js +40 -1
  51. package/lib/metadataTypes/definitions/Folder.definition.js +31 -0
  52. package/lib/metadataTypes/definitions/ImportFile.definition.js +1 -1
  53. package/lib/metadataTypes/definitions/Interaction.definition.js +47 -26
  54. package/lib/metadataTypes/definitions/List.definition.js +1 -1
  55. package/lib/metadataTypes/definitions/Query.definition.js +1 -1
  56. package/lib/metadataTypes/definitions/Script.definition.js +1 -1
  57. package/lib/metadataTypes/definitions/TransactionalEmail.definition.js +2 -1
  58. package/lib/metadataTypes/definitions/TransactionalPush.definition.js +2 -1
  59. package/lib/metadataTypes/definitions/TransactionalSMS.definition.js +2 -1
  60. package/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js +10 -2
  61. package/lib/util/auth.js +10 -2
  62. package/lib/util/cli.js +4 -1
  63. package/lib/util/file.js +7 -3
  64. package/lib/util/init.js +62 -0
  65. package/lib/util/util.js +131 -11
  66. package/package.json +22 -9
  67. package/test/dataExtension.test.js +10 -10
  68. package/test/interaction.test.js +123 -0
  69. package/test/mockRoot/.mcdevrc.json +1 -1
  70. package/test/mockRoot/deploy/testInstance/testBU/interaction/testExisting_interaction.interaction-meta.json +266 -0
  71. package/test/mockRoot/deploy/testInstance/testBU/interaction/testNew_interaction.interaction-meta.json +266 -0
  72. package/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json +0 -3
  73. package/test/query.test.js +8 -8
  74. package/test/resourceFactory.js +12 -7
  75. package/test/resources/1111111/dataExtension/retrieve-response.xml +26 -0
  76. package/test/resources/9999999/data/v1/customobjectdata/key/childBU_dataextension_test/rowset/get-response.json +13 -0
  77. package/test/resources/9999999/dataFolder/retrieve-response.xml +22 -0
  78. package/test/resources/9999999/eventDefinition/get-expected.json +34 -0
  79. package/test/resources/9999999/interaction/build-expected.json +260 -0
  80. package/test/resources/9999999/interaction/get-expected.json +264 -0
  81. package/test/resources/9999999/interaction/post-expected.json +264 -0
  82. package/test/resources/9999999/interaction/put-expected.json +264 -0
  83. package/test/resources/9999999/interaction/template-expected.json +260 -0
  84. package/test/resources/9999999/interaction/v1/EventDefinitions/get-response.json +43 -0
  85. package/test/resources/9999999/interaction/v1/interactions/get-response.json +222 -3
  86. package/test/resources/9999999/interaction/v1/interactions/post-response.json +280 -0
  87. package/test/resources/9999999/interaction/v1/interactions/put-response.json +280 -0
  88. package/test/resources/9999999/messaging/v1/email/definitions/post-response.json +1 -1
  89. package/test/resources/9999999/query/post-expected.sql +1 -1
  90. package/test/resources/9999999/transactionalEmail/post-expected.json +1 -1
  91. package/test/transactionalEmail.test.js +7 -7
  92. package/test/transactionalPush.test.js +7 -7
  93. package/test/transactionalSMS.test.js +7 -7
  94. package/test/utils.js +50 -0
  95. package/types/mcdev.d.js +1 -0
@@ -1,7 +1,7 @@
1
1
  // asset types https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/base-asset-types.htm
2
2
  module.exports = {
3
3
  bodyIteratorField: 'items',
4
- dependencies: ['folder'],
4
+ dependencies: ['folder-asset', 'folder-asset-shared'],
5
5
  folderType: 'asset',
6
6
  hasExtended: false,
7
7
  idField: 'id',
@@ -27,7 +27,7 @@ module.exports = {
27
27
  'dataExtract',
28
28
  'emailSendDefinition',
29
29
  'fileTransfer',
30
- 'folder',
30
+ 'folder-automations',
31
31
  'importFile',
32
32
  'query',
33
33
  'script',
@@ -1,6 +1,15 @@
1
1
  module.exports = {
2
2
  bodyIteratorField: 'Results',
3
- dependencies: ['folder', 'dataExtensionTemplate'],
3
+ dependencies: [
4
+ 'folder-hidden',
5
+ 'folder-dataextension',
6
+ 'folder-salesforcedataextension',
7
+ 'folder-shared_data',
8
+ 'folder-shared_dataextension',
9
+ 'folder-shared_salesforcedataextension',
10
+ 'folder-synchronizeddataextension',
11
+ 'dataExtensionTemplate',
12
+ ],
4
13
  folderType: 'dataextension',
5
14
  filter: {
6
15
  CustomerKey: [
@@ -1,6 +1,6 @@
1
1
  module.exports = {
2
2
  bodyIteratorField: 'Results',
3
- dependencies: ['folder'],
3
+ dependencies: ['folder-hidden', 'folder-email', 'folder-shared_email_default'],
4
4
  hasExtended: false,
5
5
  idField: 'ID',
6
6
  keepId: true,
@@ -1,6 +1,6 @@
1
1
  module.exports = {
2
2
  bodyIteratorField: 'Results',
3
- dependencies: ['folder', 'email', 'asset-message', 'dataExtension', 'list'], // filter, SendClassification, SenderProfile, DeliveryProfile
3
+ dependencies: ['folder-userinitiatedsends', 'email', 'asset-message', 'dataExtension', 'list'], // filter, SendClassification, SenderProfile, DeliveryProfile
4
4
  folderType: 'userinitiatedsends',
5
5
  hasExtended: false,
6
6
  idField: 'ObjectID',
@@ -12,15 +12,48 @@ module.exports = {
12
12
  restPagination: true,
13
13
  type: 'eventDefinition',
14
14
  typeDescription: 'Used in Journeys (Interactions) to define Entry Events.',
15
- typeRetrieveByDefault: false,
15
+ typeRetrieveByDefault: true,
16
16
  typeName: 'Journey: Entry Event Definition',
17
17
  fields: {
18
+ 'arguments.audienceCount': {
19
+ isCreateable: true,
20
+ isUpdateable: true,
21
+ retrieving: true,
22
+ template: true,
23
+ },
24
+ 'arguments.audienceDefinitionID': {
25
+ isCreateable: true,
26
+ isUpdateable: true,
27
+ retrieving: true,
28
+ template: true,
29
+ },
30
+ 'arguments.audienceDescription': {
31
+ isCreateable: true,
32
+ isUpdateable: true,
33
+ retrieving: true,
34
+ template: true,
35
+ },
36
+ 'arguments.audienceSource': {
37
+ skipValidation: true,
38
+ },
39
+ 'arguments.audienceName': {
40
+ isCreateable: true,
41
+ isUpdateable: true,
42
+ retrieving: true,
43
+ template: true,
44
+ },
18
45
  'arguments.automationId': {
19
46
  isCreateable: true,
20
47
  isUpdateable: true,
21
48
  retrieving: true,
22
49
  template: true,
23
50
  },
51
+ 'arguments.buildAudienceDefinitionID': {
52
+ isCreateable: true,
53
+ isUpdateable: true,
54
+ retrieving: true,
55
+ template: true,
56
+ },
24
57
  'arguments.contactAttributeGroup': {
25
58
  isCreateable: true,
26
59
  isUpdateable: true,
@@ -832,6 +865,12 @@ module.exports = {
832
865
  retrieving: true,
833
866
  template: false,
834
867
  },
868
+ 'schema.isPlatformObject': {
869
+ isCreateable: true,
870
+ isUpdateable: true,
871
+ retrieving: true,
872
+ template: true,
873
+ },
835
874
  'schema.fields': {
836
875
  isCreateable: true,
837
876
  isUpdateable: true,
@@ -1,6 +1,36 @@
1
1
  module.exports = {
2
2
  bodyIteratorField: 'Results',
3
3
  dependencies: [],
4
+ subTypes: [
5
+ 'asset-shared',
6
+ 'asset',
7
+ 'contextual_suppression_list',
8
+ 'dataextension',
9
+ 'filteractivity',
10
+ 'filterdefinition',
11
+ 'journey',
12
+ 'list',
13
+ 'mysubs',
14
+ 'mysubs',
15
+ 'publication',
16
+ 'queryactivity',
17
+ 'salesforcedataextension',
18
+ 'shared_content',
19
+ 'shared_data',
20
+ 'shared_dataextension',
21
+ 'shared_email',
22
+ 'shared_item',
23
+ 'shared_portfolio',
24
+ 'shared_publication',
25
+ 'shared_salesforcedataextension',
26
+ 'shared_suppression_list',
27
+ 'shared_template',
28
+ 'ssjsactivity',
29
+ 'suppression_list',
30
+ 'synchronizeddataextension',
31
+ 'triggered_send_journeybuilder',
32
+ 'triggered_send',
33
+ ],
4
34
  deployFolderTypes: [
5
35
  // lower-case values!
6
36
  'asset',
@@ -41,6 +71,7 @@ module.exports = {
41
71
  ],
42
72
  hasExtended: false,
43
73
  idField: 'ID',
74
+ keepId: true,
44
75
  keyField: 'CustomerKey',
45
76
  nameField: 'Name',
46
77
  restPagination: false,
@@ -1,6 +1,6 @@
1
1
  module.exports = {
2
2
  bodyIteratorField: 'items',
3
- dependencies: ['folder', 'ftpLocation', 'dataExtension', 'list'], // folder has to be kept in here to resolve lists correctly
3
+ dependencies: ['ftpLocation', 'dataExtension', 'list'],
4
4
  destinationObjectTypeMapping: {
5
5
  unknown: 783,
6
6
  DataExtension: 310,
@@ -1,6 +1,11 @@
1
+ // overview: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/jb-api-specification.html
2
+ // obj definition: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/getting-started-spec.html
3
+ // insert: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/postCreateInteraction.html
4
+ // update: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/putUpdateInteraction.html
1
5
  module.exports = {
2
6
  bodyIteratorField: 'items',
3
- dependencies: [],
7
+ dependencies: ['folder-journey', 'triggeredSendDefinition', 'eventDefinition'], // ! interaction and transactionalEmail both link to each other. caching transactionalEmail here "manually" instead of via dependencies array, assuming that it is quicker than the other way round
8
+ folderIdField: 'categoryId',
4
9
  hasExtended: false,
5
10
  idField: 'id',
6
11
  keyField: 'key',
@@ -9,10 +14,11 @@ module.exports = {
9
14
  createdNameField: null,
10
15
  lastmodDateField: 'modifiedDate',
11
16
  lastmodNameField: null,
12
- restPagination: false,
17
+ restPagination: true,
18
+ restPageSize: 250,
13
19
  type: 'interaction',
14
- typeDescription: 'Journey from Builder (internally called "Interaction").',
15
- typeRetrieveByDefault: false,
20
+ typeDescription: 'Journey (internally called "Interaction").',
21
+ typeRetrieveByDefault: true,
16
22
  typeName: 'Journey',
17
23
  fields: {
18
24
  activities: {
@@ -61,10 +67,10 @@ module.exports = {
61
67
  template: null,
62
68
  },
63
69
  definitionId: {
64
- isCreateable: true,
65
- isUpdateable: true,
66
- retrieving: true,
67
- template: true,
70
+ isCreateable: false,
71
+ isUpdateable: false,
72
+ retrieving: false,
73
+ template: false,
68
74
  },
69
75
  definitionType: {
70
76
  isCreateable: true,
@@ -104,9 +110,9 @@ module.exports = {
104
110
  },
105
111
  id: {
106
112
  isCreateable: false,
107
- isUpdateable: true,
108
- retrieving: false,
109
- template: false,
113
+ isUpdateable: false,
114
+ retrieving: true,
115
+ template: true,
110
116
  },
111
117
  key: {
112
118
  isCreateable: true,
@@ -117,7 +123,7 @@ module.exports = {
117
123
  lastPublishedDate: {
118
124
  isCreateable: false,
119
125
  isUpdateable: false,
120
- retrieving: false,
126
+ retrieving: true,
121
127
  template: false,
122
128
  },
123
129
  'metaData.templateId': {
@@ -128,9 +134,9 @@ module.exports = {
128
134
  },
129
135
  modifiedDate: {
130
136
  isCreateable: false,
131
- isUpdateable: false,
137
+ isUpdateable: true,
132
138
  retrieving: true,
133
- template: false,
139
+ template: true,
134
140
  },
135
141
  name: {
136
142
  isCreateable: true,
@@ -151,10 +157,10 @@ module.exports = {
151
157
  template: false,
152
158
  },
153
159
  status: {
154
- isCreateable: true,
160
+ isCreateable: false,
155
161
  isUpdateable: true,
156
162
  retrieving: true,
157
- template: true,
163
+ template: false,
158
164
  },
159
165
  triggers: {
160
166
  isCreateable: true,
@@ -169,16 +175,16 @@ module.exports = {
169
175
  template: false,
170
176
  },
171
177
  'triggers[].key': {
172
- isCreateable: false,
173
- isUpdateable: false,
174
- retrieving: false,
175
- template: false,
178
+ isCreateable: true,
179
+ isUpdateable: true,
180
+ retrieving: true,
181
+ template: true,
176
182
  },
177
183
  'triggers[].name': {
178
- isCreateable: false,
179
- isUpdateable: false,
180
- retrieving: false,
181
- template: false,
184
+ isCreateable: true,
185
+ isUpdateable: true,
186
+ retrieving: true,
187
+ template: true,
182
188
  },
183
189
  'triggers[].description': {
184
190
  isCreateable: true,
@@ -388,15 +394,30 @@ module.exports = {
388
394
  },
389
395
  version: {
390
396
  isCreateable: false,
391
- isUpdateable: false,
397
+ isUpdateable: true,
392
398
  retrieving: true,
393
399
  template: false,
394
400
  },
395
401
  workflowApiVersion: {
402
+ isCreateable: true,
403
+ isUpdateable: true,
404
+ retrieving: true,
405
+ template: true,
406
+ },
407
+ metaData: {
408
+ skipValidation: true,
409
+ },
410
+ notifiers: {
411
+ skipValidation: true,
412
+ },
413
+ tags: {
414
+ skipValidation: true,
415
+ },
416
+ r__folder_Path: {
396
417
  isCreateable: false,
397
418
  isUpdateable: false,
398
419
  retrieving: true,
399
- template: false,
420
+ template: true,
400
421
  },
401
422
  },
402
423
  };
@@ -1,6 +1,6 @@
1
1
  module.exports = {
2
2
  bodyIteratorField: 'Results',
3
- dependencies: ['folder'],
3
+ dependencies: ['folder-mysubs', 'folder-list', 'folder-publication'],
4
4
  folderType: 'list',
5
5
  hasExtended: false,
6
6
  idField: 'ObjectID',
@@ -1,6 +1,6 @@
1
1
  module.exports = {
2
2
  bodyIteratorField: 'items',
3
- dependencies: ['folder', 'dataExtension'],
3
+ dependencies: ['folder-queryactivity', 'dataExtension'],
4
4
  folderType: 'queryactivity',
5
5
  filter: {
6
6
  description: ['Query created by Query Studio'],
@@ -1,6 +1,6 @@
1
1
  module.exports = {
2
2
  bodyIteratorField: 'items',
3
- dependencies: ['folder'],
3
+ dependencies: ['folder-ssjsactivity'],
4
4
  folderType: 'ssjsactivity',
5
5
  hasExtended: false,
6
6
  idField: 'ssjsActivityId',
@@ -9,7 +9,8 @@ module.exports = {
9
9
  createdNameField: null,
10
10
  lastmodDateField: 'modifiedDate',
11
11
  lastmodNameField: null,
12
- restPagination: false,
12
+ restPagination: true,
13
+ restPageSize: 100,
13
14
  type: 'transactionalEmail',
14
15
  typeDescription: 'Lets you send immediate Email messages via API events',
15
16
  typeRetrieveByDefault: true,
@@ -9,7 +9,8 @@ module.exports = {
9
9
  createdNameField: null,
10
10
  lastmodDateField: 'modifiedDate',
11
11
  lastmodNameField: null,
12
- restPagination: false,
12
+ restPagination: true,
13
+ restPageSize: 100,
13
14
  type: 'transactionalPush',
14
15
  typeDescription: 'Lets you send immediate Push messages via API events',
15
16
  typeRetrieveByDefault: true,
@@ -9,7 +9,8 @@ module.exports = {
9
9
  createdNameField: null,
10
10
  lastmodDateField: 'modifiedDate',
11
11
  lastmodNameField: null,
12
- restPagination: false,
12
+ restPagination: true,
13
+ restPageSize: 100,
13
14
  type: 'transactionalSMS',
14
15
  typeDescription: 'Lets you send immediate SMS messages via API events',
15
16
  typeRetrieveByDefault: true,
@@ -1,6 +1,13 @@
1
1
  module.exports = {
2
2
  bodyIteratorField: 'Results',
3
- dependencies: ['folder', 'email', 'asset-message', 'list'], // SendClassification, SenderProfile, DeliveryProfile
3
+ dependencies: [
4
+ 'folder-hidden',
5
+ 'folder-triggered_send',
6
+ 'folder-triggered_send_journeybuilder',
7
+ 'email',
8
+ 'asset-message',
9
+ 'list',
10
+ ], // SendClassification, SenderProfile, DeliveryProfile
4
11
  folderType: 'triggered_send',
5
12
  hasExtended: false,
6
13
  idField: 'ObjectID',
@@ -380,7 +387,7 @@ module.exports = {
380
387
  },
381
388
  RefreshContent: {
382
389
  isCreateable: false,
383
- isUpdateable: false,
390
+ isUpdateable: true,
384
391
  retrieving: false,
385
392
  templating: false,
386
393
  },
@@ -525,5 +532,6 @@ module.exports = {
525
532
  r__folder_Path: { skipValidation: true },
526
533
  r__assetMessage_Name: { skipValidation: true },
527
534
  r__assetMessage_Key: { skipValidation: true },
535
+ r__list_PathName: { skipValidation: true },
528
536
  },
529
537
  };
package/lib/util/auth.js CHANGED
@@ -91,9 +91,9 @@ const Auth = {
91
91
  function setupSDK(sessionKey, authObject) {
92
92
  return new SDK(authObject, {
93
93
  eventHandlers: {
94
- onLoop: (type, req) => {
94
+ onLoop: (type, accumulator) => {
95
95
  Util.logger.info(
96
- ` - Requesting next batch (currently ${req.Results.length} records)`
96
+ ` - Requesting next batch (currently ${accumulator?.length} records)`
97
97
  );
98
98
  },
99
99
  onRefresh: (authObject) => {
@@ -104,10 +104,18 @@ function setupSDK(sessionKey, authObject) {
104
104
  Util.logger.warn(
105
105
  ` - Connection problem (Code: ${ex.code}). Retrying ${remainingAttempts} time${
106
106
  remainingAttempts > 1 ? 's' : ''
107
+ }${
108
+ ex.endpoint
109
+ ? Util.getGrayMsg(
110
+ ' - ' + ex.endpoint.split('rest.marketingcloudapis.com')[1]
111
+ )
112
+ : ''
107
113
  }`
108
114
  );
109
115
  Util.logger.errorStack(ex);
110
116
  },
117
+ // logRequest: (req) => console.log('request', req), // uncomment to log requests
118
+ // logResponse: (res) => console.log('response:', res), // uncomment to log responses
111
119
  },
112
120
  requestAttempts: 4,
113
121
  retryOnConnectionError: true,
package/lib/util/cli.js CHANGED
@@ -410,7 +410,10 @@ const Cli = {
410
410
  const flattenedDefinitions = [];
411
411
  for (const el in MetadataDefinitions) {
412
412
  // if subtypes on metadata (eg. Assets) then add each nested subtype
413
- if (MetadataDefinitions[el].subTypes) {
413
+ if (
414
+ MetadataDefinitions[el].subTypes &&
415
+ Array.isArray(MetadataDefinitions[el].typeRetrieveByDefault)
416
+ ) {
414
417
  for (const subtype of MetadataDefinitions[el].subTypes) {
415
418
  flattenedDefinitions.push({
416
419
  typeName:
package/lib/util/file.js CHANGED
@@ -246,6 +246,10 @@ const File = {
246
246
  filename + '.' + filetype,
247
247
  ])}`;
248
248
  Util.logger.debug(warnMsg);
249
+ if (Util.logger.level === 'debug') {
250
+ // useful when running test cases in which we cannot see .error files
251
+ Util.logger.debug(ex.message);
252
+ }
249
253
 
250
254
  // save prettier errror into log file
251
255
  // Note: we have to filter color codes from prettier's error message before saving it to file
@@ -300,7 +304,7 @@ const File = {
300
304
  * @param {string} filename name of the file without '.json' ending
301
305
  * @param {boolean} sync should execute sync (default is async)
302
306
  * @param {boolean} cleanPath should execute sync (default is true)
303
- * @returns {Promise | object} Promise or JSON object depending on if async or not
307
+ * @returns {Promise.<object> | object | void} Promise or JSON object depending on if async or not; void on error
304
308
  */
305
309
  readJSONFile: function (directory, filename, sync, cleanPath) {
306
310
  try {
@@ -336,7 +340,7 @@ const File = {
336
340
  * @param {string} filename name of the file without '.json' ending
337
341
  * @param {string} filetype filetype suffix
338
342
  * @param {string} [encoding='utf8'] read file with encoding (defaults to utf-8)
339
- * @returns {Promise.<string>} file contents
343
+ * @returns {Promise.<string> | void} file contents; void on error
340
344
  */
341
345
  readFilteredFilename: function (directory, filename, filetype, encoding) {
342
346
  try {
@@ -411,7 +415,7 @@ const File = {
411
415
  * @param {number} [depth] how many levels to check (1 base)
412
416
  * @param {boolean} [includeStem] include the parent directory in the response
413
417
  * @param {number} [_stemLength] set recursively for subfolders. do not set manually!
414
- * @returns {string[]} array of fully defined file paths
418
+ * @returns {string[] | void} array of fully defined file paths; void on error
415
419
  */
416
420
  readDirectoriesSync: function (directory, depth, includeStem, _stemLength) {
417
421
  try {
package/lib/util/init.js CHANGED
@@ -186,6 +186,68 @@ const Init = {
186
186
  }
187
187
  },
188
188
 
189
+ /**
190
+ * Creates template file for properties.json
191
+ *
192
+ * @returns {Promise.<void>} -
193
+ */
194
+ async joinProject() {
195
+ const responses = await inquirer.prompt([
196
+ {
197
+ type: 'confirm',
198
+ name: 'isJoin',
199
+ message:
200
+ 'Do you want to join an existing project for which you have a Git-Repository URL?',
201
+ default: true,
202
+ },
203
+ ]);
204
+ if (responses.isJoin) {
205
+ const gitRepoQs = await inquirer.prompt([
206
+ {
207
+ type: 'input',
208
+ name: 'gitRepoUrl',
209
+ message: 'Please enter the Git-Repository URL',
210
+ },
211
+ {
212
+ type: 'input',
213
+ name: 'gitBranch',
214
+ message:
215
+ 'If you were asked to work on a specific branch, please enter it now (or leave empty for default)',
216
+ },
217
+ ]);
218
+ const repoName = gitRepoQs.gitRepoUrl.split('/').pop().replace('.git', '');
219
+ // clone repo into current folder
220
+ Util.execSync(
221
+ 'git',
222
+ [
223
+ 'clone',
224
+ gitRepoQs.gitBranch ? `--branch ${gitRepoQs.gitBranch}` : null,
225
+ '--config core.longpaths=true',
226
+ '--config core.autocrlf=input',
227
+ gitRepoQs.gitRepoUrl,
228
+ ].filter(Boolean)
229
+ );
230
+ // make sure we switch to the new subfolder or else the rest will fail
231
+ process.chdir(repoName);
232
+
233
+ // check if the branch looks good
234
+ const properties = await config.getProperties(true, true);
235
+ if (!properties) {
236
+ Util.logger.error(
237
+ 'Could not find .mcdevrc.json file in project folder. Please check your Git repository and branch.'
238
+ );
239
+ return;
240
+ }
241
+
242
+ // get name and email that's to be used for git commits
243
+ await InitGit._updateGitConfigUser();
244
+
245
+ // ask the user to enter the server credentials
246
+ await this.initProject(properties);
247
+ } else {
248
+ return;
249
+ }
250
+ },
189
251
  /**
190
252
  * helper for @initProject that optionally creates markets and market lists for all BUs
191
253
  */