@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.
- package/CHANGELOG.md +41 -1
- package/dist/NotificationServicesController/NotificationServicesController.cjs +56 -42
- package/dist/NotificationServicesController/NotificationServicesController.cjs.map +1 -1
- package/dist/NotificationServicesController/NotificationServicesController.d.cts +3 -2
- package/dist/NotificationServicesController/NotificationServicesController.d.cts.map +1 -1
- package/dist/NotificationServicesController/NotificationServicesController.d.mts +3 -2
- package/dist/NotificationServicesController/NotificationServicesController.d.mts.map +1 -1
- package/dist/NotificationServicesController/NotificationServicesController.mjs +56 -41
- package/dist/NotificationServicesController/NotificationServicesController.mjs.map +1 -1
- package/dist/NotificationServicesController/constants/notification-schema.cjs +4 -12
- package/dist/NotificationServicesController/constants/notification-schema.cjs.map +1 -1
- package/dist/NotificationServicesController/constants/notification-schema.d.cts +0 -12
- package/dist/NotificationServicesController/constants/notification-schema.d.cts.map +1 -1
- package/dist/NotificationServicesController/constants/notification-schema.d.mts +0 -12
- package/dist/NotificationServicesController/constants/notification-schema.d.mts.map +1 -1
- package/dist/NotificationServicesController/constants/notification-schema.mjs +3 -11
- package/dist/NotificationServicesController/constants/notification-schema.mjs.map +1 -1
- package/dist/NotificationServicesController/index.cjs +1 -2
- package/dist/NotificationServicesController/index.cjs.map +1 -1
- package/dist/NotificationServicesController/index.d.cts +0 -1
- package/dist/NotificationServicesController/index.d.cts.map +1 -1
- package/dist/NotificationServicesController/index.d.mts +0 -1
- package/dist/NotificationServicesController/index.d.mts.map +1 -1
- package/dist/NotificationServicesController/index.mjs +0 -1
- package/dist/NotificationServicesController/index.mjs.map +1 -1
- package/dist/NotificationServicesController/mocks/mock-feature-announcements.cjs +2 -2
- package/dist/NotificationServicesController/mocks/mock-feature-announcements.cjs.map +1 -1
- package/dist/NotificationServicesController/mocks/mock-feature-announcements.d.cts.map +1 -1
- package/dist/NotificationServicesController/mocks/mock-feature-announcements.d.mts.map +1 -1
- package/dist/NotificationServicesController/mocks/mock-feature-announcements.mjs +2 -2
- package/dist/NotificationServicesController/mocks/mock-feature-announcements.mjs.map +1 -1
- package/dist/NotificationServicesController/mocks/mock-raw-notifications.cjs +120 -0
- package/dist/NotificationServicesController/mocks/mock-raw-notifications.cjs.map +1 -1
- package/dist/NotificationServicesController/mocks/mock-raw-notifications.d.cts.map +1 -1
- package/dist/NotificationServicesController/mocks/mock-raw-notifications.d.mts.map +1 -1
- package/dist/NotificationServicesController/mocks/mock-raw-notifications.mjs +120 -0
- package/dist/NotificationServicesController/mocks/mock-raw-notifications.mjs.map +1 -1
- package/dist/NotificationServicesController/mocks/mock-snap-notification.cjs.map +1 -1
- package/dist/NotificationServicesController/mocks/mock-snap-notification.d.cts +1 -1
- package/dist/NotificationServicesController/mocks/mock-snap-notification.d.cts.map +1 -1
- package/dist/NotificationServicesController/mocks/mock-snap-notification.d.mts +1 -1
- package/dist/NotificationServicesController/mocks/mock-snap-notification.d.mts.map +1 -1
- package/dist/NotificationServicesController/mocks/mock-snap-notification.mjs.map +1 -1
- package/dist/NotificationServicesController/mocks/mockResponses.cjs +6 -0
- package/dist/NotificationServicesController/mocks/mockResponses.cjs.map +1 -1
- package/dist/NotificationServicesController/mocks/mockResponses.d.cts.map +1 -1
- package/dist/NotificationServicesController/mocks/mockResponses.d.mts.map +1 -1
- package/dist/NotificationServicesController/mocks/mockResponses.mjs +6 -0
- package/dist/NotificationServicesController/mocks/mockResponses.mjs.map +1 -1
- package/dist/NotificationServicesController/processors/process-notifications.cjs +11 -9
- package/dist/NotificationServicesController/processors/process-notifications.cjs.map +1 -1
- package/dist/NotificationServicesController/processors/process-notifications.d.cts +1 -563
- package/dist/NotificationServicesController/processors/process-notifications.d.cts.map +1 -1
- package/dist/NotificationServicesController/processors/process-notifications.d.mts +1 -563
- package/dist/NotificationServicesController/processors/process-notifications.d.mts.map +1 -1
- package/dist/NotificationServicesController/processors/process-notifications.mjs +11 -9
- package/dist/NotificationServicesController/processors/process-notifications.mjs.map +1 -1
- package/dist/NotificationServicesController/processors/process-snap-notifications.cjs.map +1 -1
- package/dist/NotificationServicesController/processors/process-snap-notifications.d.cts +1 -1
- package/dist/NotificationServicesController/processors/process-snap-notifications.d.cts.map +1 -1
- package/dist/NotificationServicesController/processors/process-snap-notifications.d.mts +1 -1
- package/dist/NotificationServicesController/processors/process-snap-notifications.d.mts.map +1 -1
- package/dist/NotificationServicesController/processors/process-snap-notifications.mjs.map +1 -1
- package/dist/NotificationServicesController/services/api-notifications.cjs +21 -21
- package/dist/NotificationServicesController/services/api-notifications.cjs.map +1 -1
- package/dist/NotificationServicesController/services/api-notifications.d.cts.map +1 -1
- package/dist/NotificationServicesController/services/api-notifications.d.mts.map +1 -1
- package/dist/NotificationServicesController/services/api-notifications.mjs +21 -21
- package/dist/NotificationServicesController/services/api-notifications.mjs.map +1 -1
- package/dist/NotificationServicesController/services/feature-announcements.cjs +19 -10
- package/dist/NotificationServicesController/services/feature-announcements.cjs.map +1 -1
- package/dist/NotificationServicesController/services/feature-announcements.d.cts.map +1 -1
- package/dist/NotificationServicesController/services/feature-announcements.d.mts.map +1 -1
- package/dist/NotificationServicesController/services/feature-announcements.mjs +19 -10
- package/dist/NotificationServicesController/services/feature-announcements.mjs.map +1 -1
- package/dist/NotificationServicesController/services/notification-config-cache.cjs +4 -4
- package/dist/NotificationServicesController/services/notification-config-cache.cjs.map +1 -1
- package/dist/NotificationServicesController/services/notification-config-cache.mjs +4 -4
- package/dist/NotificationServicesController/services/notification-config-cache.mjs.map +1 -1
- package/dist/NotificationServicesController/services/perp-notifications.cjs +2 -2
- package/dist/NotificationServicesController/services/perp-notifications.cjs.map +1 -1
- package/dist/NotificationServicesController/services/perp-notifications.d.cts.map +1 -1
- package/dist/NotificationServicesController/services/perp-notifications.d.mts.map +1 -1
- package/dist/NotificationServicesController/services/perp-notifications.mjs +2 -2
- package/dist/NotificationServicesController/services/perp-notifications.mjs.map +1 -1
- package/dist/NotificationServicesController/types/notification-api/notification-api.cjs.map +1 -1
- package/dist/NotificationServicesController/types/notification-api/notification-api.d.cts +2 -0
- package/dist/NotificationServicesController/types/notification-api/notification-api.d.cts.map +1 -1
- package/dist/NotificationServicesController/types/notification-api/notification-api.d.mts +2 -0
- package/dist/NotificationServicesController/types/notification-api/notification-api.d.mts.map +1 -1
- package/dist/NotificationServicesController/types/notification-api/notification-api.mjs.map +1 -1
- package/dist/NotificationServicesController/types/notification-api/schema.cjs +2 -0
- package/dist/NotificationServicesController/types/notification-api/schema.cjs.map +1 -1
- package/dist/NotificationServicesController/types/notification-api/schema.d.cts +23 -0
- package/dist/NotificationServicesController/types/notification-api/schema.d.cts.map +1 -1
- package/dist/NotificationServicesController/types/notification-api/schema.d.mts +23 -0
- package/dist/NotificationServicesController/types/notification-api/schema.d.mts.map +1 -1
- package/dist/NotificationServicesController/types/notification-api/schema.mjs +2 -0
- package/dist/NotificationServicesController/types/notification-api/schema.mjs.map +1 -1
- package/dist/NotificationServicesController/types/perps/schema.cjs +2 -0
- package/dist/NotificationServicesController/types/perps/schema.cjs.map +1 -1
- package/dist/NotificationServicesController/types/perps/schema.d.cts.map +1 -1
- package/dist/NotificationServicesController/types/perps/schema.d.mts.map +1 -1
- package/dist/NotificationServicesController/types/perps/schema.mjs +2 -0
- package/dist/NotificationServicesController/types/perps/schema.mjs.map +1 -1
- package/dist/NotificationServicesController/utils/isVersionInBounds.cjs.map +1 -1
- package/dist/NotificationServicesController/utils/isVersionInBounds.d.cts.map +1 -1
- package/dist/NotificationServicesController/utils/isVersionInBounds.d.mts.map +1 -1
- package/dist/NotificationServicesController/utils/isVersionInBounds.mjs.map +1 -1
- package/dist/NotificationServicesController/utils/should-auto-expire.cjs.map +1 -1
- package/dist/NotificationServicesController/utils/should-auto-expire.d.cts.map +1 -1
- package/dist/NotificationServicesController/utils/should-auto-expire.d.mts.map +1 -1
- package/dist/NotificationServicesController/utils/should-auto-expire.mjs.map +1 -1
- package/dist/NotificationServicesPushController/NotificationServicesPushController.cjs +0 -1
- package/dist/NotificationServicesPushController/NotificationServicesPushController.cjs.map +1 -1
- package/dist/NotificationServicesPushController/NotificationServicesPushController.d.cts +1 -1
- package/dist/NotificationServicesPushController/NotificationServicesPushController.d.cts.map +1 -1
- package/dist/NotificationServicesPushController/NotificationServicesPushController.d.mts +1 -1
- package/dist/NotificationServicesPushController/NotificationServicesPushController.d.mts.map +1 -1
- package/dist/NotificationServicesPushController/NotificationServicesPushController.mjs +0 -1
- package/dist/NotificationServicesPushController/NotificationServicesPushController.mjs.map +1 -1
- package/dist/NotificationServicesPushController/mocks/mockResponse.cjs.map +1 -1
- package/dist/NotificationServicesPushController/mocks/mockResponse.d.cts +9 -24
- package/dist/NotificationServicesPushController/mocks/mockResponse.d.cts.map +1 -1
- package/dist/NotificationServicesPushController/mocks/mockResponse.d.mts +9 -24
- package/dist/NotificationServicesPushController/mocks/mockResponse.d.mts.map +1 -1
- package/dist/NotificationServicesPushController/mocks/mockResponse.mjs.map +1 -1
- package/dist/NotificationServicesPushController/services/endpoints.cjs.map +1 -1
- package/dist/NotificationServicesPushController/services/endpoints.d.cts.map +1 -1
- package/dist/NotificationServicesPushController/services/endpoints.d.mts.map +1 -1
- package/dist/NotificationServicesPushController/services/endpoints.mjs.map +1 -1
- package/dist/NotificationServicesPushController/services/services.cjs.map +1 -1
- package/dist/NotificationServicesPushController/services/services.d.cts.map +1 -1
- package/dist/NotificationServicesPushController/services/services.d.mts.map +1 -1
- package/dist/NotificationServicesPushController/services/services.mjs.map +1 -1
- package/dist/NotificationServicesPushController/utils/get-notification-data.cjs +4 -4
- package/dist/NotificationServicesPushController/utils/get-notification-data.cjs.map +1 -1
- package/dist/NotificationServicesPushController/utils/get-notification-data.d.cts +2 -2
- package/dist/NotificationServicesPushController/utils/get-notification-data.d.cts.map +1 -1
- package/dist/NotificationServicesPushController/utils/get-notification-data.d.mts +2 -2
- package/dist/NotificationServicesPushController/utils/get-notification-data.d.mts.map +1 -1
- package/dist/NotificationServicesPushController/utils/get-notification-data.mjs +4 -4
- package/dist/NotificationServicesPushController/utils/get-notification-data.mjs.map +1 -1
- package/dist/NotificationServicesPushController/utils/get-notification-message.cjs +62 -71
- package/dist/NotificationServicesPushController/utils/get-notification-message.cjs.map +1 -1
- package/dist/NotificationServicesPushController/utils/get-notification-message.d.cts +9 -9
- package/dist/NotificationServicesPushController/utils/get-notification-message.d.cts.map +1 -1
- package/dist/NotificationServicesPushController/utils/get-notification-message.d.mts +9 -9
- package/dist/NotificationServicesPushController/utils/get-notification-message.d.mts.map +1 -1
- package/dist/NotificationServicesPushController/utils/get-notification-message.mjs +62 -71
- package/dist/NotificationServicesPushController/utils/get-notification-message.mjs.map +1 -1
- package/dist/NotificationServicesPushController/web/push-utils.cjs +15 -7
- package/dist/NotificationServicesPushController/web/push-utils.cjs.map +1 -1
- package/dist/NotificationServicesPushController/web/push-utils.d.cts.map +1 -1
- package/dist/NotificationServicesPushController/web/push-utils.d.mts.map +1 -1
- package/dist/NotificationServicesPushController/web/push-utils.mjs +16 -8
- package/dist/NotificationServicesPushController/web/push-utils.mjs.map +1 -1
- package/dist/shared/is-onchain-notification.cjs +3 -3
- package/dist/shared/is-onchain-notification.cjs.map +1 -1
- package/dist/shared/is-onchain-notification.d.cts +2 -2
- package/dist/shared/is-onchain-notification.d.cts.map +1 -1
- package/dist/shared/is-onchain-notification.d.mts +2 -2
- package/dist/shared/is-onchain-notification.d.mts.map +1 -1
- package/dist/shared/is-onchain-notification.mjs +3 -3
- package/dist/shared/is-onchain-notification.mjs.map +1 -1
- package/dist/shared/to-raw-notification.cjs.map +1 -1
- package/dist/shared/to-raw-notification.mjs.map +1 -1
- package/package.json +12 -25
- package/dist/NotificationServicesController/ui/constants.cjs +0 -75
- package/dist/NotificationServicesController/ui/constants.cjs.map +0 -1
- package/dist/NotificationServicesController/ui/constants.d.cts +0 -66
- package/dist/NotificationServicesController/ui/constants.d.cts.map +0 -1
- package/dist/NotificationServicesController/ui/constants.d.mts +0 -66
- package/dist/NotificationServicesController/ui/constants.d.mts.map +0 -1
- package/dist/NotificationServicesController/ui/constants.mjs +0 -71
- package/dist/NotificationServicesController/ui/constants.mjs.map +0 -1
- package/dist/NotificationServicesController/ui/index.cjs +0 -18
- package/dist/NotificationServicesController/ui/index.cjs.map +0 -1
- package/dist/NotificationServicesController/ui/index.d.cts +0 -2
- package/dist/NotificationServicesController/ui/index.d.cts.map +0 -1
- package/dist/NotificationServicesController/ui/index.d.mts +0 -2
- package/dist/NotificationServicesController/ui/index.d.mts.map +0 -1
- package/dist/NotificationServicesController/ui/index.mjs +0 -2
- package/dist/NotificationServicesController/ui/index.mjs.map +0 -1
- package/dist/NotificationServicesPushController/services/push/push-web.cjs +0 -145
- package/dist/NotificationServicesPushController/services/push/push-web.cjs.map +0 -1
- package/dist/NotificationServicesPushController/services/push/push-web.d.cts +0 -34
- package/dist/NotificationServicesPushController/services/push/push-web.d.cts.map +0 -1
- package/dist/NotificationServicesPushController/services/push/push-web.d.mts +0 -34
- package/dist/NotificationServicesPushController/services/push/push-web.d.mts.map +0 -1
- package/dist/NotificationServicesPushController/services/push/push-web.mjs +0 -142
- package/dist/NotificationServicesPushController/services/push/push-web.mjs.map +0 -1
- 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 {
|
|
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
|
-
//
|
|
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
|
-
|
|
52
|
-
const cached = notification_config_cache_1.notificationsConfigCache.get(
|
|
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 =
|
|
57
|
-
const
|
|
58
|
-
.then((
|
|
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 =
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
});
|
|
83
|
-
const body =
|
|
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(
|
|
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((
|
|
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((
|
|
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((
|
|
114
|
-
if (!
|
|
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)(
|
|
118
|
+
return (0, to_raw_notification_1.toRawAPINotification)(notification);
|
|
119
119
|
}
|
|
120
120
|
catch {
|
|
121
121
|
return undefined;
|
|
122
122
|
}
|
|
123
123
|
})
|
|
124
|
-
.filter((
|
|
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 (
|
|
149
|
-
loglevel_1.default.error('Error marking notifications as read:',
|
|
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,
|
|
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,
|
|
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
|
-
//
|
|
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
|
-
|
|
47
|
-
const cached = notificationsConfigCache.get(
|
|
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 =
|
|
52
|
-
const
|
|
53
|
-
.then((
|
|
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 =
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
});
|
|
77
|
-
const body =
|
|
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(
|
|
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((
|
|
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((
|
|
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((
|
|
107
|
-
if (!
|
|
106
|
+
?.map((notification) => {
|
|
107
|
+
if (!notification.notification_type) {
|
|
108
108
|
return undefined;
|
|
109
109
|
}
|
|
110
110
|
try {
|
|
111
|
-
return toRawAPINotification(
|
|
111
|
+
return toRawAPINotification(notification);
|
|
112
112
|
}
|
|
113
113
|
catch {
|
|
114
114
|
return undefined;
|
|
115
115
|
}
|
|
116
116
|
})
|
|
117
|
-
.filter((
|
|
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 (
|
|
141
|
-
log.error('Error marking notifications as read:',
|
|
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":"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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.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
|
|
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((
|
|
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((
|
|
35
|
-
typedData?.includes?.Asset?.find((
|
|
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
|
|
40
|
-
|
|
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(
|
|
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((
|
|
105
|
-
const minVersion =
|
|
106
|
-
const maxVersion =
|
|
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":";;;AAAA,iFAA2E;AAG3E,8EAAiE;AACjE,iGAAwF;AAaxF,sEAA+D;AAE/D,uFAAuF;AACvF,MAAM,mCAAmC,GAAG,CAAC,CAAC;AAE9C,MAAM,gBAAgB,GAAG,WAAW,CAAC;AACrC,MAAM,oBAAoB,GAAG,eAAe,CAAC;AAC7C,MAAM,iBAAiB,GAAG,YAAY,CAAC;AACvC,MAAM,cAAc,GAAG,oBAAoB,CAAC;AAC5C,MAAM,cAAc,GAAG,wBAAwB,CAAC;AACnC,QAAA,wBAAwB,GAAG,WAAW,cAAc,WAAW,gBAAgB,8BAA8B,CAAC;AAC9G,QAAA,wBAAwB,GAAG,GAAG,gCAAwB,iBAAiB,oBAAoB,mEAAmE,iBAAiB,EAAE,CAAC;AAuBxL,MAAM,yBAAyB,GAAG,CACvC,GAAQ,EACR,YAAqB,EACb,EAAE;IACV,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC;IAC9D,MAAM,WAAW,GAAG,gCAAwB,CAAC,OAAO,CAClD,gBAAgB,EAChB,GAAG,CAAC,OAAO,CACZ;SACE,OAAO,CAAC,oBAAoB,EAAE,YAAY,IAAI,GAAG,CAAC,WAAW,CAAC;SAC9D,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,QAAQ,CAAC;SACxC,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO,SAAS,CAAC,WAAW,CAAC,CAAC;AAChC,CAAC,CAAC;AAbW,QAAA,yBAAyB,6BAapC;AAEF,MAAM,qCAAqC,GAAG,KAAK,EACjD,GAAQ,EACR,YAAqB,EAC0B,EAAE;IACjD,MAAM,GAAG,GAAG,IAAA,iCAAyB,EAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAEzD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC;SAC1B,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;SACnC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAErB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,gBAAgB,GAAG,CACvB,KAAa,EAON,EAAE;QACT,MAAM,SAAS,GAMX,IAAI,CAAC;QACT,MAAM,IAAI,GACR,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAC9B,CAAC,KAAY,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,KAAK,KAAK,CAC3C;YACD,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAC9B,CAAC,KAAY,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,KAAK,KAAK,CAC3C,CAAC;QACJ,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IACpC,CAAC,CAAC;IAEF,MAAM,uBAAuB,GAAG,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;IAClD,MAAM,gBAAgB,GACpB,uBAAuB;SACpB,MAAM,CAAC,CAAC,IAA6B,EAAE,EAAE;QACxC,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;QAC7B,SAAS,CAAC,QAAQ,CAChB,SAAS,CAAC,QAAQ,EAAE,GAAG,mCAAmC,CAC3D,CAAC;QACF,OAAO,SAAS,GAAG,SAAS,CAAC;IAC/B,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,IAA6B,EAAE,EAAE;QACrC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACxB,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK;YAC9B,CAAC,CAAE,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAA2B;YAClE,CAAC,CAAC,SAAS,CAAC;QAEd,MAAM,kBAAkB,GAAG,MAAM,CAAC,YAAY;YAC5C,CAAC,CAAE,gBAAgB,CACf,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CACU;YACxC,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,mBAAmB,GAAG,MAAM,CAAC,aAAa;YAC9C,CAAC,CAAE,gBAAgB,CACf,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CACU;YACzC,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,mBAAmB,GAAG,MAAM,CAAC,aAAa;YAC9C,CAAC,CAAE,gBAAgB,CACf,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CACU;YACzC,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,gBAAgB,GAAG,MAAM,CAAC,UAAU;YACxC,CAAC,CAAE,gBAAgB,CACf,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CACU;YACtC,CAAC,CAAC,SAAS,CAAC;QAEd,MAAM,YAAY,GAAuC;YACvD,IAAI,EAAE,mCAAa,CAAC,qBAAqB;YACzC,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE;YAClD,IAAI,EAAE;gBACJ,EAAE,EAAE,MAAM,CAAC,EAAE;gBACb,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,eAAe,EAAE,IAAA,8CAAoB,EAAC,MAAM,CAAC,eAAe,CAAC;gBAC7D,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;gBACzC,KAAK,EAAE;oBACL,KAAK,EAAE,WAAW,EAAE,KAAK;oBACzB,WAAW,EAAE,WAAW,EAAE,WAAW;oBACrC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE;iBAClC;gBACD,YAAY,EAAE,kBAAkB,IAAI;oBAClC,gBAAgB,EAAE,kBAAkB,EAAE,gBAAgB;oBACtD,eAAe,EAAE,kBAAkB,EAAE,eAAe;iBACrD;gBACD,aAAa,EAAE,mBAAmB,IAAI;oBACpC,iBAAiB,EAAE,mBAAmB,EAAE,iBAAiB;oBACzD,gBAAgB,EAAE,mBAAmB,EAAE,gBAAgB;iBACxD;gBACD,aAAa,EAAE,mBAAmB,IAAI;oBACpC,iBAAiB,EAAE,mBAAmB,EAAE,iBAAiB;oBACzD,kBAAkB,EAAE,mBAAmB,EAAE,kBAAkB;iBAC5D;gBACD,UAAU,EAAE,gBAAgB,IAAI;oBAC9B,cAAc,EAAE,gBAAgB,EAAE,cAAc;oBAChD,aAAa,EAAE,gBAAgB,EAAE,aAAa;iBAC/C;gBACD,6BAA6B,EAAE,MAAM,CAAC,6BAA6B;gBACnE,0BAA0B,EAAE,MAAM,CAAC,0BAA0B;gBAC7D,6BAA6B,EAAE,MAAM,CAAC,6BAA6B;gBACnE,0BAA0B,EAAE,MAAM,CAAC,0BAA0B;aAC9D;SACF,CAAC;QAEF,OAAO,YAAY,CAAC;IACtB,CAAC,CAAC,CAAC;IAEP,MAAM,WAAW,GAAG;QAClB,SAAS,EAAE;YACT,GAAG,EAAE,+BAA+B;YACpC,GAAG,EAAE,+BAA+B;SACrC;QACD,MAAM,EAAE;YACN,GAAG,EAAE,4BAA4B;YACjC,GAAG,EAAE,4BAA4B;SAClC;KACO,CAAC;IAEX,MAAM,wBAAwB,GAAG,gBAAgB,CAAC,MAAM,CACtD,CAAC,eAAe,EAAE,EAAE;QAClB,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;QACzE,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;QACzE,OAAO,IAAA,qCAAiB,EAAC;YACvB,cAAc,EAAE,GAAG,CAAC,eAAe;YACnC,UAAU;YACV,UAAU;SACX,CAAC,CAAC;IACL,CAAC,CACF,CAAC;IAEF,OAAO,wBAAwB,CAAC;AAClC,CAAC,CAAC;AAEF;;;;;;GAMG;AACI,KAAK,UAAU,mCAAmC,CACvD,GAAQ,EACR,YAAqB;IAErB,IAAI,GAAG,EAAE,WAAW,IAAI,GAAG,EAAE,OAAO,IAAI,GAAG,EAAE,QAAQ,EAAE,CAAC;QACtD,MAAM,gBAAgB,GAAG,MAAM,qCAAqC,CAClE,GAAG,EACH,YAAY,CACb,CAAC;QACF,MAAM,aAAa,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAC1D,IAAA,yDAA0B,EAAC,YAAY,CAAC,CACzC,CAAC;QAEF,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAjBD,kFAiBC","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;
|
|
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;
|
|
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
|
|
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((
|
|
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((
|
|
31
|
-
typedData?.includes?.Asset?.find((
|
|
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
|
|
36
|
-
|
|
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(
|
|
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((
|
|
101
|
-
const minVersion =
|
|
102
|
-
const maxVersion =
|
|
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,
|