@metamask/notification-services-controller 21.0.0 → 22.1.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 (193) hide show
  1. package/CHANGELOG.md +41 -1
  2. package/dist/NotificationServicesController/NotificationServicesController.cjs +56 -42
  3. package/dist/NotificationServicesController/NotificationServicesController.cjs.map +1 -1
  4. package/dist/NotificationServicesController/NotificationServicesController.d.cts +3 -2
  5. package/dist/NotificationServicesController/NotificationServicesController.d.cts.map +1 -1
  6. package/dist/NotificationServicesController/NotificationServicesController.d.mts +3 -2
  7. package/dist/NotificationServicesController/NotificationServicesController.d.mts.map +1 -1
  8. package/dist/NotificationServicesController/NotificationServicesController.mjs +56 -41
  9. package/dist/NotificationServicesController/NotificationServicesController.mjs.map +1 -1
  10. package/dist/NotificationServicesController/constants/notification-schema.cjs +4 -12
  11. package/dist/NotificationServicesController/constants/notification-schema.cjs.map +1 -1
  12. package/dist/NotificationServicesController/constants/notification-schema.d.cts +0 -12
  13. package/dist/NotificationServicesController/constants/notification-schema.d.cts.map +1 -1
  14. package/dist/NotificationServicesController/constants/notification-schema.d.mts +0 -12
  15. package/dist/NotificationServicesController/constants/notification-schema.d.mts.map +1 -1
  16. package/dist/NotificationServicesController/constants/notification-schema.mjs +3 -11
  17. package/dist/NotificationServicesController/constants/notification-schema.mjs.map +1 -1
  18. package/dist/NotificationServicesController/index.cjs +1 -2
  19. package/dist/NotificationServicesController/index.cjs.map +1 -1
  20. package/dist/NotificationServicesController/index.d.cts +0 -1
  21. package/dist/NotificationServicesController/index.d.cts.map +1 -1
  22. package/dist/NotificationServicesController/index.d.mts +0 -1
  23. package/dist/NotificationServicesController/index.d.mts.map +1 -1
  24. package/dist/NotificationServicesController/index.mjs +0 -1
  25. package/dist/NotificationServicesController/index.mjs.map +1 -1
  26. package/dist/NotificationServicesController/mocks/mock-feature-announcements.cjs +2 -2
  27. package/dist/NotificationServicesController/mocks/mock-feature-announcements.cjs.map +1 -1
  28. package/dist/NotificationServicesController/mocks/mock-feature-announcements.d.cts.map +1 -1
  29. package/dist/NotificationServicesController/mocks/mock-feature-announcements.d.mts.map +1 -1
  30. package/dist/NotificationServicesController/mocks/mock-feature-announcements.mjs +2 -2
  31. package/dist/NotificationServicesController/mocks/mock-feature-announcements.mjs.map +1 -1
  32. package/dist/NotificationServicesController/mocks/mock-raw-notifications.cjs +120 -0
  33. package/dist/NotificationServicesController/mocks/mock-raw-notifications.cjs.map +1 -1
  34. package/dist/NotificationServicesController/mocks/mock-raw-notifications.d.cts.map +1 -1
  35. package/dist/NotificationServicesController/mocks/mock-raw-notifications.d.mts.map +1 -1
  36. package/dist/NotificationServicesController/mocks/mock-raw-notifications.mjs +120 -0
  37. package/dist/NotificationServicesController/mocks/mock-raw-notifications.mjs.map +1 -1
  38. package/dist/NotificationServicesController/mocks/mock-snap-notification.cjs.map +1 -1
  39. package/dist/NotificationServicesController/mocks/mock-snap-notification.d.cts +1 -1
  40. package/dist/NotificationServicesController/mocks/mock-snap-notification.d.cts.map +1 -1
  41. package/dist/NotificationServicesController/mocks/mock-snap-notification.d.mts +1 -1
  42. package/dist/NotificationServicesController/mocks/mock-snap-notification.d.mts.map +1 -1
  43. package/dist/NotificationServicesController/mocks/mock-snap-notification.mjs.map +1 -1
  44. package/dist/NotificationServicesController/mocks/mockResponses.cjs +6 -0
  45. package/dist/NotificationServicesController/mocks/mockResponses.cjs.map +1 -1
  46. package/dist/NotificationServicesController/mocks/mockResponses.d.cts.map +1 -1
  47. package/dist/NotificationServicesController/mocks/mockResponses.d.mts.map +1 -1
  48. package/dist/NotificationServicesController/mocks/mockResponses.mjs +6 -0
  49. package/dist/NotificationServicesController/mocks/mockResponses.mjs.map +1 -1
  50. package/dist/NotificationServicesController/processors/process-notifications.cjs +11 -9
  51. package/dist/NotificationServicesController/processors/process-notifications.cjs.map +1 -1
  52. package/dist/NotificationServicesController/processors/process-notifications.d.cts +1 -563
  53. package/dist/NotificationServicesController/processors/process-notifications.d.cts.map +1 -1
  54. package/dist/NotificationServicesController/processors/process-notifications.d.mts +1 -563
  55. package/dist/NotificationServicesController/processors/process-notifications.d.mts.map +1 -1
  56. package/dist/NotificationServicesController/processors/process-notifications.mjs +11 -9
  57. package/dist/NotificationServicesController/processors/process-notifications.mjs.map +1 -1
  58. package/dist/NotificationServicesController/processors/process-snap-notifications.cjs.map +1 -1
  59. package/dist/NotificationServicesController/processors/process-snap-notifications.d.cts +1 -1
  60. package/dist/NotificationServicesController/processors/process-snap-notifications.d.cts.map +1 -1
  61. package/dist/NotificationServicesController/processors/process-snap-notifications.d.mts +1 -1
  62. package/dist/NotificationServicesController/processors/process-snap-notifications.d.mts.map +1 -1
  63. package/dist/NotificationServicesController/processors/process-snap-notifications.mjs.map +1 -1
  64. package/dist/NotificationServicesController/services/api-notifications.cjs +21 -21
  65. package/dist/NotificationServicesController/services/api-notifications.cjs.map +1 -1
  66. package/dist/NotificationServicesController/services/api-notifications.d.cts.map +1 -1
  67. package/dist/NotificationServicesController/services/api-notifications.d.mts.map +1 -1
  68. package/dist/NotificationServicesController/services/api-notifications.mjs +21 -21
  69. package/dist/NotificationServicesController/services/api-notifications.mjs.map +1 -1
  70. package/dist/NotificationServicesController/services/feature-announcements.cjs +19 -10
  71. package/dist/NotificationServicesController/services/feature-announcements.cjs.map +1 -1
  72. package/dist/NotificationServicesController/services/feature-announcements.d.cts.map +1 -1
  73. package/dist/NotificationServicesController/services/feature-announcements.d.mts.map +1 -1
  74. package/dist/NotificationServicesController/services/feature-announcements.mjs +19 -10
  75. package/dist/NotificationServicesController/services/feature-announcements.mjs.map +1 -1
  76. package/dist/NotificationServicesController/services/notification-config-cache.cjs +4 -4
  77. package/dist/NotificationServicesController/services/notification-config-cache.cjs.map +1 -1
  78. package/dist/NotificationServicesController/services/notification-config-cache.mjs +4 -4
  79. package/dist/NotificationServicesController/services/notification-config-cache.mjs.map +1 -1
  80. package/dist/NotificationServicesController/services/perp-notifications.cjs +2 -2
  81. package/dist/NotificationServicesController/services/perp-notifications.cjs.map +1 -1
  82. package/dist/NotificationServicesController/services/perp-notifications.d.cts.map +1 -1
  83. package/dist/NotificationServicesController/services/perp-notifications.d.mts.map +1 -1
  84. package/dist/NotificationServicesController/services/perp-notifications.mjs +2 -2
  85. package/dist/NotificationServicesController/services/perp-notifications.mjs.map +1 -1
  86. package/dist/NotificationServicesController/types/notification-api/notification-api.cjs.map +1 -1
  87. package/dist/NotificationServicesController/types/notification-api/notification-api.d.cts +2 -0
  88. package/dist/NotificationServicesController/types/notification-api/notification-api.d.cts.map +1 -1
  89. package/dist/NotificationServicesController/types/notification-api/notification-api.d.mts +2 -0
  90. package/dist/NotificationServicesController/types/notification-api/notification-api.d.mts.map +1 -1
  91. package/dist/NotificationServicesController/types/notification-api/notification-api.mjs.map +1 -1
  92. package/dist/NotificationServicesController/types/notification-api/schema.cjs +2 -0
  93. package/dist/NotificationServicesController/types/notification-api/schema.cjs.map +1 -1
  94. package/dist/NotificationServicesController/types/notification-api/schema.d.cts +23 -0
  95. package/dist/NotificationServicesController/types/notification-api/schema.d.cts.map +1 -1
  96. package/dist/NotificationServicesController/types/notification-api/schema.d.mts +23 -0
  97. package/dist/NotificationServicesController/types/notification-api/schema.d.mts.map +1 -1
  98. package/dist/NotificationServicesController/types/notification-api/schema.mjs +2 -0
  99. package/dist/NotificationServicesController/types/notification-api/schema.mjs.map +1 -1
  100. package/dist/NotificationServicesController/types/perps/schema.cjs +2 -0
  101. package/dist/NotificationServicesController/types/perps/schema.cjs.map +1 -1
  102. package/dist/NotificationServicesController/types/perps/schema.d.cts.map +1 -1
  103. package/dist/NotificationServicesController/types/perps/schema.d.mts.map +1 -1
  104. package/dist/NotificationServicesController/types/perps/schema.mjs +2 -0
  105. package/dist/NotificationServicesController/types/perps/schema.mjs.map +1 -1
  106. package/dist/NotificationServicesController/utils/isVersionInBounds.cjs.map +1 -1
  107. package/dist/NotificationServicesController/utils/isVersionInBounds.d.cts.map +1 -1
  108. package/dist/NotificationServicesController/utils/isVersionInBounds.d.mts.map +1 -1
  109. package/dist/NotificationServicesController/utils/isVersionInBounds.mjs.map +1 -1
  110. package/dist/NotificationServicesController/utils/should-auto-expire.cjs.map +1 -1
  111. package/dist/NotificationServicesController/utils/should-auto-expire.d.cts.map +1 -1
  112. package/dist/NotificationServicesController/utils/should-auto-expire.d.mts.map +1 -1
  113. package/dist/NotificationServicesController/utils/should-auto-expire.mjs.map +1 -1
  114. package/dist/NotificationServicesPushController/NotificationServicesPushController.cjs +0 -1
  115. package/dist/NotificationServicesPushController/NotificationServicesPushController.cjs.map +1 -1
  116. package/dist/NotificationServicesPushController/NotificationServicesPushController.d.cts +1 -1
  117. package/dist/NotificationServicesPushController/NotificationServicesPushController.d.cts.map +1 -1
  118. package/dist/NotificationServicesPushController/NotificationServicesPushController.d.mts +1 -1
  119. package/dist/NotificationServicesPushController/NotificationServicesPushController.d.mts.map +1 -1
  120. package/dist/NotificationServicesPushController/NotificationServicesPushController.mjs +0 -1
  121. package/dist/NotificationServicesPushController/NotificationServicesPushController.mjs.map +1 -1
  122. package/dist/NotificationServicesPushController/mocks/mockResponse.cjs.map +1 -1
  123. package/dist/NotificationServicesPushController/mocks/mockResponse.d.cts +9 -24
  124. package/dist/NotificationServicesPushController/mocks/mockResponse.d.cts.map +1 -1
  125. package/dist/NotificationServicesPushController/mocks/mockResponse.d.mts +9 -24
  126. package/dist/NotificationServicesPushController/mocks/mockResponse.d.mts.map +1 -1
  127. package/dist/NotificationServicesPushController/mocks/mockResponse.mjs.map +1 -1
  128. package/dist/NotificationServicesPushController/services/endpoints.cjs.map +1 -1
  129. package/dist/NotificationServicesPushController/services/endpoints.d.cts.map +1 -1
  130. package/dist/NotificationServicesPushController/services/endpoints.d.mts.map +1 -1
  131. package/dist/NotificationServicesPushController/services/endpoints.mjs.map +1 -1
  132. package/dist/NotificationServicesPushController/services/services.cjs.map +1 -1
  133. package/dist/NotificationServicesPushController/services/services.d.cts.map +1 -1
  134. package/dist/NotificationServicesPushController/services/services.d.mts.map +1 -1
  135. package/dist/NotificationServicesPushController/services/services.mjs.map +1 -1
  136. package/dist/NotificationServicesPushController/utils/get-notification-data.cjs +4 -4
  137. package/dist/NotificationServicesPushController/utils/get-notification-data.cjs.map +1 -1
  138. package/dist/NotificationServicesPushController/utils/get-notification-data.d.cts +2 -2
  139. package/dist/NotificationServicesPushController/utils/get-notification-data.d.cts.map +1 -1
  140. package/dist/NotificationServicesPushController/utils/get-notification-data.d.mts +2 -2
  141. package/dist/NotificationServicesPushController/utils/get-notification-data.d.mts.map +1 -1
  142. package/dist/NotificationServicesPushController/utils/get-notification-data.mjs +4 -4
  143. package/dist/NotificationServicesPushController/utils/get-notification-data.mjs.map +1 -1
  144. package/dist/NotificationServicesPushController/utils/get-notification-message.cjs +62 -71
  145. package/dist/NotificationServicesPushController/utils/get-notification-message.cjs.map +1 -1
  146. package/dist/NotificationServicesPushController/utils/get-notification-message.d.cts +9 -9
  147. package/dist/NotificationServicesPushController/utils/get-notification-message.d.cts.map +1 -1
  148. package/dist/NotificationServicesPushController/utils/get-notification-message.d.mts +9 -9
  149. package/dist/NotificationServicesPushController/utils/get-notification-message.d.mts.map +1 -1
  150. package/dist/NotificationServicesPushController/utils/get-notification-message.mjs +62 -71
  151. package/dist/NotificationServicesPushController/utils/get-notification-message.mjs.map +1 -1
  152. package/dist/NotificationServicesPushController/web/push-utils.cjs +15 -7
  153. package/dist/NotificationServicesPushController/web/push-utils.cjs.map +1 -1
  154. package/dist/NotificationServicesPushController/web/push-utils.d.cts.map +1 -1
  155. package/dist/NotificationServicesPushController/web/push-utils.d.mts.map +1 -1
  156. package/dist/NotificationServicesPushController/web/push-utils.mjs +16 -8
  157. package/dist/NotificationServicesPushController/web/push-utils.mjs.map +1 -1
  158. package/dist/shared/is-onchain-notification.cjs +3 -3
  159. package/dist/shared/is-onchain-notification.cjs.map +1 -1
  160. package/dist/shared/is-onchain-notification.d.cts +2 -2
  161. package/dist/shared/is-onchain-notification.d.cts.map +1 -1
  162. package/dist/shared/is-onchain-notification.d.mts +2 -2
  163. package/dist/shared/is-onchain-notification.d.mts.map +1 -1
  164. package/dist/shared/is-onchain-notification.mjs +3 -3
  165. package/dist/shared/is-onchain-notification.mjs.map +1 -1
  166. package/dist/shared/to-raw-notification.cjs.map +1 -1
  167. package/dist/shared/to-raw-notification.mjs.map +1 -1
  168. package/package.json +12 -25
  169. package/dist/NotificationServicesController/ui/constants.cjs +0 -75
  170. package/dist/NotificationServicesController/ui/constants.cjs.map +0 -1
  171. package/dist/NotificationServicesController/ui/constants.d.cts +0 -66
  172. package/dist/NotificationServicesController/ui/constants.d.cts.map +0 -1
  173. package/dist/NotificationServicesController/ui/constants.d.mts +0 -66
  174. package/dist/NotificationServicesController/ui/constants.d.mts.map +0 -1
  175. package/dist/NotificationServicesController/ui/constants.mjs +0 -71
  176. package/dist/NotificationServicesController/ui/constants.mjs.map +0 -1
  177. package/dist/NotificationServicesController/ui/index.cjs +0 -18
  178. package/dist/NotificationServicesController/ui/index.cjs.map +0 -1
  179. package/dist/NotificationServicesController/ui/index.d.cts +0 -2
  180. package/dist/NotificationServicesController/ui/index.d.cts.map +0 -1
  181. package/dist/NotificationServicesController/ui/index.d.mts +0 -2
  182. package/dist/NotificationServicesController/ui/index.d.mts.map +0 -1
  183. package/dist/NotificationServicesController/ui/index.mjs +0 -2
  184. package/dist/NotificationServicesController/ui/index.mjs.map +0 -1
  185. package/dist/NotificationServicesPushController/services/push/push-web.cjs +0 -145
  186. package/dist/NotificationServicesPushController/services/push/push-web.cjs.map +0 -1
  187. package/dist/NotificationServicesPushController/services/push/push-web.d.cts +0 -34
  188. package/dist/NotificationServicesPushController/services/push/push-web.d.cts.map +0 -1
  189. package/dist/NotificationServicesPushController/services/push/push-web.d.mts +0 -34
  190. package/dist/NotificationServicesPushController/services/push/push-web.d.mts.map +0 -1
  191. package/dist/NotificationServicesPushController/services/push/push-web.mjs +0 -142
  192. package/dist/NotificationServicesPushController/services/push/push-web.mjs.map +0 -1
  193. package/notification-services/ui/package.json +0 -9
