mcdev 4.3.4 → 5.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 (228) hide show
  1. package/.coverage-comment-template.md +20 -0
  2. package/.coverage-comment-template.svelte +178 -0
  3. package/.eslintrc.json +2 -0
  4. package/.github/ISSUE_TEMPLATE/bug.yml +2 -0
  5. package/.github/workflows/code-test.yml +36 -0
  6. package/.github/workflows/coverage-base-update.yml +57 -0
  7. package/.github/workflows/coverage-develop-branch.yml +41 -0
  8. package/.github/workflows/coverage-main-branch.yml +41 -0
  9. package/.github/workflows/coverage.yml +77 -0
  10. package/.husky/post-checkout +1 -1
  11. package/.prettierrc +1 -1
  12. package/.vscode/extensions.json +0 -4
  13. package/README.md +1 -1
  14. package/boilerplate/config.json +1 -1
  15. package/boilerplate/files/.prettierrc +1 -1
  16. package/boilerplate/files/.vscode/extensions.json +1 -1
  17. package/boilerplate/forcedUpdates.json +4 -0
  18. package/docs/dist/documentation.md +1196 -430
  19. package/lib/Builder.js +6 -1
  20. package/lib/Deployer.js +30 -5
  21. package/lib/MetadataTypeDefinitions.js +8 -6
  22. package/lib/MetadataTypeInfo.js +8 -6
  23. package/lib/cli.js +54 -42
  24. package/lib/index.js +82 -8
  25. package/lib/metadataTypes/Asset.js +73 -1
  26. package/lib/metadataTypes/AttributeGroup.js +0 -1
  27. package/lib/metadataTypes/Automation.js +48 -5
  28. package/lib/metadataTypes/Campaign.js +20 -7
  29. package/lib/metadataTypes/ContentArea.js +1 -1
  30. package/lib/metadataTypes/DataExtension.js +221 -184
  31. package/lib/metadataTypes/DataExtensionField.js +12 -19
  32. package/lib/metadataTypes/DataExtensionTemplate.js +1 -1
  33. package/lib/metadataTypes/DataExtract.js +1 -1
  34. package/lib/metadataTypes/DataExtractType.js +1 -1
  35. package/lib/metadataTypes/Email.js +1 -1
  36. package/lib/metadataTypes/{EmailSendDefinition.js → EmailSend.js} +5 -5
  37. package/lib/metadataTypes/{EventDefinition.js → Event.js} +17 -35
  38. package/lib/metadataTypes/{FtpLocation.js → FileLocation.js} +2 -2
  39. package/lib/metadataTypes/FileTransfer.js +8 -7
  40. package/lib/metadataTypes/Filter.js +1 -1
  41. package/lib/metadataTypes/Folder.js +8 -3
  42. package/lib/metadataTypes/ImportFile.js +6 -6
  43. package/lib/metadataTypes/{Interaction.js → Journey.js} +311 -147
  44. package/lib/metadataTypes/List.js +2 -2
  45. package/lib/metadataTypes/MetadataType.js +318 -90
  46. package/lib/metadataTypes/MobileCode.js +0 -1
  47. package/lib/metadataTypes/MobileKeyword.js +336 -40
  48. package/lib/metadataTypes/MobileMessage.js +473 -0
  49. package/lib/metadataTypes/Query.js +114 -32
  50. package/lib/metadataTypes/Role.js +60 -21
  51. package/lib/metadataTypes/Script.js +2 -3
  52. package/lib/metadataTypes/SendClassification.js +40 -0
  53. package/lib/metadataTypes/SetDefinition.js +1 -7
  54. package/lib/metadataTypes/TransactionalEmail.js +2 -3
  55. package/lib/metadataTypes/TransactionalMessage.js +1 -2
  56. package/lib/metadataTypes/TransactionalSMS.js +8 -15
  57. package/lib/metadataTypes/{TriggeredSendDefinition.js → TriggeredSend.js} +35 -27
  58. package/lib/metadataTypes/User.js +1185 -0
  59. package/lib/metadataTypes/definitions/Asset.definition.js +1 -0
  60. package/lib/metadataTypes/definitions/AttributeGroup.definition.js +1 -0
  61. package/lib/metadataTypes/definitions/Automation.definition.js +3 -2
  62. package/lib/metadataTypes/definitions/Campaign.definition.js +79 -4
  63. package/lib/metadataTypes/definitions/ContentArea.definition.js +1 -0
  64. package/lib/metadataTypes/definitions/DataExtension.definition.js +2 -1
  65. package/lib/metadataTypes/definitions/DataExtensionField.definition.js +1 -0
  66. package/lib/metadataTypes/definitions/DataExtensionTemplate.definition.js +1 -0
  67. package/lib/metadataTypes/definitions/DataExtract.definition.js +1 -0
  68. package/lib/metadataTypes/definitions/DataExtractType.definition.js +1 -0
  69. package/lib/metadataTypes/definitions/Discovery.definition.js +1 -0
  70. package/lib/metadataTypes/definitions/Email.definition.js +1 -0
  71. package/lib/metadataTypes/definitions/{EmailSendDefinition.definition.js → EmailSend.definition.js} +4 -2
  72. package/lib/metadataTypes/definitions/{EventDefinition.definition.js → Event.definition.js} +2 -1
  73. package/lib/metadataTypes/definitions/{FtpLocation.definition.js → FileLocation.definition.js} +4 -3
  74. package/lib/metadataTypes/definitions/FileTransfer.definition.js +3 -2
  75. package/lib/metadataTypes/definitions/Filter.definition.js +1 -0
  76. package/lib/metadataTypes/definitions/Folder.definition.js +2 -0
  77. package/lib/metadataTypes/definitions/ImportFile.definition.js +4 -3
  78. package/lib/metadataTypes/definitions/{Interaction.definition.js → Journey.definition.js} +11 -2
  79. package/lib/metadataTypes/definitions/List.definition.js +1 -0
  80. package/lib/metadataTypes/definitions/MobileCode.definition.js +3 -1
  81. package/lib/metadataTypes/definitions/MobileKeyword.definition.js +27 -17
  82. package/lib/metadataTypes/definitions/MobileMessage.definition.js +743 -0
  83. package/lib/metadataTypes/definitions/Query.definition.js +3 -2
  84. package/lib/metadataTypes/definitions/Role.definition.js +5 -0
  85. package/lib/metadataTypes/definitions/Script.definition.js +1 -0
  86. package/lib/metadataTypes/definitions/SendClassification.definition.js +114 -0
  87. package/lib/metadataTypes/definitions/SetDefinition.definition.js +1 -0
  88. package/lib/metadataTypes/definitions/TransactionalEmail.definition.js +2 -1
  89. package/lib/metadataTypes/definitions/TransactionalPush.definition.js +1 -0
  90. package/lib/metadataTypes/definitions/TransactionalSMS.definition.js +1 -0
  91. package/lib/metadataTypes/definitions/{TriggeredSendDefinition.definition.js → TriggeredSend.definition.js} +5 -3
  92. package/lib/metadataTypes/definitions/User.definition.js +365 -0
  93. package/lib/retrieveChangelog.js +1 -2
  94. package/lib/util/auth.js +38 -9
  95. package/lib/util/businessUnit.js +3 -3
  96. package/lib/util/cli.js +55 -7
  97. package/lib/util/devops.js +6 -4
  98. package/lib/util/file.js +55 -13
  99. package/lib/util/init.config.js +1 -2
  100. package/lib/util/init.npm.js +3 -3
  101. package/lib/util/util.js +23 -14
  102. package/package.json +16 -15
  103. package/test/general.test.js +62 -0
  104. package/test/mockRoot/.mcdevrc.json +7 -5
  105. package/test/mockRoot/deploy/testInstance/_ParentBU_/user/testBlocked_user.user-meta.json +23 -0
  106. package/test/mockRoot/deploy/testInstance/_ParentBU_/user/testExisting_user.user-meta.json +31 -0
  107. package/test/mockRoot/deploy/testInstance/_ParentBU_/user/testNew_user.user-meta.json +27 -0
  108. package/test/mockRoot/deploy/testInstance/testBU/dataExtension/{childBU_dataextension_test.dataExtension-meta.json → testExisting_dataExtension.dataExtension-meta.json} +2 -2
  109. package/test/mockRoot/deploy/testInstance/testBU/dataExtension/{testDataExtension.dataExtension-meta.json → testNew_dataExtension.dataExtension-meta.json} +2 -2
  110. package/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_interaction.interaction-meta.json +576 -0
  111. package/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/testNew_keyword.mobileKeyword-meta.amp +2 -0
  112. package/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/testNew_keyword.mobileKeyword-meta.json +10 -0
  113. package/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/testNew_keyword_blocked.mobileKeyword-meta.amp +2 -0
  114. package/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/testNew_keyword_blocked.mobileKeyword-meta.json +10 -0
  115. package/test/mockRoot/deploy/testInstance/testBU/mobileMessage/NTIzOjc4OjA.mobileMessage-meta.amp +1 -0
  116. package/test/mockRoot/deploy/testInstance/testBU/mobileMessage/NTIzOjc4OjA.mobileMessage-meta.json +61 -0
  117. package/test/mockRoot/deploy/testInstance/testBU/mobileMessage/new.mobileMessage-meta.amp +1 -0
  118. package/test/mockRoot/deploy/testInstance/testBU/mobileMessage/new.mobileMessage-meta.json +60 -0
  119. package/test/mockRoot/deploy/testInstance/testBU/query/testExistingQuery.query-meta.json +1 -1
  120. package/test/mockRoot/deploy/testInstance/testBU/query/testNewQuery.query-meta.json +1 -1
  121. package/test/mockRoot/deploy/testInstance/testBU/query/testNewQuery.query-meta.sql +1 -1
  122. package/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json +1 -1
  123. package/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testNew_temail.transactionalEmail-meta.json +1 -1
  124. package/test/resourceFactory.js +13 -0
  125. package/test/resources/1111111/accountUser/configure-response.xml +70 -0
  126. package/test/resources/1111111/accountUser/create-response.xml +97 -0
  127. package/test/resources/1111111/accountUser/retrieve-response.xml +156 -0
  128. package/test/resources/1111111/accountUser/update-response.xml +111 -0
  129. package/test/resources/1111111/accountUserAccount/retrieve-response.xml +77 -0
  130. package/test/resources/1111111/platform/v1/setup/quickflow/data/get-response.json +455 -0
  131. package/test/resources/1111111/role/retrieve-response.xml +76 -0
  132. package/test/resources/1111111/user/build-expected.json +16 -0
  133. package/test/resources/1111111/user/create-expected.json +21 -0
  134. package/test/resources/1111111/user/retrieve-expected.json +24 -0
  135. package/test/resources/1111111/user/template-expected.json +16 -0
  136. package/test/resources/1111111/user/update-expected.json +21 -0
  137. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/delete-response.json +1 -0
  138. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/get-response.json +17 -0
  139. package/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/patch-response.json +3 -3
  140. package/test/resources/9999999/automation/v1/queries/get-response.json +21 -4
  141. package/test/resources/9999999/automation/v1/queries/post-response.json +4 -4
  142. package/test/resources/9999999/data/v1/customobjectdata/key/{childBU_dataextension_test → testExisting_dataExtension}/rowset/get-response.json +1 -1
  143. package/test/resources/9999999/dataExtension/build-expected.json +3 -3
  144. package/test/resources/9999999/dataExtension/create-expected.json +2 -2
  145. package/test/resources/9999999/dataExtension/create-response.xml +8 -3
  146. package/test/resources/9999999/dataExtension/retrieve-expected.json +3 -3
  147. package/test/resources/9999999/dataExtension/retrieve-response.xml +9 -4
  148. package/test/resources/9999999/dataExtension/template-expected.json +3 -3
  149. package/test/resources/9999999/dataExtension/update-expected.json +3 -3
  150. package/test/resources/9999999/dataExtension/update-response.xml +9 -4
  151. package/test/resources/9999999/dataExtensionField/retrieve-response.xml +14 -9
  152. package/test/resources/9999999/interaction/v1/interactions/get-response.json +312 -0
  153. package/test/resources/9999999/interaction/v1/interactions/key_testExisting_interaction/get-response.json +312 -0
  154. package/test/resources/9999999/interaction/v1/interactions/key_testExisting_interaction/put-response.json +592 -0
  155. package/test/resources/9999999/journey/build-expected.json +572 -0
  156. package/test/resources/9999999/journey/get-expected.json +576 -0
  157. package/test/resources/9999999/journey/put-expected.json +576 -0
  158. package/test/resources/9999999/journey/template-expected.json +572 -0
  159. package/test/resources/9999999/legacy/v1/beta/mobile/keyword/NXV4ZFMwTEFwRVczd3RaLUF5X3p5dzo4Njow/get-response.json +42 -0
  160. package/test/resources/9999999/legacy/v1/beta/mobile/keyword/cTVJaG5oSDJPVUNHcUh6Z3pQT2tVdzo4Njow/delete-response.json +0 -0
  161. package/test/resources/9999999/legacy/v1/beta/mobile/keyword/get-response.json +1 -0
  162. package/test/resources/9999999/legacy/v1/beta/mobile/keyword/post-response.json +3 -0
  163. package/test/resources/9999999/legacy/v1/beta/mobile/message/NTIzOjc4OjA/delete-response.json +0 -0
  164. package/test/resources/9999999/legacy/v1/beta/mobile/message/NTIzOjc4OjA/get-response.json +106 -0
  165. package/test/resources/9999999/legacy/v1/beta/mobile/message/NTIzOjc4OjA/post-response.json +0 -0
  166. package/test/resources/9999999/legacy/v1/beta/mobile/message/NTQ3Ojc4OjA/get-response.json +127 -0
  167. package/test/resources/9999999/legacy/v1/beta/mobile/message/get-response.json +129 -0
  168. package/test/resources/9999999/legacy/v1/beta/mobile/message/post-response.json +3 -0
  169. package/test/resources/9999999/legacy/v1/beta2/data/campaign/get-response.json +29 -0
  170. package/test/resources/9999999/messaging/v1/email/definitions/post-response.json +1 -1
  171. package/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/get-response.json +1 -1
  172. package/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/patch-response.json +1 -1
  173. package/test/resources/9999999/mobileKeyword/build-expected.amp +2 -0
  174. package/test/resources/9999999/mobileKeyword/build-expected.json +9 -0
  175. package/test/resources/9999999/mobileKeyword/get-expected.amp +2 -0
  176. package/test/resources/9999999/mobileKeyword/get-expected.json +15 -0
  177. package/test/resources/9999999/mobileKeyword/post-create-expected.amp +2 -0
  178. package/test/resources/9999999/mobileKeyword/post-create-expected.json +17 -0
  179. package/test/resources/9999999/mobileKeyword/template-expected.amp +2 -0
  180. package/test/resources/9999999/mobileKeyword/template-expected.json +9 -0
  181. package/test/resources/9999999/mobileMessage/build-expected.amp +1 -0
  182. package/test/resources/9999999/mobileMessage/build-expected.json +60 -0
  183. package/test/resources/9999999/mobileMessage/get-expected.amp +1 -0
  184. package/test/resources/9999999/mobileMessage/get-expected.json +61 -0
  185. package/test/resources/9999999/mobileMessage/post-create-expected.amp +1 -0
  186. package/test/resources/9999999/mobileMessage/post-create-expected.json +63 -0
  187. package/test/resources/9999999/mobileMessage/post-update-expected.amp +1 -0
  188. package/test/resources/9999999/mobileMessage/post-update-expected.json +61 -0
  189. package/test/resources/9999999/mobileMessage/template-expected.amp +1 -0
  190. package/test/resources/9999999/mobileMessage/template-expected.json +60 -0
  191. package/test/resources/9999999/query/build-expected.json +1 -1
  192. package/test/resources/9999999/query/get-expected.json +1 -1
  193. package/test/resources/9999999/query/get2-expected.json +11 -0
  194. package/test/resources/9999999/query/patch-expected.json +1 -1
  195. package/test/resources/9999999/query/post-expected.json +1 -1
  196. package/test/resources/9999999/query/template-expected.json +1 -1
  197. package/test/resources/9999999/queryDefinition/retrieve-response.xml +30 -0
  198. package/test/resources/9999999/transactionalEmail/build-expected.json +5 -5
  199. package/test/resources/9999999/transactionalEmail/get-expected.json +1 -1
  200. package/test/resources/9999999/transactionalEmail/patch-expected.json +1 -1
  201. package/test/resources/9999999/transactionalEmail/post-expected.json +1 -1
  202. package/test/resources/9999999/transactionalEmail/template-expected.json +5 -5
  203. package/test/resources/9999999/transactionalPush/build-expected.json +2 -2
  204. package/test/resources/9999999/transactionalPush/template-expected.json +2 -2
  205. package/test/resources/9999999/transactionalSMS/build-expected.json +3 -3
  206. package/test/resources/9999999/transactionalSMS/template-expected.json +3 -3
  207. package/test/{dataExtension.test.js → type.dataExtension.test.js} +78 -21
  208. package/test/{interaction.test.js → type.journey.test.js} +64 -30
  209. package/test/type.mobileKeyword.test.js +250 -0
  210. package/test/type.mobileMessage.test.js +205 -0
  211. package/test/{query.test.js → type.query.test.js} +102 -5
  212. package/test/{transactionalEmail.test.js → type.transactionalEmail.test.js} +40 -2
  213. package/test/{transactionalPush.test.js → type.transactionalPush.test.js} +41 -2
  214. package/test/{transactionalSMS.test.js → type.transactionalSMS.test.js} +73 -3
  215. package/test/type.user.test.js +160 -0
  216. package/test/utils.js +17 -5
  217. package/types/mcdev.d.js +48 -15
  218. package/.github/workflows/code-analysis.yml +0 -57
  219. package/lib/metadataTypes/AccountUser.js +0 -426
  220. package/lib/metadataTypes/definitions/AccountUser.definition.js +0 -227
  221. package/test/mockRoot/deploy/testInstance/testBU/interaction/testExisting_interaction.interaction-meta.json +0 -266
  222. package/test/resources/9999999/interaction/build-expected.json +0 -260
  223. package/test/resources/9999999/interaction/get-expected.json +0 -264
  224. package/test/resources/9999999/interaction/put-expected.json +0 -264
  225. package/test/resources/9999999/interaction/template-expected.json +0 -260
  226. package/test/resources/9999999/interaction/v1/interactions/put-response.json +0 -280
  227. /package/test/mockRoot/deploy/testInstance/testBU/{interaction → journey}/testNew_interaction.interaction-meta.json +0 -0
  228. /package/test/resources/9999999/{interaction → journey}/post-expected.json +0 -0