@@ -1 +1 @@
1
- {"version":3,"file":"process-snap-notifications.mjs","sourceRoot":"","sources":["../../../src/NotificationServicesController/processors/process-snap-notifications.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,aAAa;AAKlC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,gBAAqC,EACtB,EAAE;IACjB,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC;IAClD,OAAO;QACL,EAAE,EAAE,IAAI,EAAE;QACV,QAAQ;QACR,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,MAAM,EAAE,KAAK;QACb,IAAI;QACJ,IAAI;KACL,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { v4 as uuid } from 'uuid';\n\nimport { type INotification } from '../types';\nimport type { RawSnapNotification } from '../types/snaps';\n\n/**\n * Processes a snap notification into a normalized shape.\n *\n * @param snapNotification - A raw snap notification.\n * @returns a normalized snap notification.\n */\nexport const processSnapNotification = (\n snapNotification: RawSnapNotification,\n): INotification => {\n const { data, type, readDate } = snapNotification;\n return {\n id: uuid(),\n readDate,\n createdAt: new Date().toISOString(),\n isRead: false,\n type,\n data,\n };\n};\n"]}
1
+ {"version":3,"file":"process-snap-notifications.mjs","sourceRoot":"","sources":["../../../src/NotificationServicesController/processors/process-snap-notifications.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,aAAa;AAKlC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,gBAAqC,EACtB,EAAE;IACjB,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC;IAClD,OAAO;QACL,EAAE,EAAE,IAAI,EAAE;QACV,QAAQ;QACR,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,MAAM,EAAE,KAAK;QACb,IAAI;QACJ,IAAI;KACL,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { v4 as uuid } from 'uuid';\n\nimport type { INotification } from '../types';\nimport type { RawSnapNotification } from '../types/snaps';\n\n/**\n * Processes a snap notification into a normalized shape.\n *\n * @param snapNotification - A raw snap notification.\n * @returns a normalized snap notification.\n */\nexport const processSnapNotification = (\n snapNotification: RawSnapNotification,\n): INotification => {\n const { data, type, readDate } = snapNotification;\n return {\n id: uuid(),\n readDate,\n createdAt: new Date().toISOString(),\n isRead: false,\n type,\n data,\n };\n};\n"]}
@@ -31,7 +31,7 @@ exports.TRIGGER_API_NOTIFICATIONS_ENDPOINT = TRIGGER_API_NOTIFICATIONS_ENDPOINT;
31
31
  // Lists notifications for each account provided
32
32
  const NOTIFICATION_API_LIST_ENDPOINT = (env = 'prd') => `${(0, exports.NOTIFICATION_API)(env)}/api/v3/notifications`;
33
33
  exports.NOTIFICATION_API_LIST_ENDPOINT = NOTIFICATION_API_LIST_ENDPOINT;
34
- // Makrs notifications as read
34
+ // Marks notifications as read
35
35
  const NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = (env = 'prd') => `${(0, exports.NOTIFICATION_API)(env)}/api/v3/notifications/mark-as-read`;
36
36
  exports.NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT;
37
37
  /**
@@ -48,16 +48,16 @@ async function getNotificationsApiConfigCached(bearerToken, addresses, env = 'pr
48
48
  if (addresses.length === 0) {
49
49
  return [];
50
50
  }
51
- addresses = addresses.map((a) => a.toLowerCase());
52
- const cached = notification_config_cache_1.notificationsConfigCache.get(addresses);
51
+ const normalizedAddresses = addresses.map((addr) => addr.toLowerCase());
52
+ const cached = notification_config_cache_1.notificationsConfigCache.get(normalizedAddresses);
53
53
  if (cached) {
54
54
  return cached;
55
55
  }
56
- const body = addresses.map((address) => ({ address }));
57
- const data = await (0, utils_1.makeApiCall)(bearerToken, (0, exports.TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT)(env), 'POST', body)
58
- .then((r) => (r.ok ? r.json() : null))
56
+ const body = normalizedAddresses.map((address) => ({ address }));
57
+ const apiResponse = await (0, utils_1.makeApiCall)(bearerToken, (0, exports.TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT)(env), 'POST', body)
58
+ .then((response) => (response.ok ? response.json() : null))
59
59
  .catch(() => null);
60
- const result = data ?? [];
60
+ const result = apiResponse ?? [];
61
61
  if (result.length > 0) {
62
62
  notification_config_cache_1.notificationsConfigCache.set(result);
63
63
  }
@@ -76,13 +76,13 @@ async function updateOnChainNotifications(bearerToken, addresses, env = 'prd') {
76
76
  if (addresses.length === 0) {
77
77
  return;
78
78
  }
79
- addresses = addresses.map((a) => {
80
- a.address = a.address.toLowerCase();
81
- return a;
82
- });
83
- const body = addresses;
79
+ const normalizedAddresses = addresses.map((item) => ({
80
+ ...item,
81
+ address: item.address.toLowerCase(),
82
+ }));
83
+ const body = normalizedAddresses;
84
84
  await (0, utils_1.makeApiCall)(bearerToken, (0, exports.TRIGGER_API_NOTIFICATIONS_ENDPOINT)(env), 'POST', body)
85
- .then(() => notification_config_cache_1.notificationsConfigCache.set(addresses))
85
+ .then(() => notification_config_cache_1.notificationsConfigCache.set(normalizedAddresses))
86
86
  .catch(() => null);
87
87
  }
88
88
  exports.updateOnChainNotifications = updateOnChainNotifications;
@@ -101,27 +101,27 @@ async function getAPINotifications(bearerToken, addresses, locale, platform, env
101
101
  return [];
102
102
  }
103
103
  const body = {
104
- addresses: addresses.map((a) => a.toLowerCase()),
104
+ addresses: addresses.map((addr) => addr.toLowerCase()),
105
105
  locale,
106
106
  platform,
107
107
  };
108
108
  const notifications = await (0, utils_1.makeApiCall)(bearerToken, (0, exports.NOTIFICATION_API_LIST_ENDPOINT)(env), 'POST', body)
109
- .then((r) => (r.ok ? r.json() : null))
109
+ .then((response) => response.ok ? response.json() : null)
110
110
  .catch(() => null);
111
111
  // Transform and sort notifications
112
112
  const transformedNotifications = notifications
113
- ?.map((n) => {
114
- if (!n.notification_type) {
113
+ ?.map((notification) => {
114
+ if (!notification.notification_type) {
115
115
  return undefined;
116
116
  }
117
117
  try {
118
- return (0, to_raw_notification_1.toRawAPINotification)(n);
118
+ return (0, to_raw_notification_1.toRawAPINotification)(notification);
119
119
  }
120
120
  catch {
121
121
  return undefined;
122
122
  }
123
123
  })
124
- .filter((n) => Boolean(n));
124
+ .filter((item) => Boolean(item));
125
125
  return transformedNotifications ?? [];
126
126
  }
127
127
  exports.getAPINotifications = getAPINotifications;
@@ -145,8 +145,8 @@ async function markNotificationsAsRead(bearerToken, notificationIds, env = 'prd'
145
145
  try {
146
146
  await (0, utils_1.makeApiCall)(bearerToken, (0, exports.NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT)(env), 'POST', body);
147
147
  }
148
- catch (err) {
149
- loglevel_1.default.error('Error marking notifications as read:', err);
148
+ catch (error) {
149
+ loglevel_1.default.error('Error marking notifications as read:', error);
150
150
  }
151
151
  }
152
152
  exports.markNotificationsAsRead = markNotificationsAsRead;
@@ -1 +1 @@
1
- {"version":3,"file":"api-notifications.cjs","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/api-notifications.ts"],"names":[],"mappings":"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","sourcesContent":["import log from 'loglevel';\n\nimport { notificationsConfigCache } from './notification-config-cache';\nimport { toRawAPINotification } from '../../shared/to-raw-notification';\nimport type {\n NormalisedAPINotification,\n Schema,\n UnprocessedRawNotification,\n} from '../types/notification-api';\nimport { makeApiCall } from '../utils/utils';\n\nexport type NotificationTrigger = {\n id: string;\n chainId: string;\n kind: string;\n address: string;\n};\n\nexport type ENV = 'prd' | 'uat' | 'dev';\n\nconst TRIGGER_API_ENV = {\n dev: 'https://trigger.dev-api.cx.metamask.io',\n uat: 'https://trigger.uat-api.cx.metamask.io',\n prd: 'https://trigger.api.cx.metamask.io',\n} satisfies Record<ENV, string>;\n\nexport const TRIGGER_API = (env: ENV = 'prd') =>\n TRIGGER_API_ENV[env] ?? TRIGGER_API_ENV.prd;\n\nconst NOTIFICATION_API_ENV = {\n dev: 'https://notification.dev-api.cx.metamask.io',\n uat: 'https://notification.uat-api.cx.metamask.io',\n prd: 'https://notification.api.cx.metamask.io',\n};\n\nexport const NOTIFICATION_API = (env: ENV = 'prd') =>\n NOTIFICATION_API_ENV[env] ?? NOTIFICATION_API_ENV.prd;\n\n// Gets notification settings for each account provided\nexport const TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT = (env: ENV = 'prd') =>\n `${TRIGGER_API(env)}/api/v2/notifications/query`;\n\n// Used to create/update account notifications for each account provided\nexport const TRIGGER_API_NOTIFICATIONS_ENDPOINT = (env: ENV = 'prd') =>\n `${TRIGGER_API(env)}/api/v2/notifications`;\n\n// Lists notifications for each account provided\nexport const NOTIFICATION_API_LIST_ENDPOINT = (env: ENV = 'prd') =>\n `${NOTIFICATION_API(env)}/api/v3/notifications`;\n\n// Makrs notifications as read\nexport const NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = (env: ENV = 'prd') =>\n `${NOTIFICATION_API(env)}/api/v3/notifications/mark-as-read`;\n\n/**\n * fetches notification config (accounts enabled vs disabled)\n *\n * @param bearerToken - jwt\n * @param addresses - list of addresses to check\n * @param env - the environment to use for the API call\n * NOTE the API will return addresses config with false if they have not been created before.\n * NOTE this is cached for 1s to prevent multiple update calls\n * @returns object of notification config, or null if missing\n */\nexport async function getNotificationsApiConfigCached(\n bearerToken: string,\n addresses: string[],\n env: ENV = 'prd',\n) {\n if (addresses.length === 0) {\n return [];\n }\n\n addresses = addresses.map((a) => a.toLowerCase());\n\n const cached = notificationsConfigCache.get(addresses);\n if (cached) {\n return cached;\n }\n\n type RequestBody = { address: string }[];\n type Response = { address: string; enabled: boolean }[];\n const body: RequestBody = addresses.map((address) => ({ address }));\n const data = await makeApiCall(\n bearerToken,\n TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT(env),\n 'POST',\n body,\n )\n .then<Response | null>((r) => (r.ok ? r.json() : null))\n .catch(() => null);\n\n const result = data ?? [];\n\n if (result.length > 0) {\n notificationsConfigCache.set(result);\n }\n\n return result;\n}\n\n/**\n * updates notifications for a given addresses\n *\n * @param bearerToken - jwt\n * @param addresses - list of addresses to check\n * @param env - the environment to use for the API call\n * @returns void\n */\nexport async function updateOnChainNotifications(\n bearerToken: string,\n addresses: { address: string; enabled: boolean }[],\n env: ENV = 'prd',\n) {\n if (addresses.length === 0) {\n return;\n }\n\n addresses = addresses.map((a) => {\n a.address = a.address.toLowerCase();\n return a;\n });\n\n type RequestBody = { address: string; enabled: boolean }[];\n const body: RequestBody = addresses;\n await makeApiCall(\n bearerToken,\n TRIGGER_API_NOTIFICATIONS_ENDPOINT(env),\n 'POST',\n body,\n )\n .then(() => notificationsConfigCache.set(addresses))\n .catch(() => null);\n}\n\n/**\n * Fetches on-chain notifications for the given addresses\n *\n * @param bearerToken - The JSON Web Token used for authentication in the API call.\n * @param addresses - List of addresses\n * @param locale - to generate translated notifications\n * @param platform - filter notifications for specific platforms ('extension' | 'mobile')\n * @param env - the environment to use for the API call\n * @returns A promise that resolves to an array of NormalisedAPINotification objects. If no notifications are enabled or an error occurs, it may return an empty array.\n */\nexport async function getAPINotifications(\n bearerToken: string,\n addresses: string[],\n locale: string,\n platform: 'extension' | 'mobile',\n env: ENV = 'prd',\n): Promise<NormalisedAPINotification[]> {\n if (addresses.length === 0) {\n return [];\n }\n\n type RequestBody =\n Schema.paths['/api/v3/notifications']['post']['requestBody']['content']['application/json'];\n type APIResponse =\n Schema.paths['/api/v3/notifications']['post']['responses']['200']['content']['application/json'];\n\n const body: RequestBody = {\n addresses: addresses.map((a) => a.toLowerCase()),\n locale,\n platform,\n };\n const notifications = await makeApiCall(\n bearerToken,\n NOTIFICATION_API_LIST_ENDPOINT(env),\n 'POST',\n body,\n )\n .then<APIResponse | null>((r) => (r.ok ? r.json() : null))\n .catch(() => null);\n\n // Transform and sort notifications\n const transformedNotifications = notifications\n ?.map((n): UnprocessedRawNotification | undefined => {\n if (!n.notification_type) {\n return undefined;\n }\n\n try {\n return toRawAPINotification(n);\n } catch {\n return undefined;\n }\n })\n .filter((n): n is NormalisedAPINotification => Boolean(n));\n\n return transformedNotifications ?? [];\n}\n\n/**\n * Marks the specified notifications as read.\n * This method sends a POST request to the notifications service to mark the provided notification IDs as read.\n * If the operation is successful, it completes without error. If the operation fails, it throws an error with details.\n *\n * @param bearerToken - The JSON Web Token used for authentication in the API call.\n * @param notificationIds - An array of notification IDs to be marked as read.\n * @param env - the environment to use for the API call\n * @returns A promise that resolves to void. The promise will reject if there's an error during the API call or if the response status is not 200.\n */\nexport async function markNotificationsAsRead(\n bearerToken: string,\n notificationIds: string[],\n env: ENV = 'prd',\n): Promise<void> {\n if (notificationIds.length === 0) {\n return;\n }\n\n type ResponseBody =\n Schema.paths['/api/v3/notifications/mark-as-read']['post']['requestBody']['content']['application/json'];\n const body: ResponseBody = {\n ids: notificationIds,\n };\n\n try {\n await makeApiCall(\n bearerToken,\n NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT(env),\n 'POST',\n body,\n );\n } catch (err) {\n log.error('Error marking notifications as read:', err);\n }\n}\n"]}
1
+ {"version":3,"file":"api-notifications.cjs","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/api-notifications.ts"],"names":[],"mappings":"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","sourcesContent":["import log from 'loglevel';\n\nimport { notificationsConfigCache } from './notification-config-cache';\nimport { toRawAPINotification } from '../../shared/to-raw-notification';\nimport type {\n NormalisedAPINotification,\n Schema,\n UnprocessedRawNotification,\n} from '../types/notification-api';\nimport { makeApiCall } from '../utils/utils';\n\nexport type NotificationTrigger = {\n id: string;\n chainId: string;\n kind: string;\n address: string;\n};\n\nexport type ENV = 'prd' | 'uat' | 'dev';\n\nconst TRIGGER_API_ENV = {\n dev: 'https://trigger.dev-api.cx.metamask.io',\n uat: 'https://trigger.uat-api.cx.metamask.io',\n prd: 'https://trigger.api.cx.metamask.io',\n} satisfies Record<ENV, string>;\n\nexport const TRIGGER_API = (env: ENV = 'prd'): string =>\n TRIGGER_API_ENV[env] ?? TRIGGER_API_ENV.prd;\n\nconst NOTIFICATION_API_ENV = {\n dev: 'https://notification.dev-api.cx.metamask.io',\n uat: 'https://notification.uat-api.cx.metamask.io',\n prd: 'https://notification.api.cx.metamask.io',\n};\n\nexport const NOTIFICATION_API = (env: ENV = 'prd'): string =>\n NOTIFICATION_API_ENV[env] ?? NOTIFICATION_API_ENV.prd;\n\n// Gets notification settings for each account provided\nexport const TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT = (\n env: ENV = 'prd',\n): string => `${TRIGGER_API(env)}/api/v2/notifications/query`;\n\n// Used to create/update account notifications for each account provided\nexport const TRIGGER_API_NOTIFICATIONS_ENDPOINT = (env: ENV = 'prd'): string =>\n `${TRIGGER_API(env)}/api/v2/notifications`;\n\n// Lists notifications for each account provided\nexport const NOTIFICATION_API_LIST_ENDPOINT = (env: ENV = 'prd'): string =>\n `${NOTIFICATION_API(env)}/api/v3/notifications`;\n\n// Marks notifications as read\nexport const NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = (\n env: ENV = 'prd',\n): string => `${NOTIFICATION_API(env)}/api/v3/notifications/mark-as-read`;\n\n/**\n * fetches notification config (accounts enabled vs disabled)\n *\n * @param bearerToken - jwt\n * @param addresses - list of addresses to check\n * @param env - the environment to use for the API call\n * NOTE the API will return addresses config with false if they have not been created before.\n * NOTE this is cached for 1s to prevent multiple update calls\n * @returns object of notification config, or null if missing\n */\nexport async function getNotificationsApiConfigCached(\n bearerToken: string,\n addresses: string[],\n env: ENV = 'prd',\n): Promise<{ address: string; enabled: boolean }[]> {\n if (addresses.length === 0) {\n return [];\n }\n\n const normalizedAddresses = addresses.map((addr) => addr.toLowerCase());\n\n const cached = notificationsConfigCache.get(normalizedAddresses);\n if (cached) {\n return cached;\n }\n\n type RequestBody = { address: string }[];\n type Response = { address: string; enabled: boolean }[];\n const body: RequestBody = normalizedAddresses.map((address) => ({ address }));\n const apiResponse = await makeApiCall(\n bearerToken,\n TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT(env),\n 'POST',\n body,\n )\n .then<Response | null>((response) => (response.ok ? response.json() : null))\n .catch(() => null);\n\n const result = apiResponse ?? [];\n\n if (result.length > 0) {\n notificationsConfigCache.set(result);\n }\n\n return result;\n}\n\n/**\n * updates notifications for a given addresses\n *\n * @param bearerToken - jwt\n * @param addresses - list of addresses to check\n * @param env - the environment to use for the API call\n * @returns void\n */\nexport async function updateOnChainNotifications(\n bearerToken: string,\n addresses: { address: string; enabled: boolean }[],\n env: ENV = 'prd',\n): Promise<void> {\n if (addresses.length === 0) {\n return;\n }\n\n const normalizedAddresses = addresses.map((item) => ({\n ...item,\n address: item.address.toLowerCase(),\n }));\n\n type RequestBody = { address: string; enabled: boolean }[];\n const body: RequestBody = normalizedAddresses;\n await makeApiCall(\n bearerToken,\n TRIGGER_API_NOTIFICATIONS_ENDPOINT(env),\n 'POST',\n body,\n )\n .then(() => notificationsConfigCache.set(normalizedAddresses))\n .catch(() => null);\n}\n\n/**\n * Fetches on-chain notifications for the given addresses\n *\n * @param bearerToken - The JSON Web Token used for authentication in the API call.\n * @param addresses - List of addresses\n * @param locale - to generate translated notifications\n * @param platform - filter notifications for specific platforms ('extension' | 'mobile')\n * @param env - the environment to use for the API call\n * @returns A promise that resolves to an array of NormalisedAPINotification objects. If no notifications are enabled or an error occurs, it may return an empty array.\n */\nexport async function getAPINotifications(\n bearerToken: string,\n addresses: string[],\n locale: string,\n platform: 'extension' | 'mobile',\n env: ENV = 'prd',\n): Promise<NormalisedAPINotification[]> {\n if (addresses.length === 0) {\n return [];\n }\n\n type RequestBody =\n Schema.paths['/api/v3/notifications']['post']['requestBody']['content']['application/json'];\n type APIResponse =\n Schema.paths['/api/v3/notifications']['post']['responses']['200']['content']['application/json'];\n\n const body: RequestBody = {\n addresses: addresses.map((addr) => addr.toLowerCase()),\n locale,\n platform,\n };\n const notifications = await makeApiCall(\n bearerToken,\n NOTIFICATION_API_LIST_ENDPOINT(env),\n 'POST',\n body,\n )\n .then<APIResponse | null>((response) =>\n response.ok ? response.json() : null,\n )\n .catch(() => null);\n\n // Transform and sort notifications\n const transformedNotifications = notifications\n ?.map((notification): UnprocessedRawNotification | undefined => {\n if (!notification.notification_type) {\n return undefined;\n }\n\n try {\n return toRawAPINotification(notification);\n } catch {\n return undefined;\n }\n })\n .filter((item): item is NormalisedAPINotification => Boolean(item));\n\n return transformedNotifications ?? [];\n}\n\n/**\n * Marks the specified notifications as read.\n * This method sends a POST request to the notifications service to mark the provided notification IDs as read.\n * If the operation is successful, it completes without error. If the operation fails, it throws an error with details.\n *\n * @param bearerToken - The JSON Web Token used for authentication in the API call.\n * @param notificationIds - An array of notification IDs to be marked as read.\n * @param env - the environment to use for the API call\n * @returns A promise that resolves to void. The promise will reject if there's an error during the API call or if the response status is not 200.\n */\nexport async function markNotificationsAsRead(\n bearerToken: string,\n notificationIds: string[],\n env: ENV = 'prd',\n): Promise<void> {\n if (notificationIds.length === 0) {\n return;\n }\n\n type ResponseBody =\n Schema.paths['/api/v3/notifications/mark-as-read']['post']['requestBody']['content']['application/json'];\n const body: ResponseBody = {\n ids: notificationIds,\n };\n\n try {\n await makeApiCall(\n bearerToken,\n NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT(env),\n 'POST',\n body,\n );\n } catch (error) {\n log.error('Error marking notifications as read:', error);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"api-notifications.d.cts","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/api-notifications.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,yBAAyB,EAG1B,4CAAkC;AAGnC,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,GAAG,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAQxC,eAAO,MAAM,WAAW,SAAS,GAAG,WACS,CAAC;AAQ9C,eAAO,MAAM,gBAAgB,SAAS,GAAG,WACc,CAAC;AAGxD,eAAO,MAAM,wCAAwC,SAAS,GAAG,WACf,CAAC;AAGnD,eAAO,MAAM,kCAAkC,SAAS,GAAG,WACf,CAAC;AAG7C,eAAO,MAAM,8BAA8B,SAAS,GAAG,WACN,CAAC;AAGlD,eAAO,MAAM,0CAA0C,SAAS,GAAG,WACL,CAAC;AAE/D;;;;;;;;;GASG;AACH,wBAAsB,+BAA+B,CACnD,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,GAAG,GAAE,GAAW;;;KAgCjB;AAED;;;;;;;GAOG;AACH,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,EAAE,EAClD,GAAG,GAAE,GAAW,iBAqBjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,WAAW,GAAG,QAAQ,EAChC,GAAG,GAAE,GAAW,GACf,OAAO,CAAC,yBAAyB,EAAE,CAAC,CAwCtC;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EAAE,EACzB,GAAG,GAAE,GAAW,GACf,OAAO,CAAC,IAAI,CAAC,CAqBf"}
1
+ {"version":3,"file":"api-notifications.d.cts","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/api-notifications.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,yBAAyB,EAG1B,4CAAkC;AAGnC,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,GAAG,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAQxC,eAAO,MAAM,WAAW,SAAS,GAAG,KAAW,MACF,CAAC;AAQ9C,eAAO,MAAM,gBAAgB,SAAS,GAAG,KAAW,MACG,CAAC;AAGxD,eAAO,MAAM,wCAAwC,SAC9C,GAAG,KACP,MAA0D,CAAC;AAG9D,eAAO,MAAM,kCAAkC,SAAS,GAAG,KAAW,MAC1B,CAAC;AAG7C,eAAO,MAAM,8BAA8B,SAAS,GAAG,KAAW,MACjB,CAAC;AAGlD,eAAO,MAAM,0CAA0C,SAChD,GAAG,KACP,MAAsE,CAAC;AAE1E;;;;;;;;;GASG;AACH,wBAAsB,+BAA+B,CACnD,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,GAAG,GAAE,GAAW,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,EAAE,CAAC,CA+BlD;AAED;;;;;;;GAOG;AACH,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,EAAE,EAClD,GAAG,GAAE,GAAW,GACf,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,WAAW,GAAG,QAAQ,EAChC,GAAG,GAAE,GAAW,GACf,OAAO,CAAC,yBAAyB,EAAE,CAAC,CA0CtC;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EAAE,EACzB,GAAG,GAAE,GAAW,GACf,OAAO,CAAC,IAAI,CAAC,CAqBf"}
@@ -1 +1 @@
1
- {"version":3,"file":"api-notifications.d.mts","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/api-notifications.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,yBAAyB,EAG1B,4CAAkC;AAGnC,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,GAAG,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAQxC,eAAO,MAAM,WAAW,SAAS,GAAG,WACS,CAAC;AAQ9C,eAAO,MAAM,gBAAgB,SAAS,GAAG,WACc,CAAC;AAGxD,eAAO,MAAM,wCAAwC,SAAS,GAAG,WACf,CAAC;AAGnD,eAAO,MAAM,kCAAkC,SAAS,GAAG,WACf,CAAC;AAG7C,eAAO,MAAM,8BAA8B,SAAS,GAAG,WACN,CAAC;AAGlD,eAAO,MAAM,0CAA0C,SAAS,GAAG,WACL,CAAC;AAE/D;;;;;;;;;GASG;AACH,wBAAsB,+BAA+B,CACnD,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,GAAG,GAAE,GAAW;;;KAgCjB;AAED;;;;;;;GAOG;AACH,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,EAAE,EAClD,GAAG,GAAE,GAAW,iBAqBjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,WAAW,GAAG,QAAQ,EAChC,GAAG,GAAE,GAAW,GACf,OAAO,CAAC,yBAAyB,EAAE,CAAC,CAwCtC;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EAAE,EACzB,GAAG,GAAE,GAAW,GACf,OAAO,CAAC,IAAI,CAAC,CAqBf"}
1
+ {"version":3,"file":"api-notifications.d.mts","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/api-notifications.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,yBAAyB,EAG1B,4CAAkC;AAGnC,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,GAAG,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAQxC,eAAO,MAAM,WAAW,SAAS,GAAG,KAAW,MACF,CAAC;AAQ9C,eAAO,MAAM,gBAAgB,SAAS,GAAG,KAAW,MACG,CAAC;AAGxD,eAAO,MAAM,wCAAwC,SAC9C,GAAG,KACP,MAA0D,CAAC;AAG9D,eAAO,MAAM,kCAAkC,SAAS,GAAG,KAAW,MAC1B,CAAC;AAG7C,eAAO,MAAM,8BAA8B,SAAS,GAAG,KAAW,MACjB,CAAC;AAGlD,eAAO,MAAM,0CAA0C,SAChD,GAAG,KACP,MAAsE,CAAC;AAE1E;;;;;;;;;GASG;AACH,wBAAsB,+BAA+B,CACnD,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,GAAG,GAAE,GAAW,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,EAAE,CAAC,CA+BlD;AAED;;;;;;;GAOG;AACH,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,EAAE,EAClD,GAAG,GAAE,GAAW,GACf,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,WAAW,GAAG,QAAQ,EAChC,GAAG,GAAE,GAAW,GACf,OAAO,CAAC,yBAAyB,EAAE,CAAC,CA0CtC;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EAAE,EACzB,GAAG,GAAE,GAAW,GACf,OAAO,CAAC,IAAI,CAAC,CAqBf"}
@@ -27,7 +27,7 @@ export const TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT = (env = 'prd') => `${TRIG
27
27
  export const TRIGGER_API_NOTIFICATIONS_ENDPOINT = (env = 'prd') => `${TRIGGER_API(env)}/api/v2/notifications`;
28
28
  // Lists notifications for each account provided
29
29
  export const NOTIFICATION_API_LIST_ENDPOINT = (env = 'prd') => `${NOTIFICATION_API(env)}/api/v3/notifications`;
30
- // Makrs notifications as read
30
+ // Marks notifications as read
31
31
  export const NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = (env = 'prd') => `${NOTIFICATION_API(env)}/api/v3/notifications/mark-as-read`;
32
32
  /**
33
33
  * fetches notification config (accounts enabled vs disabled)
@@ -43,16 +43,16 @@ export async function getNotificationsApiConfigCached(bearerToken, addresses, en
43
43
  if (addresses.length === 0) {
44
44
  return [];
45
45
  }
46
- addresses = addresses.map((a) => a.toLowerCase());
47
- const cached = notificationsConfigCache.get(addresses);
46
+ const normalizedAddresses = addresses.map((addr) => addr.toLowerCase());
47
+ const cached = notificationsConfigCache.get(normalizedAddresses);
48
48
  if (cached) {
49
49
  return cached;
50
50
  }
51
- const body = addresses.map((address) => ({ address }));
52
- const data = await makeApiCall(bearerToken, TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT(env), 'POST', body)
53
- .then((r) => (r.ok ? r.json() : null))
51
+ const body = normalizedAddresses.map((address) => ({ address }));
52
+ const apiResponse = await makeApiCall(bearerToken, TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT(env), 'POST', body)
53
+ .then((response) => (response.ok ? response.json() : null))
54
54
  .catch(() => null);
55
- const result = data ?? [];
55
+ const result = apiResponse ?? [];
56
56
  if (result.length > 0) {
57
57
  notificationsConfigCache.set(result);
58
58
  }
@@ -70,13 +70,13 @@ export async function updateOnChainNotifications(bearerToken, addresses, env = '
70
70
  if (addresses.length === 0) {
71
71
  return;
72
72
  }
73
- addresses = addresses.map((a) => {
74
- a.address = a.address.toLowerCase();
75
- return a;
76
- });
77
- const body = addresses;
73
+ const normalizedAddresses = addresses.map((item) => ({
74
+ ...item,
75
+ address: item.address.toLowerCase(),
76
+ }));
77
+ const body = normalizedAddresses;
78
78
  await makeApiCall(bearerToken, TRIGGER_API_NOTIFICATIONS_ENDPOINT(env), 'POST', body)
79
- .then(() => notificationsConfigCache.set(addresses))
79
+ .then(() => notificationsConfigCache.set(normalizedAddresses))
80
80
  .catch(() => null);
81
81
  }
82
82
  /**
@@ -94,27 +94,27 @@ export async function getAPINotifications(bearerToken, addresses, locale, platfo
94
94
  return [];
95
95
  }
96
96
  const body = {
97
- addresses: addresses.map((a) => a.toLowerCase()),
97
+ addresses: addresses.map((addr) => addr.toLowerCase()),
98
98
  locale,
99
99
  platform,
100
100
  };
101
101
  const notifications = await makeApiCall(bearerToken, NOTIFICATION_API_LIST_ENDPOINT(env), 'POST', body)
102
- .then((r) => (r.ok ? r.json() : null))
102
+ .then((response) => response.ok ? response.json() : null)
103
103
  .catch(() => null);
104
104
  // Transform and sort notifications
105
105
  const transformedNotifications = notifications
106
- ?.map((n) => {
107
- if (!n.notification_type) {
106
+ ?.map((notification) => {
107
+ if (!notification.notification_type) {
108
108
  return undefined;
109
109
  }
110
110
  try {
111
- return toRawAPINotification(n);
111
+ return toRawAPINotification(notification);
112
112
  }
113
113
  catch {
114
114
  return undefined;
115
115
  }
116
116
  })
117
- .filter((n) => Boolean(n));
117
+ .filter((item) => Boolean(item));
118
118
  return transformedNotifications ?? [];
119
119
  }
120
120
  /**
@@ -137,8 +137,8 @@ export async function markNotificationsAsRead(bearerToken, notificationIds, env
137
137
  try {
138
138
  await makeApiCall(bearerToken, NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT(env), 'POST', body);
139
139
  }
140
- catch (err) {
141
- log.error('Error marking notifications as read:', err);
140
+ catch (error) {
141
+ log.error('Error marking notifications as read:', error);
142
142
  }
143
143
  }
144
144
  //# sourceMappingURL=api-notifications.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-notifications.mjs","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/api-notifications.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,IAAG,iBAAiB;;AAE3B,OAAO,EAAE,wBAAwB,EAAE,wCAAoC;AACvE,OAAO,EAAE,oBAAoB,EAAE,6CAAyC;AAMxE,OAAO,EAAE,WAAW,EAAE,2BAAuB;AAW7C,MAAM,eAAe,GAAG;IACtB,GAAG,EAAE,wCAAwC;IAC7C,GAAG,EAAE,wCAAwC;IAC7C,GAAG,EAAE,oCAAoC;CACZ,CAAC;AAEhC,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAW,KAAK,EAAE,EAAE,CAC9C,eAAe,CAAC,GAAG,CAAC,IAAI,eAAe,CAAC,GAAG,CAAC;AAE9C,MAAM,oBAAoB,GAAG;IAC3B,GAAG,EAAE,6CAA6C;IAClD,GAAG,EAAE,6CAA6C;IAClD,GAAG,EAAE,yCAAyC;CAC/C,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAW,KAAK,EAAE,EAAE,CACnD,oBAAoB,CAAC,GAAG,CAAC,IAAI,oBAAoB,CAAC,GAAG,CAAC;AAExD,uDAAuD;AACvD,MAAM,CAAC,MAAM,wCAAwC,GAAG,CAAC,MAAW,KAAK,EAAE,EAAE,CAC3E,GAAG,WAAW,CAAC,GAAG,CAAC,6BAA6B,CAAC;AAEnD,wEAAwE;AACxE,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,MAAW,KAAK,EAAE,EAAE,CACrE,GAAG,WAAW,CAAC,GAAG,CAAC,uBAAuB,CAAC;AAE7C,gDAAgD;AAChD,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,MAAW,KAAK,EAAE,EAAE,CACjE,GAAG,gBAAgB,CAAC,GAAG,CAAC,uBAAuB,CAAC;AAElD,8BAA8B;AAC9B,MAAM,CAAC,MAAM,0CAA0C,GAAG,CAAC,MAAW,KAAK,EAAE,EAAE,CAC7E,GAAG,gBAAgB,CAAC,GAAG,CAAC,oCAAoC,CAAC;AAE/D;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,WAAmB,EACnB,SAAmB,EACnB,MAAW,KAAK;IAEhB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAElD,MAAM,MAAM,GAAG,wBAAwB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACvD,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IAID,MAAM,IAAI,GAAgB,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IACpE,MAAM,IAAI,GAAG,MAAM,WAAW,CAC5B,WAAW,EACX,wCAAwC,CAAC,GAAG,CAAC,EAC7C,MAAM,EACN,IAAI,CACL;SACE,IAAI,CAAkB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SACtD,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAErB,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;IAE1B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,wBAAwB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,WAAmB,EACnB,SAAkD,EAClD,MAAW,KAAK;IAEhB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO;IACT,CAAC;IAED,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC9B,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QACpC,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;IAGH,MAAM,IAAI,GAAgB,SAAS,CAAC;IACpC,MAAM,WAAW,CACf,WAAW,EACX,kCAAkC,CAAC,GAAG,CAAC,EACvC,MAAM,EACN,IAAI,CACL;SACE,IAAI,CAAC,GAAG,EAAE,CAAC,wBAAwB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;SACnD,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,WAAmB,EACnB,SAAmB,EACnB,MAAc,EACd,QAAgC,EAChC,MAAW,KAAK;IAEhB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC;IAOD,MAAM,IAAI,GAAgB;QACxB,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAChD,MAAM;QACN,QAAQ;KACT,CAAC;IACF,MAAM,aAAa,GAAG,MAAM,WAAW,CACrC,WAAW,EACX,8BAA8B,CAAC,GAAG,CAAC,EACnC,MAAM,EACN,IAAI,CACL;SACE,IAAI,CAAqB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SACzD,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAErB,mCAAmC;IACnC,MAAM,wBAAwB,GAAG,aAAa;QAC5C,EAAE,GAAG,CAAC,CAAC,CAAC,EAA0C,EAAE;QAClD,IAAI,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;YACzB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,CAAC;YACH,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,CAAC,EAAkC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7D,OAAO,wBAAwB,IAAI,EAAE,CAAC;AACxC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,WAAmB,EACnB,eAAyB,EACzB,MAAW,KAAK;IAEhB,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO;IACT,CAAC;IAID,MAAM,IAAI,GAAiB;QACzB,GAAG,EAAE,eAAe;KACrB,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,WAAW,CACf,WAAW,EACX,0CAA0C,CAAC,GAAG,CAAC,EAC/C,MAAM,EACN,IAAI,CACL,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,sCAAsC,EAAE,GAAG,CAAC,CAAC;IACzD,CAAC;AACH,CAAC","sourcesContent":["import log from 'loglevel';\n\nimport { notificationsConfigCache } from './notification-config-cache';\nimport { toRawAPINotification } from '../../shared/to-raw-notification';\nimport type {\n NormalisedAPINotification,\n Schema,\n UnprocessedRawNotification,\n} from '../types/notification-api';\nimport { makeApiCall } from '../utils/utils';\n\nexport type NotificationTrigger = {\n id: string;\n chainId: string;\n kind: string;\n address: string;\n};\n\nexport type ENV = 'prd' | 'uat' | 'dev';\n\nconst TRIGGER_API_ENV = {\n dev: 'https://trigger.dev-api.cx.metamask.io',\n uat: 'https://trigger.uat-api.cx.metamask.io',\n prd: 'https://trigger.api.cx.metamask.io',\n} satisfies Record<ENV, string>;\n\nexport const TRIGGER_API = (env: ENV = 'prd') =>\n TRIGGER_API_ENV[env] ?? TRIGGER_API_ENV.prd;\n\nconst NOTIFICATION_API_ENV = {\n dev: 'https://notification.dev-api.cx.metamask.io',\n uat: 'https://notification.uat-api.cx.metamask.io',\n prd: 'https://notification.api.cx.metamask.io',\n};\n\nexport const NOTIFICATION_API = (env: ENV = 'prd') =>\n NOTIFICATION_API_ENV[env] ?? NOTIFICATION_API_ENV.prd;\n\n// Gets notification settings for each account provided\nexport const TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT = (env: ENV = 'prd') =>\n `${TRIGGER_API(env)}/api/v2/notifications/query`;\n\n// Used to create/update account notifications for each account provided\nexport const TRIGGER_API_NOTIFICATIONS_ENDPOINT = (env: ENV = 'prd') =>\n `${TRIGGER_API(env)}/api/v2/notifications`;\n\n// Lists notifications for each account provided\nexport const NOTIFICATION_API_LIST_ENDPOINT = (env: ENV = 'prd') =>\n `${NOTIFICATION_API(env)}/api/v3/notifications`;\n\n// Makrs notifications as read\nexport const NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = (env: ENV = 'prd') =>\n `${NOTIFICATION_API(env)}/api/v3/notifications/mark-as-read`;\n\n/**\n * fetches notification config (accounts enabled vs disabled)\n *\n * @param bearerToken - jwt\n * @param addresses - list of addresses to check\n * @param env - the environment to use for the API call\n * NOTE the API will return addresses config with false if they have not been created before.\n * NOTE this is cached for 1s to prevent multiple update calls\n * @returns object of notification config, or null if missing\n */\nexport async function getNotificationsApiConfigCached(\n bearerToken: string,\n addresses: string[],\n env: ENV = 'prd',\n) {\n if (addresses.length === 0) {\n return [];\n }\n\n addresses = addresses.map((a) => a.toLowerCase());\n\n const cached = notificationsConfigCache.get(addresses);\n if (cached) {\n return cached;\n }\n\n type RequestBody = { address: string }[];\n type Response = { address: string; enabled: boolean }[];\n const body: RequestBody = addresses.map((address) => ({ address }));\n const data = await makeApiCall(\n bearerToken,\n TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT(env),\n 'POST',\n body,\n )\n .then<Response | null>((r) => (r.ok ? r.json() : null))\n .catch(() => null);\n\n const result = data ?? [];\n\n if (result.length > 0) {\n notificationsConfigCache.set(result);\n }\n\n return result;\n}\n\n/**\n * updates notifications for a given addresses\n *\n * @param bearerToken - jwt\n * @param addresses - list of addresses to check\n * @param env - the environment to use for the API call\n * @returns void\n */\nexport async function updateOnChainNotifications(\n bearerToken: string,\n addresses: { address: string; enabled: boolean }[],\n env: ENV = 'prd',\n) {\n if (addresses.length === 0) {\n return;\n }\n\n addresses = addresses.map((a) => {\n a.address = a.address.toLowerCase();\n return a;\n });\n\n type RequestBody = { address: string; enabled: boolean }[];\n const body: RequestBody = addresses;\n await makeApiCall(\n bearerToken,\n TRIGGER_API_NOTIFICATIONS_ENDPOINT(env),\n 'POST',\n body,\n )\n .then(() => notificationsConfigCache.set(addresses))\n .catch(() => null);\n}\n\n/**\n * Fetches on-chain notifications for the given addresses\n *\n * @param bearerToken - The JSON Web Token used for authentication in the API call.\n * @param addresses - List of addresses\n * @param locale - to generate translated notifications\n * @param platform - filter notifications for specific platforms ('extension' | 'mobile')\n * @param env - the environment to use for the API call\n * @returns A promise that resolves to an array of NormalisedAPINotification objects. If no notifications are enabled or an error occurs, it may return an empty array.\n */\nexport async function getAPINotifications(\n bearerToken: string,\n addresses: string[],\n locale: string,\n platform: 'extension' | 'mobile',\n env: ENV = 'prd',\n): Promise<NormalisedAPINotification[]> {\n if (addresses.length === 0) {\n return [];\n }\n\n type RequestBody =\n Schema.paths['/api/v3/notifications']['post']['requestBody']['content']['application/json'];\n type APIResponse =\n Schema.paths['/api/v3/notifications']['post']['responses']['200']['content']['application/json'];\n\n const body: RequestBody = {\n addresses: addresses.map((a) => a.toLowerCase()),\n locale,\n platform,\n };\n const notifications = await makeApiCall(\n bearerToken,\n NOTIFICATION_API_LIST_ENDPOINT(env),\n 'POST',\n body,\n )\n .then<APIResponse | null>((r) => (r.ok ? r.json() : null))\n .catch(() => null);\n\n // Transform and sort notifications\n const transformedNotifications = notifications\n ?.map((n): UnprocessedRawNotification | undefined => {\n if (!n.notification_type) {\n return undefined;\n }\n\n try {\n return toRawAPINotification(n);\n } catch {\n return undefined;\n }\n })\n .filter((n): n is NormalisedAPINotification => Boolean(n));\n\n return transformedNotifications ?? [];\n}\n\n/**\n * Marks the specified notifications as read.\n * This method sends a POST request to the notifications service to mark the provided notification IDs as read.\n * If the operation is successful, it completes without error. If the operation fails, it throws an error with details.\n *\n * @param bearerToken - The JSON Web Token used for authentication in the API call.\n * @param notificationIds - An array of notification IDs to be marked as read.\n * @param env - the environment to use for the API call\n * @returns A promise that resolves to void. The promise will reject if there's an error during the API call or if the response status is not 200.\n */\nexport async function markNotificationsAsRead(\n bearerToken: string,\n notificationIds: string[],\n env: ENV = 'prd',\n): Promise<void> {\n if (notificationIds.length === 0) {\n return;\n }\n\n type ResponseBody =\n Schema.paths['/api/v3/notifications/mark-as-read']['post']['requestBody']['content']['application/json'];\n const body: ResponseBody = {\n ids: notificationIds,\n };\n\n try {\n await makeApiCall(\n bearerToken,\n NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT(env),\n 'POST',\n body,\n );\n } catch (err) {\n log.error('Error marking notifications as read:', err);\n }\n}\n"]}
1
+ {"version":3,"file":"api-notifications.mjs","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/api-notifications.ts"],"names":[],"mappings":"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","sourcesContent":["import log from 'loglevel';\n\nimport { notificationsConfigCache } from './notification-config-cache';\nimport { toRawAPINotification } from '../../shared/to-raw-notification';\nimport type {\n NormalisedAPINotification,\n Schema,\n UnprocessedRawNotification,\n} from '../types/notification-api';\nimport { makeApiCall } from '../utils/utils';\n\nexport type NotificationTrigger = {\n id: string;\n chainId: string;\n kind: string;\n address: string;\n};\n\nexport type ENV = 'prd' | 'uat' | 'dev';\n\nconst TRIGGER_API_ENV = {\n dev: 'https://trigger.dev-api.cx.metamask.io',\n uat: 'https://trigger.uat-api.cx.metamask.io',\n prd: 'https://trigger.api.cx.metamask.io',\n} satisfies Record<ENV, string>;\n\nexport const TRIGGER_API = (env: ENV = 'prd'): string =>\n TRIGGER_API_ENV[env] ?? TRIGGER_API_ENV.prd;\n\nconst NOTIFICATION_API_ENV = {\n dev: 'https://notification.dev-api.cx.metamask.io',\n uat: 'https://notification.uat-api.cx.metamask.io',\n prd: 'https://notification.api.cx.metamask.io',\n};\n\nexport const NOTIFICATION_API = (env: ENV = 'prd'): string =>\n NOTIFICATION_API_ENV[env] ?? NOTIFICATION_API_ENV.prd;\n\n// Gets notification settings for each account provided\nexport const TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT = (\n env: ENV = 'prd',\n): string => `${TRIGGER_API(env)}/api/v2/notifications/query`;\n\n// Used to create/update account notifications for each account provided\nexport const TRIGGER_API_NOTIFICATIONS_ENDPOINT = (env: ENV = 'prd'): string =>\n `${TRIGGER_API(env)}/api/v2/notifications`;\n\n// Lists notifications for each account provided\nexport const NOTIFICATION_API_LIST_ENDPOINT = (env: ENV = 'prd'): string =>\n `${NOTIFICATION_API(env)}/api/v3/notifications`;\n\n// Marks notifications as read\nexport const NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = (\n env: ENV = 'prd',\n): string => `${NOTIFICATION_API(env)}/api/v3/notifications/mark-as-read`;\n\n/**\n * fetches notification config (accounts enabled vs disabled)\n *\n * @param bearerToken - jwt\n * @param addresses - list of addresses to check\n * @param env - the environment to use for the API call\n * NOTE the API will return addresses config with false if they have not been created before.\n * NOTE this is cached for 1s to prevent multiple update calls\n * @returns object of notification config, or null if missing\n */\nexport async function getNotificationsApiConfigCached(\n bearerToken: string,\n addresses: string[],\n env: ENV = 'prd',\n): Promise<{ address: string; enabled: boolean }[]> {\n if (addresses.length === 0) {\n return [];\n }\n\n const normalizedAddresses = addresses.map((addr) => addr.toLowerCase());\n\n const cached = notificationsConfigCache.get(normalizedAddresses);\n if (cached) {\n return cached;\n }\n\n type RequestBody = { address: string }[];\n type Response = { address: string; enabled: boolean }[];\n const body: RequestBody = normalizedAddresses.map((address) => ({ address }));\n const apiResponse = await makeApiCall(\n bearerToken,\n TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT(env),\n 'POST',\n body,\n )\n .then<Response | null>((response) => (response.ok ? response.json() : null))\n .catch(() => null);\n\n const result = apiResponse ?? [];\n\n if (result.length > 0) {\n notificationsConfigCache.set(result);\n }\n\n return result;\n}\n\n/**\n * updates notifications for a given addresses\n *\n * @param bearerToken - jwt\n * @param addresses - list of addresses to check\n * @param env - the environment to use for the API call\n * @returns void\n */\nexport async function updateOnChainNotifications(\n bearerToken: string,\n addresses: { address: string; enabled: boolean }[],\n env: ENV = 'prd',\n): Promise<void> {\n if (addresses.length === 0) {\n return;\n }\n\n const normalizedAddresses = addresses.map((item) => ({\n ...item,\n address: item.address.toLowerCase(),\n }));\n\n type RequestBody = { address: string; enabled: boolean }[];\n const body: RequestBody = normalizedAddresses;\n await makeApiCall(\n bearerToken,\n TRIGGER_API_NOTIFICATIONS_ENDPOINT(env),\n 'POST',\n body,\n )\n .then(() => notificationsConfigCache.set(normalizedAddresses))\n .catch(() => null);\n}\n\n/**\n * Fetches on-chain notifications for the given addresses\n *\n * @param bearerToken - The JSON Web Token used for authentication in the API call.\n * @param addresses - List of addresses\n * @param locale - to generate translated notifications\n * @param platform - filter notifications for specific platforms ('extension' | 'mobile')\n * @param env - the environment to use for the API call\n * @returns A promise that resolves to an array of NormalisedAPINotification objects. If no notifications are enabled or an error occurs, it may return an empty array.\n */\nexport async function getAPINotifications(\n bearerToken: string,\n addresses: string[],\n locale: string,\n platform: 'extension' | 'mobile',\n env: ENV = 'prd',\n): Promise<NormalisedAPINotification[]> {\n if (addresses.length === 0) {\n return [];\n }\n\n type RequestBody =\n Schema.paths['/api/v3/notifications']['post']['requestBody']['content']['application/json'];\n type APIResponse =\n Schema.paths['/api/v3/notifications']['post']['responses']['200']['content']['application/json'];\n\n const body: RequestBody = {\n addresses: addresses.map((addr) => addr.toLowerCase()),\n locale,\n platform,\n };\n const notifications = await makeApiCall(\n bearerToken,\n NOTIFICATION_API_LIST_ENDPOINT(env),\n 'POST',\n body,\n )\n .then<APIResponse | null>((response) =>\n response.ok ? response.json() : null,\n )\n .catch(() => null);\n\n // Transform and sort notifications\n const transformedNotifications = notifications\n ?.map((notification): UnprocessedRawNotification | undefined => {\n if (!notification.notification_type) {\n return undefined;\n }\n\n try {\n return toRawAPINotification(notification);\n } catch {\n return undefined;\n }\n })\n .filter((item): item is NormalisedAPINotification => Boolean(item));\n\n return transformedNotifications ?? [];\n}\n\n/**\n * Marks the specified notifications as read.\n * This method sends a POST request to the notifications service to mark the provided notification IDs as read.\n * If the operation is successful, it completes without error. If the operation fails, it throws an error with details.\n *\n * @param bearerToken - The JSON Web Token used for authentication in the API call.\n * @param notificationIds - An array of notification IDs to be marked as read.\n * @param env - the environment to use for the API call\n * @returns A promise that resolves to void. The promise will reject if there's an error during the API call or if the response status is not 200.\n */\nexport async function markNotificationsAsRead(\n bearerToken: string,\n notificationIds: string[],\n env: ENV = 'prd',\n): Promise<void> {\n if (notificationIds.length === 0) {\n return;\n }\n\n type ResponseBody =\n Schema.paths['/api/v3/notifications/mark-as-read']['post']['requestBody']['content']['application/json'];\n const body: ResponseBody = {\n ids: notificationIds,\n };\n\n try {\n await makeApiCall(\n bearerToken,\n NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT(env),\n 'POST',\n body,\n );\n } catch (error) {\n log.error('Error marking notifications as read:', error);\n }\n}\n"]}
@@ -5,6 +5,8 @@ const rich_text_html_renderer_1 = require("@contentful/rich-text-html-renderer")
5
5
  const notification_schema_1 = require("../constants/notification-schema.cjs");
6
6
  const process_feature_announcement_1 = require("../processors/process-feature-announcement.cjs");
7
7
  const isVersionInBounds_1 = require("../utils/isVersionInBounds.cjs");
8
+ // Feature announcements older than this (by sys.updatedAt) are excluded from the feed.
9
+ const FEATURE_ANNOUNCEMENT_MAX_AGE_MONTHS = 3;
8
10
  const DEFAULT_SPACE_ID = ':space_id';
9
11
  const DEFAULT_ACCESS_TOKEN = ':access_token';
10
12
  const DEFAULT_CLIENT_ID = ':client_id';
@@ -15,7 +17,7 @@ exports.FEATURE_ANNOUNCEMENT_URL = `${exports.FEATURE_ANNOUNCEMENT_API}?access_t
15
17
  const getFeatureAnnouncementUrl = (env, previewToken) => {
16
18
  const domain = previewToken ? PREVIEW_DOMAIN : DEFAULT_DOMAIN;
17
19
  const replacedUrl = exports.FEATURE_ANNOUNCEMENT_URL.replace(DEFAULT_SPACE_ID, env.spaceId)
18
- .replace(DEFAULT_ACCESS_TOKEN, previewToken || env.accessToken)
20
+ .replace(DEFAULT_ACCESS_TOKEN, previewToken ?? env.accessToken)
19
21
  .replace(DEFAULT_CLIENT_ID, env.platform)
20
22
  .replace(DEFAULT_DOMAIN, domain);
21
23
  return encodeURI(replacedUrl);
@@ -24,20 +26,27 @@ exports.getFeatureAnnouncementUrl = getFeatureAnnouncementUrl;
24
26
  const fetchFeatureAnnouncementNotifications = async (env, previewToken) => {
25
27
  const url = (0, exports.getFeatureAnnouncementUrl)(env, previewToken);
26
28
  const data = await fetch(url)
27
- .then((r) => r.json())
29
+ .then((response) => response.json())
28
30
  .catch(() => null);
29
31
  if (!data) {
30
32
  return [];
31
33
  }
32
34
  const findIncludedItem = (sysId) => {
33
35
  const typedData = data;
34
- const item = typedData?.includes?.Entry?.find((i) => i?.sys?.id === sysId) ||
35
- typedData?.includes?.Asset?.find((i) => i?.sys?.id === sysId);
36
+ const item = typedData?.includes?.Entry?.find((entry) => entry?.sys?.id === sysId) ??
37
+ typedData?.includes?.Asset?.find((asset) => asset?.sys?.id === sysId);
36
38
  return item ? item?.fields : null;
37
39
  };
38
40
  const contentfulNotifications = data?.items ?? [];
39
- const rawNotifications = contentfulNotifications.map((n) => {
40
- const { fields } = n;
41
+ const rawNotifications = contentfulNotifications
42
+ .filter((item) => {
43
+ const updatedAt = new Date(item.sys.updatedAt);
44
+ const limitDate = new Date();
45
+ limitDate.setMonth(limitDate.getMonth() - FEATURE_ANNOUNCEMENT_MAX_AGE_MONTHS);
46
+ return updatedAt > limitDate;
47
+ })
48
+ .map((item) => {
49
+ const { fields } = item;
41
50
  const imageFields = fields.image
42
51
  ? findIncludedItem(fields.image.sys.id)
43
52
  : undefined;
@@ -55,7 +64,7 @@ const fetchFeatureAnnouncementNotifications = async (env, previewToken) => {
55
64
  : undefined;
56
65
  const notification = {
57
66
  type: notification_schema_1.TRIGGER_TYPES.FEATURES_ANNOUNCEMENT,
58
- createdAt: new Date(n.sys.createdAt).toString(),
67
+ createdAt: new Date(item.sys.createdAt).toString(),
59
68
  data: {
60
69
  id: fields.id,
61
70
  category: fields.category,
@@ -101,9 +110,9 @@ const fetchFeatureAnnouncementNotifications = async (env, previewToken) => {
101
110
  max: 'mobileMaximumVersionNumber',
102
111
  },
103
112
  };
104
- const filteredRawNotifications = rawNotifications.filter((n) => {
105
- const minVersion = n.data?.[versionKeys[env.platform].min];
106
- const maxVersion = n.data?.[versionKeys[env.platform].max];
113
+ const filteredRawNotifications = rawNotifications.filter((rawNotification) => {
114
+ const minVersion = rawNotification.data?.[versionKeys[env.platform].min];
115
+ const maxVersion = rawNotification.data?.[versionKeys[env.platform].max];
107
116
  return (0, isVersionInBounds_1.isVersionInBounds)({
108
117
  currentVersion: env.platformVersion,
109
118
  minVersion,
@@ -1 +1 @@
1
- {"version":3,"file":"feature-announcements.cjs","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/feature-announcements.ts"],"names":[],"mappings":"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","sourcesContent":["import { documentToHtmlString } from '@contentful/rich-text-html-renderer';\nimport type { Entry, Asset, EntryCollection } from 'contentful';\n\nimport { TRIGGER_TYPES } from '../constants/notification-schema';\nimport { processFeatureAnnouncement } from '../processors/process-feature-announcement';\nimport type { FeatureAnnouncementRawNotification } from '../types/feature-announcement/feature-announcement';\nimport type {\n ImageFields,\n TypeFeatureAnnouncement,\n} from '../types/feature-announcement/type-feature-announcement';\nimport type {\n TypeExternalLinkFields,\n TypePortfolioLinkFields,\n TypeExtensionLinkFields,\n TypeMobileLinkFields,\n} from '../types/feature-announcement/type-links';\nimport type { INotification } from '../types/notification/notification';\nimport { isVersionInBounds } from '../utils/isVersionInBounds';\n\nconst DEFAULT_SPACE_ID = ':space_id';\nconst DEFAULT_ACCESS_TOKEN = ':access_token';\nconst DEFAULT_CLIENT_ID = ':client_id';\nconst DEFAULT_DOMAIN = 'cdn.contentful.com';\nconst PREVIEW_DOMAIN = 'preview.contentful.com';\nexport const FEATURE_ANNOUNCEMENT_API = `https://${DEFAULT_DOMAIN}/spaces/${DEFAULT_SPACE_ID}/environments/master/entries`;\nexport const FEATURE_ANNOUNCEMENT_URL = `${FEATURE_ANNOUNCEMENT_API}?access_token=${DEFAULT_ACCESS_TOKEN}&content_type=productAnnouncement&include=10&fields.clients[in]=${DEFAULT_CLIENT_ID}`;\n\ntype Env = {\n spaceId: string;\n accessToken: string;\n platform: 'extension' | 'mobile';\n platformVersion?: string;\n};\n\n/**\n * Contentful API Response Shape\n */\nexport type ContentfulResult = {\n includes?: {\n Entry?: Entry[];\n Asset?: Asset[];\n };\n items?: TypeFeatureAnnouncement[];\n};\n\nexport const getFeatureAnnouncementUrl = (env: Env, previewToken?: string) => {\n const domain = previewToken ? PREVIEW_DOMAIN : DEFAULT_DOMAIN;\n const replacedUrl = FEATURE_ANNOUNCEMENT_URL.replace(\n DEFAULT_SPACE_ID,\n env.spaceId,\n )\n .replace(DEFAULT_ACCESS_TOKEN, previewToken || env.accessToken)\n .replace(DEFAULT_CLIENT_ID, env.platform)\n .replace(DEFAULT_DOMAIN, domain);\n return encodeURI(replacedUrl);\n};\n\nconst fetchFeatureAnnouncementNotifications = async (\n env: Env,\n previewToken?: string,\n): Promise<FeatureAnnouncementRawNotification[]> => {\n const url = getFeatureAnnouncementUrl(env, previewToken);\n\n const data = await fetch(url)\n .then((r) => r.json())\n .catch(() => null);\n\n if (!data) {\n return [];\n }\n\n const findIncludedItem = (sysId: string) => {\n const typedData: EntryCollection<\n | ImageFields\n | TypeExtensionLinkFields\n | TypePortfolioLinkFields\n | TypeMobileLinkFields\n | TypeExternalLinkFields\n > = data;\n const item =\n typedData?.includes?.Entry?.find((i: Entry) => i?.sys?.id === sysId) ||\n typedData?.includes?.Asset?.find((i: Asset) => i?.sys?.id === sysId);\n return item ? item?.fields : null;\n };\n\n const contentfulNotifications = data?.items ?? [];\n const rawNotifications: FeatureAnnouncementRawNotification[] =\n contentfulNotifications.map((n: TypeFeatureAnnouncement) => {\n const { fields } = n;\n const imageFields = fields.image\n ? (findIncludedItem(fields.image.sys.id) as ImageFields['fields'])\n : undefined;\n\n const externalLinkFields = fields.externalLink\n ? (findIncludedItem(\n fields.externalLink.sys.id,\n ) as TypeExternalLinkFields['fields'])\n : undefined;\n const portfolioLinkFields = fields.portfolioLink\n ? (findIncludedItem(\n fields.portfolioLink.sys.id,\n ) as TypePortfolioLinkFields['fields'])\n : undefined;\n const extensionLinkFields = fields.extensionLink\n ? (findIncludedItem(\n fields.extensionLink.sys.id,\n ) as TypeExtensionLinkFields['fields'])\n : undefined;\n const mobileLinkFields = fields.mobileLink\n ? (findIncludedItem(\n fields.mobileLink.sys.id,\n ) as TypeMobileLinkFields['fields'])\n : undefined;\n\n const notification: FeatureAnnouncementRawNotification = {\n type: TRIGGER_TYPES.FEATURES_ANNOUNCEMENT,\n createdAt: new Date(n.sys.createdAt).toString(),\n data: {\n id: fields.id,\n category: fields.category,\n title: fields.title,\n longDescription: documentToHtmlString(fields.longDescription),\n shortDescription: fields.shortDescription,\n image: {\n title: imageFields?.title,\n description: imageFields?.description,\n url: imageFields?.file?.url ?? '',\n },\n externalLink: externalLinkFields && {\n externalLinkText: externalLinkFields?.externalLinkText,\n externalLinkUrl: externalLinkFields?.externalLinkUrl,\n },\n portfolioLink: portfolioLinkFields && {\n portfolioLinkText: portfolioLinkFields?.portfolioLinkText,\n portfolioLinkUrl: portfolioLinkFields?.portfolioLinkUrl,\n },\n extensionLink: extensionLinkFields && {\n extensionLinkText: extensionLinkFields?.extensionLinkText,\n extensionLinkRoute: extensionLinkFields?.extensionLinkRoute,\n },\n mobileLink: mobileLinkFields && {\n mobileLinkText: mobileLinkFields?.mobileLinkText,\n mobileLinkUrl: mobileLinkFields?.mobileLinkUrl,\n },\n extensionMinimumVersionNumber: fields.extensionMinimumVersionNumber,\n mobileMinimumVersionNumber: fields.mobileMinimumVersionNumber,\n extensionMaximumVersionNumber: fields.extensionMaximumVersionNumber,\n mobileMaximumVersionNumber: fields.mobileMaximumVersionNumber,\n },\n };\n\n return notification;\n });\n\n const versionKeys = {\n extension: {\n min: 'extensionMinimumVersionNumber',\n max: 'extensionMaximumVersionNumber',\n },\n mobile: {\n min: 'mobileMinimumVersionNumber',\n max: 'mobileMaximumVersionNumber',\n },\n } as const;\n\n const filteredRawNotifications = rawNotifications.filter((n) => {\n const minVersion = n.data?.[versionKeys[env.platform].min];\n const maxVersion = n.data?.[versionKeys[env.platform].max];\n return isVersionInBounds({\n currentVersion: env.platformVersion,\n minVersion,\n maxVersion,\n });\n });\n\n return filteredRawNotifications;\n};\n\n/**\n * Gets Feature Announcement from our services\n *\n * @param env - environment for feature announcements\n * @param previewToken - the preview token to use if needed\n * @returns Raw Feature Announcements\n */\nexport async function getFeatureAnnouncementNotifications(\n env: Env,\n previewToken?: string,\n): Promise<INotification[]> {\n if (env?.accessToken && env?.spaceId && env?.platform) {\n const rawNotifications = await fetchFeatureAnnouncementNotifications(\n env,\n previewToken,\n );\n const notifications = rawNotifications.map((notification) =>\n processFeatureAnnouncement(notification),\n );\n\n return notifications;\n }\n\n return [];\n}\n"]}
1
+ {"version":3,"file":"feature-announcements.cjs","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/feature-announcements.ts"],"names":[],"mappings":"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","sourcesContent":["import { documentToHtmlString } from '@contentful/rich-text-html-renderer';\nimport type { Entry, Asset, EntryCollection } from 'contentful';\n\nimport { TRIGGER_TYPES } from '../constants/notification-schema';\nimport { processFeatureAnnouncement } from '../processors/process-feature-announcement';\nimport type { FeatureAnnouncementRawNotification } from '../types/feature-announcement/feature-announcement';\nimport type {\n ImageFields,\n TypeFeatureAnnouncement,\n} from '../types/feature-announcement/type-feature-announcement';\nimport type {\n TypeExternalLinkFields,\n TypePortfolioLinkFields,\n TypeExtensionLinkFields,\n TypeMobileLinkFields,\n} from '../types/feature-announcement/type-links';\nimport type { INotification } from '../types/notification/notification';\nimport { isVersionInBounds } from '../utils/isVersionInBounds';\n\n// Feature announcements older than this (by sys.updatedAt) are excluded from the feed.\nconst FEATURE_ANNOUNCEMENT_MAX_AGE_MONTHS = 3;\n\nconst DEFAULT_SPACE_ID = ':space_id';\nconst DEFAULT_ACCESS_TOKEN = ':access_token';\nconst DEFAULT_CLIENT_ID = ':client_id';\nconst DEFAULT_DOMAIN = 'cdn.contentful.com';\nconst PREVIEW_DOMAIN = 'preview.contentful.com';\nexport const FEATURE_ANNOUNCEMENT_API = `https://${DEFAULT_DOMAIN}/spaces/${DEFAULT_SPACE_ID}/environments/master/entries`;\nexport const FEATURE_ANNOUNCEMENT_URL = `${FEATURE_ANNOUNCEMENT_API}?access_token=${DEFAULT_ACCESS_TOKEN}&content_type=productAnnouncement&include=10&fields.clients[in]=${DEFAULT_CLIENT_ID}`;\n\ntype Env = {\n spaceId: string;\n accessToken: string;\n platform: 'extension' | 'mobile';\n platformVersion?: string;\n};\n\n/**\n * Contentful API Response Shape\n */\nexport type ContentfulResult = {\n includes?: {\n // Property names match Contentful API response structure\n // eslint-disable-next-line @typescript-eslint/naming-convention\n Entry?: Entry[];\n // eslint-disable-next-line @typescript-eslint/naming-convention\n Asset?: Asset[];\n };\n items?: TypeFeatureAnnouncement[];\n};\n\nexport const getFeatureAnnouncementUrl = (\n env: Env,\n previewToken?: string,\n): string => {\n const domain = previewToken ? PREVIEW_DOMAIN : DEFAULT_DOMAIN;\n const replacedUrl = FEATURE_ANNOUNCEMENT_URL.replace(\n DEFAULT_SPACE_ID,\n env.spaceId,\n )\n .replace(DEFAULT_ACCESS_TOKEN, previewToken ?? env.accessToken)\n .replace(DEFAULT_CLIENT_ID, env.platform)\n .replace(DEFAULT_DOMAIN, domain);\n return encodeURI(replacedUrl);\n};\n\nconst fetchFeatureAnnouncementNotifications = async (\n env: Env,\n previewToken?: string,\n): Promise<FeatureAnnouncementRawNotification[]> => {\n const url = getFeatureAnnouncementUrl(env, previewToken);\n\n const data = await fetch(url)\n .then((response) => response.json())\n .catch(() => null);\n\n if (!data) {\n return [];\n }\n\n const findIncludedItem = (\n sysId: string,\n ):\n | ImageFields['fields']\n | TypeExtensionLinkFields['fields']\n | TypePortfolioLinkFields['fields']\n | TypeMobileLinkFields['fields']\n | TypeExternalLinkFields['fields']\n | null => {\n const typedData: EntryCollection<\n | ImageFields\n | TypeExtensionLinkFields\n | TypePortfolioLinkFields\n | TypeMobileLinkFields\n | TypeExternalLinkFields\n > = data;\n const item =\n typedData?.includes?.Entry?.find(\n (entry: Entry) => entry?.sys?.id === sysId,\n ) ??\n typedData?.includes?.Asset?.find(\n (asset: Asset) => asset?.sys?.id === sysId,\n );\n return item ? item?.fields : null;\n };\n\n const contentfulNotifications = data?.items ?? [];\n const rawNotifications: FeatureAnnouncementRawNotification[] =\n contentfulNotifications\n .filter((item: TypeFeatureAnnouncement) => {\n const updatedAt = new Date(item.sys.updatedAt);\n const limitDate = new Date();\n limitDate.setMonth(\n limitDate.getMonth() - FEATURE_ANNOUNCEMENT_MAX_AGE_MONTHS,\n );\n return updatedAt > limitDate;\n })\n .map((item: TypeFeatureAnnouncement) => {\n const { fields } = item;\n const imageFields = fields.image\n ? (findIncludedItem(fields.image.sys.id) as ImageFields['fields'])\n : undefined;\n\n const externalLinkFields = fields.externalLink\n ? (findIncludedItem(\n fields.externalLink.sys.id,\n ) as TypeExternalLinkFields['fields'])\n : undefined;\n const portfolioLinkFields = fields.portfolioLink\n ? (findIncludedItem(\n fields.portfolioLink.sys.id,\n ) as TypePortfolioLinkFields['fields'])\n : undefined;\n const extensionLinkFields = fields.extensionLink\n ? (findIncludedItem(\n fields.extensionLink.sys.id,\n ) as TypeExtensionLinkFields['fields'])\n : undefined;\n const mobileLinkFields = fields.mobileLink\n ? (findIncludedItem(\n fields.mobileLink.sys.id,\n ) as TypeMobileLinkFields['fields'])\n : undefined;\n\n const notification: FeatureAnnouncementRawNotification = {\n type: TRIGGER_TYPES.FEATURES_ANNOUNCEMENT,\n createdAt: new Date(item.sys.createdAt).toString(),\n data: {\n id: fields.id,\n category: fields.category,\n title: fields.title,\n longDescription: documentToHtmlString(fields.longDescription),\n shortDescription: fields.shortDescription,\n image: {\n title: imageFields?.title,\n description: imageFields?.description,\n url: imageFields?.file?.url ?? '',\n },\n externalLink: externalLinkFields && {\n externalLinkText: externalLinkFields?.externalLinkText,\n externalLinkUrl: externalLinkFields?.externalLinkUrl,\n },\n portfolioLink: portfolioLinkFields && {\n portfolioLinkText: portfolioLinkFields?.portfolioLinkText,\n portfolioLinkUrl: portfolioLinkFields?.portfolioLinkUrl,\n },\n extensionLink: extensionLinkFields && {\n extensionLinkText: extensionLinkFields?.extensionLinkText,\n extensionLinkRoute: extensionLinkFields?.extensionLinkRoute,\n },\n mobileLink: mobileLinkFields && {\n mobileLinkText: mobileLinkFields?.mobileLinkText,\n mobileLinkUrl: mobileLinkFields?.mobileLinkUrl,\n },\n extensionMinimumVersionNumber: fields.extensionMinimumVersionNumber,\n mobileMinimumVersionNumber: fields.mobileMinimumVersionNumber,\n extensionMaximumVersionNumber: fields.extensionMaximumVersionNumber,\n mobileMaximumVersionNumber: fields.mobileMaximumVersionNumber,\n },\n };\n\n return notification;\n });\n\n const versionKeys = {\n extension: {\n min: 'extensionMinimumVersionNumber',\n max: 'extensionMaximumVersionNumber',\n },\n mobile: {\n min: 'mobileMinimumVersionNumber',\n max: 'mobileMaximumVersionNumber',\n },\n } as const;\n\n const filteredRawNotifications = rawNotifications.filter(\n (rawNotification) => {\n const minVersion = rawNotification.data?.[versionKeys[env.platform].min];\n const maxVersion = rawNotification.data?.[versionKeys[env.platform].max];\n return isVersionInBounds({\n currentVersion: env.platformVersion,\n minVersion,\n maxVersion,\n });\n },\n );\n\n return filteredRawNotifications;\n};\n\n/**\n * Gets Feature Announcement from our services\n *\n * @param env - environment for feature announcements\n * @param previewToken - the preview token to use if needed\n * @returns Raw Feature Announcements\n */\nexport async function getFeatureAnnouncementNotifications(\n env: Env,\n previewToken?: string,\n): Promise<INotification[]> {\n if (env?.accessToken && env?.spaceId && env?.platform) {\n const rawNotifications = await fetchFeatureAnnouncementNotifications(\n env,\n previewToken,\n );\n const notifications = rawNotifications.map((notification) =>\n processFeatureAnnouncement(notification),\n );\n\n return notifications;\n }\n\n return [];\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"feature-announcements.d.cts","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/feature-announcements.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,KAAK,EAAmB,mBAAmB;AAKhE,OAAO,KAAK,EAEV,uBAAuB,EACxB,oEAAgE;AAOjE,OAAO,KAAK,EAAE,aAAa,EAAE,+CAA2C;AAQxE,eAAO,MAAM,wBAAwB,4EAAqF,CAAC;AAC3H,eAAO,MAAM,wBAAwB,iLAAyJ,CAAC;AAE/L,KAAK,GAAG,GAAG;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,WAAW,GAAG,QAAQ,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE;QACT,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;QAChB,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;KACjB,CAAC;IACF,KAAK,CAAC,EAAE,uBAAuB,EAAE,CAAC;CACnC,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAAS,GAAG,iBAAiB,MAAM,WAUxE,CAAC;AA2HF;;;;;;GAMG;AACH,wBAAsB,mCAAmC,CACvD,GAAG,EAAE,GAAG,EACR,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,aAAa,EAAE,CAAC,CAc1B"}
1
+ {"version":3,"file":"feature-announcements.d.cts","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/feature-announcements.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,KAAK,EAAmB,mBAAmB;AAKhE,OAAO,KAAK,EAEV,uBAAuB,EACxB,oEAAgE;AAOjE,OAAO,KAAK,EAAE,aAAa,EAAE,+CAA2C;AAWxE,eAAO,MAAM,wBAAwB,4EAAqF,CAAC;AAC3H,eAAO,MAAM,wBAAwB,iLAAyJ,CAAC;AAE/L,KAAK,GAAG,GAAG;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,WAAW,GAAG,QAAQ,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE;QAGT,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;QAEhB,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;KACjB,CAAC;IACF,KAAK,CAAC,EAAE,uBAAuB,EAAE,CAAC;CACnC,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAC/B,GAAG,iBACO,MAAM,KACpB,MAUF,CAAC;AAkJF;;;;;;GAMG;AACH,wBAAsB,mCAAmC,CACvD,GAAG,EAAE,GAAG,EACR,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,aAAa,EAAE,CAAC,CAc1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"feature-announcements.d.mts","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/feature-announcements.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,KAAK,EAAmB,mBAAmB;AAKhE,OAAO,KAAK,EAEV,uBAAuB,EACxB,oEAAgE;AAOjE,OAAO,KAAK,EAAE,aAAa,EAAE,+CAA2C;AAQxE,eAAO,MAAM,wBAAwB,4EAAqF,CAAC;AAC3H,eAAO,MAAM,wBAAwB,iLAAyJ,CAAC;AAE/L,KAAK,GAAG,GAAG;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,WAAW,GAAG,QAAQ,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE;QACT,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;QAChB,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;KACjB,CAAC;IACF,KAAK,CAAC,EAAE,uBAAuB,EAAE,CAAC;CACnC,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAAS,GAAG,iBAAiB,MAAM,WAUxE,CAAC;AA2HF;;;;;;GAMG;AACH,wBAAsB,mCAAmC,CACvD,GAAG,EAAE,GAAG,EACR,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,aAAa,EAAE,CAAC,CAc1B"}
1
+ {"version":3,"file":"feature-announcements.d.mts","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/feature-announcements.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,KAAK,EAAmB,mBAAmB;AAKhE,OAAO,KAAK,EAEV,uBAAuB,EACxB,oEAAgE;AAOjE,OAAO,KAAK,EAAE,aAAa,EAAE,+CAA2C;AAWxE,eAAO,MAAM,wBAAwB,4EAAqF,CAAC;AAC3H,eAAO,MAAM,wBAAwB,iLAAyJ,CAAC;AAE/L,KAAK,GAAG,GAAG;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,WAAW,GAAG,QAAQ,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE;QAGT,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;QAEhB,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;KACjB,CAAC;IACF,KAAK,CAAC,EAAE,uBAAuB,EAAE,CAAC;CACnC,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAC/B,GAAG,iBACO,MAAM,KACpB,MAUF,CAAC;AAkJF;;;;;;GAMG;AACH,wBAAsB,mCAAmC,CACvD,GAAG,EAAE,GAAG,EACR,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,aAAa,EAAE,CAAC,CAc1B"}
@@ -2,6 +2,8 @@ import { documentToHtmlString } from "@contentful/rich-text-html-renderer";
2
2
  import { TRIGGER_TYPES } from "../constants/notification-schema.mjs";
3
3
  import { processFeatureAnnouncement } from "../processors/process-feature-announcement.mjs";
4
4
  import { isVersionInBounds } from "../utils/isVersionInBounds.mjs";
5
+ // Feature announcements older than this (by sys.updatedAt) are excluded from the feed.
6
+ const FEATURE_ANNOUNCEMENT_MAX_AGE_MONTHS = 3;
5
7
  const DEFAULT_SPACE_ID = ':space_id';
6
8
  const DEFAULT_ACCESS_TOKEN = ':access_token';
7
9
  const DEFAULT_CLIENT_ID = ':client_id';
@@ -12,7 +14,7 @@ export const FEATURE_ANNOUNCEMENT_URL = `${FEATURE_ANNOUNCEMENT_API}?access_toke
12
14
  export const getFeatureAnnouncementUrl = (env, previewToken) => {
13
15
  const domain = previewToken ? PREVIEW_DOMAIN : DEFAULT_DOMAIN;
14
16
  const replacedUrl = FEATURE_ANNOUNCEMENT_URL.replace(DEFAULT_SPACE_ID, env.spaceId)
15
- .replace(DEFAULT_ACCESS_TOKEN, previewToken || env.accessToken)
17
+ .replace(DEFAULT_ACCESS_TOKEN, previewToken ?? env.accessToken)
16
18
  .replace(DEFAULT_CLIENT_ID, env.platform)
17
19
  .replace(DEFAULT_DOMAIN, domain);
18
20
  return encodeURI(replacedUrl);
@@ -20,20 +22,27 @@ export const getFeatureAnnouncementUrl = (env, previewToken) => {
20
22
  const fetchFeatureAnnouncementNotifications = async (env, previewToken) => {
21
23
  const url = getFeatureAnnouncementUrl(env, previewToken);
22
24
  const data = await fetch(url)
23
- .then((r) => r.json())
25
+ .then((response) => response.json())
24
26
  .catch(() => null);
25
27
  if (!data) {
26
28
  return [];
27
29
  }
28
30
  const findIncludedItem = (sysId) => {
29
31
  const typedData = data;
30
- const item = typedData?.includes?.Entry?.find((i) => i?.sys?.id === sysId) ||
31
- typedData?.includes?.Asset?.find((i) => i?.sys?.id === sysId);
32
+ const item = typedData?.includes?.Entry?.find((entry) => entry?.sys?.id === sysId) ??
33
+ typedData?.includes?.Asset?.find((asset) => asset?.sys?.id === sysId);
32
34
  return item ? item?.fields : null;
33
35
  };
34
36
  const contentfulNotifications = data?.items ?? [];
35
- const rawNotifications = contentfulNotifications.map((n) => {
36
- const { fields } = n;
37
+ const rawNotifications = contentfulNotifications
38
+ .filter((item) => {
39
+ const updatedAt = new Date(item.sys.updatedAt);
40
+ const limitDate = new Date();
41
+ limitDate.setMonth(limitDate.getMonth() - FEATURE_ANNOUNCEMENT_MAX_AGE_MONTHS);
42
+ return updatedAt > limitDate;
43
+ })
44
+ .map((item) => {
45
+ const { fields } = item;
37
46
  const imageFields = fields.image
38
47
  ? findIncludedItem(fields.image.sys.id)
39
48
  : undefined;
@@ -51,7 +60,7 @@ const fetchFeatureAnnouncementNotifications = async (env, previewToken) => {
51
60
  : undefined;
52
61
  const notification = {
53
62
  type: TRIGGER_TYPES.FEATURES_ANNOUNCEMENT,
54
- createdAt: new Date(n.sys.createdAt).toString(),
63
+ createdAt: new Date(item.sys.createdAt).toString(),
55
64
  data: {
56
65
  id: fields.id,
57
66
  category: fields.category,
@@ -97,9 +106,9 @@ const fetchFeatureAnnouncementNotifications = async (env, previewToken) => {
97
106
  max: 'mobileMaximumVersionNumber',
98
107
  },
99
108
  };
100
- const filteredRawNotifications = rawNotifications.filter((n) => {
101
- const minVersion = n.data?.[versionKeys[env.platform].min];
102
- const maxVersion = n.data?.[versionKeys[env.platform].max];
109
+ const filteredRawNotifications = rawNotifications.filter((rawNotification) => {
110
+ const minVersion = rawNotification.data?.[versionKeys[env.platform].min];
111
+ const maxVersion = rawNotification.data?.[versionKeys[env.platform].max];
103
112
  return isVersionInBounds({
104
113
  currentVersion: env.platformVersion,
105
114
  minVersion,