@@ -24,7 +24,6 @@ class MobileCode extends MetadataType {
24
24
  retrieveDir,
25
25
  '/legacy/v1/beta/mobile/code/' + (key ? `?$where=keyword%20eq%20%27${key}%27%20` : ''),
26
26
  null,
27
- null,
28
27
  key
29
28
  );
30
29
  }
@@ -20,26 +20,43 @@ class MobileKeyword extends MetadataType {
20
20
  * @param {void} [_] unused parameter
21
21
  * @param {void} [__] unused parameter
22
22
  * @param {string} [key] customer key of single item to retrieve
23
- * @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
23
+ * @returns {Promise.<TYPE.MetadataTypeMapObj> | void} Promise of metadata
24
24
  */
25
25
  static retrieve(retrieveDir, _, __, key) {
26
- return super.retrieveREST(
27
- retrieveDir,
28
- '/legacy/v1/beta/mobile/keyword/?view=simple' +
29
- (key ? `&$where=keyword%20eq%20%27${key}%27%20` : ''),
30
- null,
31
- null,
32
- key
33
- );
26
+ try {
27
+ return super.retrieveREST(
28
+ retrieveDir,
29
+ '/legacy/v1/beta/mobile/keyword/' +
30
+ (key
31
+ ? key.startsWith('id:')
32
+ ? key.slice(3)
33
+ : `?view=simple&$where=keyword%20eq%20%27${key}%27%20`
34
+ : '?view=simple'),
35
+ null,
36
+ key
37
+ );
38
+ } catch (ex) {
39
+ // if the mobileMessage does not exist, the API returns the error "Request failed with status code 400 (ERR_BAD_REQUEST)" which would otherwise bring execution to a hold
40
+ if (key && ex.code === 'ERR_BAD_REQUEST') {
41
+ Util.logger.info(
42
+ `Downloaded: ${this.definition.type} (0)${Util.getKeysString(key)}`
43
+ );
44
+ } else {
45
+ throw ex;
46
+ }
47
+ }
34
48
  }
35
49
 
36
50
  /**
37
51
  * Retrieves event definition metadata for caching
38
52
  *
53
+ * @param {void} _ parameter not used
54
+ * @param {void} __ parameter not used
55
+ * @param {string} [key] customer key of single item to retrieve
39
56
  * @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
40
57
  */
41
- static retrieveForCache() {
42
- return super.retrieveREST(null, '/legacy/v1/beta/mobile/keyword/?view=simple');
58
+ static retrieveForCache(_, __, key) {
59
+ return this.retrieve(null, null, null, key);
43
60
  }
44
61
 
45
62
  /**
@@ -51,37 +68,22 @@ class MobileKeyword extends MetadataType {
51
68
  * @returns {Promise.<TYPE.MetadataTypeItemObj>} Promise of metadata
52
69
  */
53
70
  static async retrieveAsTemplate(templateDir, name, templateVariables) {
54
- // TODO: Decide if we want to keep default handling (and move other types) or keep unique parsing?
55
71
  try {
56
- const res = await this.client.rest.get(
57
- `/legacy/v1/beta/mobile/keyword/?view=simple&$where=keyword%20eq%20%27${name}%27%20`
58
- );
59
- const metadata = JSON.parse(
60
- Util.replaceByObject(
61
- JSON.stringify(Util.templateSearchResult(res.entry, 'keyword', name)),
62
- templateVariables
63
- )
72
+ return super.retrieveTemplateREST(
73
+ templateDir,
74
+ `/legacy/v1/beta/mobile/keyword/?view=simple&$where=keyword%20eq%20%27${name}%27%20`,
75
+ templateVariables,
76
+ name
64
77
  );
65
- if (!metadata.code.id) {
66
- throw new Error(
67
- `MobileKeyword.parseMetadata:: ` +
68
- `No Mobile Code was found for ` +
69
- `event: ${metadata.name}. ` +
70
- `This cannot be templated`
78
+ } catch (ex) {
79
+ // if the mobileMessage does not exist, the API returns the error "Request failed with status code 400 (ERR_BAD_REQUEST)" which would otherwise bring execution to a hold
80
+ if (name && ex.code === 'ERR_BAD_REQUEST') {
81
+ Util.logger.info(
82
+ `Downloaded: ${this.definition.type} (0)${Util.getKeysString(name)}`
71
83
  );
84
+ } else {
85
+ throw ex;
72
86
  }
73
- // remove all fields listed in Definition for templating
74
- this.keepTemplateFields(metadata);
75
- await File.writeJSONToFile(
76
- [templateDir, this.definition.type].join('/'),
77
- metadata.keyword + '.' + this.definition.type + '-meta',
78
- metadata
79
- );
80
- Util.logger.info(`- templated ${this.definition.type}: ${name}`);
81
- return { metadata: metadata, type: this.definition.type };
82
- } catch (ex) {
83
- Util.logger.error('MobileKeyword.retrieveAsTemplate:: ' + ex);
84
- return null;
85
87
  }
86
88
  }
87
89
 
@@ -94,17 +96,311 @@ class MobileKeyword extends MetadataType {
94
96
  static create(MobileKeyword) {
95
97
  return super.createREST(MobileKeyword, '/legacy/v1/beta/mobile/keyword/');
96
98
  }
99
+ /**
100
+ * Updates a single item
101
+ *
102
+ * @param {TYPE.MetadataTypeItem} metadata a single item
103
+ * @returns {Promise} Promise
104
+ */
105
+ static update(metadata) {
106
+ return super.updateREST(
107
+ metadata,
108
+ '/legacy/v1/beta/mobile/keyword/' + metadata[this.definition.idField],
109
+ 'post' // upsert API, post for insert and update!
110
+ );
111
+ }
112
+
113
+ /**
114
+ * manages post retrieve steps
115
+ *
116
+ * @param {TYPE.MetadataTypeItem} metadata a single item
117
+ * @returns {TYPE.CodeExtractItem | TYPE.MetadataTypeItem} Array with one metadata object and one ssjs string
118
+ */
119
+ static postRetrieveTasks(metadata) {
120
+ if (metadata.responseMessage) {
121
+ // extract message body
122
+ const codeArr = [];
123
+ // keep between tags
124
+ const { fileExt, code } = this.prepExtractedCode(metadata.responseMessage);
125
+ delete metadata.responseMessage;
126
+ codeArr.push({
127
+ subFolder: null,
128
+ fileName: metadata[this.definition.keyField],
129
+ fileExt: fileExt,
130
+ content: code,
131
+ });
132
+ return { json: metadata, codeArr: codeArr, subFolder: null };
133
+ } else {
134
+ return metadata;
135
+ }
136
+ }
137
+ /**
138
+ * helper for {@link parseMetadata} and {@link _buildForNested}
139
+ *
140
+ * @param {string} metadataScript the code of the file
141
+ * @returns {{fileExt:string,code:string}} returns found extension and file content
142
+ */
143
+ static prepExtractedCode(metadataScript) {
144
+ const code = metadataScript;
145
+ const fileExt = 'amp';
146
+
147
+ return { fileExt, code };
148
+ }
149
+ /**
150
+ * helper for {@link MetadataType.buildDefinition}
151
+ * handles extracted code if any are found for complex types
152
+ *
153
+ * @param {string} templateDir Directory where metadata templates are stored
154
+ * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved
155
+ * @param {TYPE.MetadataTypeItem} metadata main JSON file that was read from file system
156
+ * @param {TYPE.TemplateMap} templateVariables variables to be replaced in the metadata
157
+ * @param {string} templateName name of the template to be built
158
+ * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array
159
+ */
160
+ static buildDefinitionForNested(
161
+ templateDir,
162
+ targetDir,
163
+ metadata,
164
+ templateVariables,
165
+ templateName
166
+ ) {
167
+ return this._buildForNested(
168
+ templateDir,
169
+ targetDir,
170
+ metadata,
171
+ templateVariables,
172
+ templateName,
173
+ 'definition'
174
+ );
175
+ }
176
+ /**
177
+ * helper for {@link MetadataType.buildTemplate}
178
+ * handles extracted code if any are found for complex types
179
+ *
180
+ * @example scripts are saved as 1 json and 1 ssjs file. both files need to be run through templating
181
+ * @param {string} templateDir Directory where metadata templates are stored
182
+ * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved
183
+ * @param {TYPE.MetadataTypeItem} metadata main JSON file that was read from file system
184
+ * @param {TYPE.TemplateMap} templateVariables variables to be replaced in the metadata
185
+ * @param {string} templateName name of the template to be built
186
+ * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array
187
+ */
188
+ static buildTemplateForNested(
189
+ templateDir,
190
+ targetDir,
191
+ metadata,
192
+ templateVariables,
193
+ templateName
194
+ ) {
195
+ return this._buildForNested(
196
+ templateDir,
197
+ targetDir,
198
+ metadata,
199
+ templateVariables,
200
+ templateName,
201
+ 'template'
202
+ );
203
+ }
204
+
205
+ /**
206
+ * helper for {@link buildTemplateForNested} / {@link buildDefinitionForNested}
207
+ * handles extracted code if any are found for complex types
208
+ *
209
+ * @param {string} templateDir Directory where metadata templates are stored
210
+ * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved
211
+ * @param {TYPE.MetadataTypeItem} metadata main JSON file that was read from file system
212
+ * @param {TYPE.TemplateMap} templateVariables variables to be replaced in the metadata
213
+ * @param {string} templateName name of the template to be built
214
+ * @param {'definition'|'template'} mode defines what we use this helper for
215
+ * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array
216
+ */
217
+ static async _buildForNested(
218
+ templateDir,
219
+ targetDir,
220
+ metadata,
221
+ templateVariables,
222
+ templateName,
223
+ mode
224
+ ) {
225
+ // get code from filesystem
226
+ let code = await this._mergeCode(metadata, templateDir, templateName);
227
+ if (!code) {
228
+ return null;
229
+ }
230
+ const file = this.prepExtractedCode(code, metadata.name);
231
+ const fileExt = file.fileExt;
232
+ code = file.code;
233
+ // apply templating
234
+ try {
235
+ if (mode === 'definition') {
236
+ // replace template variables with their values
237
+ code = this.applyTemplateValues(code, templateVariables);
238
+ } else if (mode === 'template') {
239
+ // replace template values with corresponding variable names
240
+ code = this.applyTemplateNames(code, templateVariables);
241
+ }
242
+ } catch {
243
+ throw new Error(
244
+ `${this.definition.type}:: Error applying template variables on ${
245
+ templateName + '.' + this.definition.type
246
+ }-meta.${fileExt}.`
247
+ );
248
+ }
249
+
250
+ // write to file
251
+ const targetDirArr = Array.isArray(targetDir) ? targetDir : [targetDir];
252
+ const nestedFilePaths = [];
253
+
254
+ // keep old name if creating templates, otherwise use new name
255
+ const fileName = mode === 'definition' ? metadata[this.definition.keyField] : templateName;
256
+
257
+ for (const targetDir of targetDirArr) {
258
+ File.writeToFile(
259
+ [targetDir, this.definition.type],
260
+ fileName + '.' + this.definition.type + '-meta',
261
+ fileExt,
262
+ code
263
+ );
264
+ nestedFilePaths.push([
265
+ targetDir,
266
+ this.definition.type,
267
+ fileName + '.' + this.definition.type + '-meta.' + fileExt,
268
+ ]);
269
+ }
270
+ return nestedFilePaths;
271
+ }
97
272
 
98
273
  /**
99
274
  * prepares an event definition for deployment
100
275
  *
101
276
  * @param {TYPE.MetadataTypeItem} metadata a single MobileKeyword
102
- * @returns {TYPE.MetadataTypeItem} Promise
277
+ * @param {string} deployDir directory of deploy files
278
+ * @returns {Promise.<TYPE.MetadataTypeItem>} Promise
103
279
  */
104
- static preDeployTasks(metadata) {
280
+ static async preDeployTasks(metadata, deployDir) {
281
+ // code
282
+ metadata.responseMessage = await this._mergeCode(metadata, deployDir);
283
+
284
+ if (metadata.responseMessage && metadata.keywordType === 'NORMAL') {
285
+ throw new Error(
286
+ `Custom Response Text is not supported for keywords of type 'NORMAL'. Please remove the .amp file or change the keywordType to 'STOP' or 'INFO'.`
287
+ );
288
+ }
289
+ if (!metadata.companyName && metadata.keywordType !== 'NORMAL') {
290
+ metadata.companyName = 'IGNORED';
291
+ Util.logger.debug(
292
+ ` - No companyName found for keyword ${
293
+ metadata[this.definition.keyField]
294
+ }. Setting to IGNORED.`
295
+ );
296
+ }
297
+
298
+ // mobileCode
105
299
  metadata.code.id = cache.searchForField('mobileCode', metadata.code.code, 'code', 'id');
106
300
  return metadata;
107
301
  }
302
+ /**
303
+ * helper for {@link createREST}
304
+ *
305
+ * @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
306
+ * @param {object} apiResponse varies depending on the API call
307
+ * @returns {void}
308
+ */
309
+ static async postCreateTasks(metadataEntry, apiResponse) {
310
+ await super.postDeployTasks_legacyApi(metadataEntry, apiResponse);
311
+ }
312
+ /**
313
+ * helper for {@link updateREST}
314
+ *
315
+ * @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
316
+ * @param {object} apiResponse varies depending on the API call
317
+ * @returns {void}
318
+ */
319
+ static async postUpdateTasks(metadataEntry, apiResponse) {
320
+ await super.postDeployTasks_legacyApi(metadataEntry, apiResponse);
321
+ }
322
+
323
+ /**
324
+ * helper for {@link preDeployTasks} that loads extracted code content back into JSON
325
+ *
326
+ * @param {TYPE.MetadataTypeItem} metadata a single definition
327
+ * @param {string} deployDir directory of deploy files
328
+ * @param {string} [templateName] name of the template used to built defintion (prior applying templating)
329
+ * @returns {Promise.<string>} content for metadata.script
330
+ */
331
+ static async _mergeCode(metadata, deployDir, templateName) {
332
+ templateName ||= metadata[this.definition.keyField];
333
+ const codePath = File.normalizePath([
334
+ deployDir,
335
+ this.definition.type,
336
+ templateName + '.' + this.definition.type + '-meta',
337
+ ]);
338
+
339
+ if (await File.pathExists(codePath + '.amp')) {
340
+ return await File.readFilteredFilename(
341
+ [deployDir, this.definition.type],
342
+ templateName + '.' + this.definition.type + '-meta',
343
+ 'amp'
344
+ );
345
+ } else {
346
+ // keeep this as a debug message, as it is optional and hence not an error
347
+ Util.logger.debug(`Could not find ${codePath}.amp`);
348
+ return null;
349
+ }
350
+ }
351
+ /**
352
+ * Delete a metadata item from the specified business unit
353
+ *
354
+ * @param {string} key Identifier of item
355
+ * @returns {Promise.<boolean>} deletion success status
356
+ */
357
+ static async deleteByKey(key) {
358
+ // get id from cache
359
+ const { metadata } = await this.retrieveForCache(key);
360
+ if (!metadata[key]) {
361
+ Util.logger.error(`Could not find ${this.definition.type} with key ${key}.`);
362
+ return false;
363
+ }
364
+ const id = metadata[key][this.definition.idField];
365
+ // execute delete
366
+ Util.logger.info(
367
+ ' - Note: As long as the provided API key once existed, you will not see an error even if the mobileKeyword is already deleted.'
368
+ );
369
+ return super.deleteByKeyREST('/legacy/v1/beta/mobile/keyword/' + id, key, false);
370
+ }
371
+
372
+ /**
373
+ * clean up after deleting a metadata item
374
+ *
375
+ * @param {string} customerKey Identifier of metadata item
376
+ * @returns {void}
377
+ */
378
+ static async postDeleteTasks(customerKey) {
379
+ // delete local copy: retrieve/cred/bu/type/...-meta.json
380
+ // delete local copy: retrieve/cred/bu/type/...-meta.amp
381
+ super.postDeleteTasks(customerKey, [`${this.definition.type}-meta.amp`]);
382
+ }
383
+ /**
384
+ * should return only the json for all but asset, query and script that are saved as multiple files
385
+ * additionally, the documentation for dataExtension and automation should be returned
386
+ *
387
+ * @param {string[]} keyArr customerkey of the metadata
388
+ * @returns {string[]} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext']
389
+ */
390
+ static getFilesToCommit(keyArr) {
391
+ const path = File.normalizePath([
392
+ this.properties.directories.retrieve,
393
+ this.buObject.credential,
394
+ this.buObject.businessUnit,
395
+ this.definition.type,
396
+ ]);
397
+
398
+ const fileList = keyArr.flatMap((key) => [
399
+ File.normalizePath([path, `${key}.${this.definition.type}-meta.json`]),
400
+ File.normalizePath([path, `${key}.${this.definition.type}-meta.amp`]),
401
+ ]);
402
+ return fileList;
403
+ }
108
404
  }
109
405
 
110
406
  // Assign definition to static attributes