@metamask-previews/notification-services-controller 24.1.2-preview-81b5f29eb → 24.1.2-preview-513faa49e
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 +0 -17
- package/dist/NotificationServicesController/NotificationServicesController.cjs +2 -4
- package/dist/NotificationServicesController/NotificationServicesController.cjs.map +1 -1
- package/dist/NotificationServicesController/NotificationServicesController.d.cts.map +1 -1
- package/dist/NotificationServicesController/NotificationServicesController.d.mts.map +1 -1
- package/dist/NotificationServicesController/NotificationServicesController.mjs +2 -4
- package/dist/NotificationServicesController/NotificationServicesController.mjs.map +1 -1
- package/dist/NotificationServicesController/index.cjs +1 -3
- 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/processors/process-api-notifications.cjs +0 -2
- package/dist/NotificationServicesController/processors/process-api-notifications.cjs.map +1 -1
- package/dist/NotificationServicesController/processors/process-api-notifications.d.cts.map +1 -1
- package/dist/NotificationServicesController/processors/process-api-notifications.d.mts.map +1 -1
- package/dist/NotificationServicesController/processors/process-api-notifications.mjs +0 -2
- package/dist/NotificationServicesController/processors/process-api-notifications.mjs.map +1 -1
- package/dist/NotificationServicesController/processors/process-feature-announcement.cjs +0 -2
- package/dist/NotificationServicesController/processors/process-feature-announcement.cjs.map +1 -1
- package/dist/NotificationServicesController/processors/process-feature-announcement.d.cts.map +1 -1
- package/dist/NotificationServicesController/processors/process-feature-announcement.d.mts.map +1 -1
- package/dist/NotificationServicesController/processors/process-feature-announcement.mjs +0 -2
- package/dist/NotificationServicesController/processors/process-feature-announcement.mjs.map +1 -1
- package/dist/NotificationServicesController/processors/process-snap-notifications.cjs +0 -2
- package/dist/NotificationServicesController/processors/process-snap-notifications.cjs.map +1 -1
- package/dist/NotificationServicesController/processors/process-snap-notifications.d.cts.map +1 -1
- package/dist/NotificationServicesController/processors/process-snap-notifications.d.mts.map +1 -1
- package/dist/NotificationServicesController/processors/process-snap-notifications.mjs +0 -2
- package/dist/NotificationServicesController/processors/process-snap-notifications.mjs.map +1 -1
- package/dist/NotificationServicesController/types/notification/notification.cjs.map +1 -1
- package/dist/NotificationServicesController/types/notification/notification.d.cts +0 -1
- package/dist/NotificationServicesController/types/notification/notification.d.cts.map +1 -1
- package/dist/NotificationServicesController/types/notification/notification.d.mts +0 -1
- package/dist/NotificationServicesController/types/notification/notification.d.mts.map +1 -1
- package/dist/NotificationServicesController/types/notification/notification.mjs.map +1 -1
- package/dist/NotificationServicesPushController/NotificationServicesPushController.cjs.map +1 -1
- package/dist/NotificationServicesPushController/NotificationServicesPushController.d.cts +4 -3
- package/dist/NotificationServicesPushController/NotificationServicesPushController.d.cts.map +1 -1
- package/dist/NotificationServicesPushController/NotificationServicesPushController.d.mts +4 -3
- package/dist/NotificationServicesPushController/NotificationServicesPushController.d.mts.map +1 -1
- package/dist/NotificationServicesPushController/NotificationServicesPushController.mjs.map +1 -1
- package/dist/NotificationServicesPushController/types/index.cjs.map +1 -1
- package/dist/NotificationServicesPushController/types/index.d.cts +0 -1
- package/dist/NotificationServicesPushController/types/index.d.cts.map +1 -1
- package/dist/NotificationServicesPushController/types/index.d.mts +0 -1
- package/dist/NotificationServicesPushController/types/index.d.mts.map +1 -1
- package/dist/NotificationServicesPushController/types/index.mjs.map +1 -1
- package/dist/NotificationServicesPushController/utils/index.cjs +0 -1
- package/dist/NotificationServicesPushController/utils/index.cjs.map +1 -1
- package/dist/NotificationServicesPushController/utils/index.d.cts +0 -1
- package/dist/NotificationServicesPushController/utils/index.d.cts.map +1 -1
- package/dist/NotificationServicesPushController/utils/index.d.mts +0 -1
- package/dist/NotificationServicesPushController/utils/index.d.mts.map +1 -1
- package/dist/NotificationServicesPushController/utils/index.mjs +0 -1
- package/dist/NotificationServicesPushController/utils/index.mjs.map +1 -1
- package/dist/NotificationServicesPushController/web/push-utils.cjs +25 -13
- package/dist/NotificationServicesPushController/web/push-utils.cjs.map +1 -1
- package/dist/NotificationServicesPushController/web/push-utils.d.cts +3 -3
- package/dist/NotificationServicesPushController/web/push-utils.d.cts.map +1 -1
- package/dist/NotificationServicesPushController/web/push-utils.d.mts +3 -3
- package/dist/NotificationServicesPushController/web/push-utils.d.mts.map +1 -1
- package/dist/NotificationServicesPushController/web/push-utils.mjs +25 -13
- package/dist/NotificationServicesPushController/web/push-utils.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/NotificationServicesController/utils/get-notification-subtype.cjs +0 -49
- package/dist/NotificationServicesController/utils/get-notification-subtype.cjs.map +0 -1
- package/dist/NotificationServicesController/utils/get-notification-subtype.d.cts +0 -22
- package/dist/NotificationServicesController/utils/get-notification-subtype.d.cts.map +0 -1
- package/dist/NotificationServicesController/utils/get-notification-subtype.d.mts +0 -22
- package/dist/NotificationServicesController/utils/get-notification-subtype.d.mts.map +0 -1
- package/dist/NotificationServicesController/utils/get-notification-subtype.mjs +0 -45
- package/dist/NotificationServicesController/utils/get-notification-subtype.mjs.map +0 -1
- package/dist/NotificationServicesPushController/types/push-analytics.cjs +0 -5
- package/dist/NotificationServicesPushController/types/push-analytics.cjs.map +0 -1
- package/dist/NotificationServicesPushController/types/push-analytics.d.cts +0 -20
- package/dist/NotificationServicesPushController/types/push-analytics.d.cts.map +0 -1
- package/dist/NotificationServicesPushController/types/push-analytics.d.mts +0 -20
- package/dist/NotificationServicesPushController/types/push-analytics.d.mts.map +0 -1
- package/dist/NotificationServicesPushController/types/push-analytics.mjs +0 -4
- package/dist/NotificationServicesPushController/types/push-analytics.mjs.map +0 -1
- package/dist/NotificationServicesPushController/utils/to-push-analytics-payload.cjs +0 -27
- package/dist/NotificationServicesPushController/utils/to-push-analytics-payload.cjs.map +0 -1
- package/dist/NotificationServicesPushController/utils/to-push-analytics-payload.d.cts +0 -12
- package/dist/NotificationServicesPushController/utils/to-push-analytics-payload.d.cts.map +0 -1
- package/dist/NotificationServicesPushController/utils/to-push-analytics-payload.d.mts +0 -12
- package/dist/NotificationServicesPushController/utils/to-push-analytics-payload.d.mts.map +0 -1
- package/dist/NotificationServicesPushController/utils/to-push-analytics-payload.mjs +0 -23
- package/dist/NotificationServicesPushController/utils/to-push-analytics-payload.mjs.map +0 -1
|
@@ -8,7 +8,8 @@ const app_1 = require("firebase/app");
|
|
|
8
8
|
const messaging_1 = require("firebase/messaging");
|
|
9
9
|
const sw_1 = require("firebase/messaging/sw");
|
|
10
10
|
const loglevel_1 = __importDefault(require("loglevel"));
|
|
11
|
-
const
|
|
11
|
+
const NotificationServicesController_1 = require("../../NotificationServicesController/index.cjs");
|
|
12
|
+
const to_raw_notification_1 = require("../../shared/to-raw-notification.cjs");
|
|
12
13
|
// Exported to help testing
|
|
13
14
|
// eslint-disable-next-line import-x/no-mutable-exports
|
|
14
15
|
exports.supportedCache = null;
|
|
@@ -103,16 +104,27 @@ async function listenToPushNotificationsReceived(env, handler) {
|
|
|
103
104
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
104
105
|
async (payload) => {
|
|
105
106
|
try {
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
// MessagePayload shapes are not known
|
|
108
|
+
// TODO - provide open-api unfied backend/frontend types
|
|
109
|
+
// TODO - we will replace the underlying Data payload with the same Notification payload used by mobile
|
|
110
|
+
const data = JSON.parse(payload?.data?.data ?? 'null');
|
|
111
|
+
if (!data) {
|
|
108
112
|
return;
|
|
109
113
|
}
|
|
110
|
-
|
|
114
|
+
if (!(0, NotificationServicesController_1.isOnChainRawNotification)(data)) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const notificationData = (0, to_raw_notification_1.toRawAPINotification)(data);
|
|
118
|
+
const notification = (0, NotificationServicesController_1.safeProcessNotification)(notificationData);
|
|
119
|
+
if (!notification) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
await handler?.(notification);
|
|
111
123
|
}
|
|
112
124
|
catch (error) {
|
|
113
|
-
// Do Nothing, cannot
|
|
114
|
-
loglevel_1.default.error('Unable to
|
|
115
|
-
notification: payload?.data,
|
|
125
|
+
// Do Nothing, cannot parse a bad notification
|
|
126
|
+
loglevel_1.default.error('Unable to send push notification:', {
|
|
127
|
+
notification: payload?.data?.data,
|
|
116
128
|
error,
|
|
117
129
|
});
|
|
118
130
|
}
|
|
@@ -150,13 +162,13 @@ function listenToPushNotificationsClicked(handler) {
|
|
|
150
162
|
*/
|
|
151
163
|
function createSubscribeToPushNotifications(props) {
|
|
152
164
|
return async function (env) {
|
|
153
|
-
const onBackgroundMessageSub = await listenToPushNotificationsReceived(env, async (
|
|
154
|
-
props.messenger.publish('NotificationServicesPushController:onNewNotifications',
|
|
155
|
-
await props.onReceivedHandler(
|
|
165
|
+
const onBackgroundMessageSub = await listenToPushNotificationsReceived(env, async (notification) => {
|
|
166
|
+
props.messenger.publish('NotificationServicesPushController:onNewNotifications', notification);
|
|
167
|
+
await props.onReceivedHandler(notification);
|
|
156
168
|
});
|
|
157
|
-
const onClickSub = listenToPushNotificationsClicked((event,
|
|
158
|
-
props.messenger.publish('NotificationServicesPushController:pushNotificationClicked',
|
|
159
|
-
props.onClickHandler(event,
|
|
169
|
+
const onClickSub = listenToPushNotificationsClicked((event, notification) => {
|
|
170
|
+
props.messenger.publish('NotificationServicesPushController:pushNotificationClicked', notification);
|
|
171
|
+
props.onClickHandler(event, notification);
|
|
160
172
|
});
|
|
161
173
|
const unsubscribe = () => {
|
|
162
174
|
onBackgroundMessageSub?.();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push-utils.cjs","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/web/push-utils.ts"],"names":[],"mappings":"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","sourcesContent":["// We are defining that this file uses a webworker global scope.\n// eslint-disable-next-line spaced-comment\n/// <reference lib=\"webworker\" />\nimport type { FirebaseApp } from 'firebase/app';\nimport { getApp, initializeApp } from 'firebase/app';\nimport { getToken, deleteToken } from 'firebase/messaging';\nimport {\n getMessaging,\n onBackgroundMessage,\n isSupported,\n} from 'firebase/messaging/sw';\nimport type { Messaging, MessagePayload } from 'firebase/messaging/sw';\nimport log from 'loglevel';\n\nimport type { NotificationServicesPushControllerMessenger } from '../NotificationServicesPushController';\nimport type { PushAnalyticsPayload } from '../types';\nimport type { PushNotificationEnv } from '../types/firebase';\nimport { toPushAnalyticsPayload } from '../utils/to-push-analytics-payload';\n\ndeclare const self: ServiceWorkerGlobalScope;\n\n// Exported to help testing\n// eslint-disable-next-line import-x/no-mutable-exports\nexport let supportedCache: boolean | null = null;\n\nconst getPushAvailability = async (): Promise<boolean> => {\n // Race condition is acceptable here - worst case is isSupported() is called\n // multiple times during initialization, which is harmless for caching a boolean\n // eslint-disable-next-line require-atomic-updates\n supportedCache ??= await isSupported();\n return supportedCache;\n};\n\nconst createFirebaseApp = async (\n env: PushNotificationEnv,\n): Promise<FirebaseApp> => {\n try {\n return getApp();\n } catch {\n const firebaseConfig = {\n apiKey: env.apiKey,\n authDomain: env.authDomain,\n storageBucket: env.storageBucket,\n projectId: env.projectId,\n messagingSenderId: env.messagingSenderId,\n appId: env.appId,\n measurementId: env.measurementId,\n };\n return initializeApp(firebaseConfig);\n }\n};\n\nconst getFirebaseMessaging = async (\n env: PushNotificationEnv,\n): Promise<Messaging | null> => {\n const supported = await getPushAvailability();\n if (!supported) {\n return null;\n }\n\n const app = await createFirebaseApp(env);\n return getMessaging(app);\n};\n\n/**\n * Creates a registration token for Firebase Cloud Messaging.\n *\n * @param env - env to configure push notifications\n * @returns A promise that resolves with the registration token or null if an error occurs.\n */\nexport async function createRegToken(\n env: PushNotificationEnv,\n): Promise<string | null> {\n try {\n const messaging = await getFirebaseMessaging(env);\n if (!messaging) {\n return null;\n }\n\n const token = await getToken(messaging, {\n serviceWorkerRegistration: self.registration,\n vapidKey: env.vapidKey,\n });\n return token;\n } catch {\n return null;\n }\n}\n\n/**\n * Deletes the Firebase Cloud Messaging registration token.\n *\n * @param env - env to configure push notifications\n * @returns A promise that resolves with true if the token was successfully deleted, false otherwise.\n */\nexport async function deleteRegToken(\n env: PushNotificationEnv,\n): Promise<boolean> {\n try {\n const messaging = await getFirebaseMessaging(env);\n if (!messaging) {\n return true;\n }\n\n await deleteToken(messaging);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Service Worker Listener for when push notifications are received.\n *\n * @param env - push notification environment\n * @param handler - handler to actually showing notification, MUST BE PROVIDED\n * @returns unsubscribe handler\n */\nasync function listenToPushNotificationsReceived(\n env: PushNotificationEnv,\n handler?: (payload: PushAnalyticsPayload) => void | Promise<void>,\n): Promise<(() => void) | null> {\n const messaging = await getFirebaseMessaging(env);\n if (!messaging) {\n return null;\n }\n\n const unsubscribePushNotifications = onBackgroundMessage(\n messaging,\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async (payload: MessagePayload): Promise<void> => {\n try {\n const analyticsPayload = toPushAnalyticsPayload(payload?.data);\n\n if (!analyticsPayload) {\n return;\n }\n\n await handler?.(analyticsPayload);\n } catch (error) {\n // Do Nothing, cannot handle a bad notification\n log.error('Unable to handle push notification:', {\n notification: payload?.data,\n error,\n });\n }\n },\n );\n\n const unsubscribe = (): void => unsubscribePushNotifications();\n return unsubscribe;\n}\n\n/**\n * Service Worker Listener for when a notification is clicked\n *\n * @param handler - listen to NotificationEvent from the service worker\n * @returns unsubscribe handler\n */\nfunction listenToPushNotificationsClicked(\n handler: (e: NotificationEvent, payload: PushAnalyticsPayload) => void,\n): () => void {\n const clickHandler = (event: NotificationEvent): void => {\n // Get Data\n const data: PushAnalyticsPayload = event?.notification?.data;\n handler(event, data);\n };\n\n self.addEventListener('notificationclick', clickHandler);\n const unsubscribe = (): void =>\n self.removeEventListener('notificationclick', clickHandler);\n return unsubscribe;\n}\n\n/**\n * A creator function that assists creating web-specific push notification subscription:\n * 1. Creates subscriptions for receiving and clicking notifications\n * 2. Creates click events when a notification is clicked\n * 3. Publishes controller messenger events\n *\n * @param props - props for this creator function.\n * @param props.onReceivedHandler - allows the developer to handle showing a notification\n * @param props.onClickHandler - allows the developer to handle clicking the notification\n * @param props.messenger - the controller messenger to publish the `onNewNotifications` and `pushNotificationsClicked` events\n * @returns a function that can be used by the controller\n */\nexport function createSubscribeToPushNotifications(props: {\n onReceivedHandler: (payload: PushAnalyticsPayload) => void | Promise<void>;\n onClickHandler: (e: NotificationEvent, payload: PushAnalyticsPayload) => void;\n messenger: NotificationServicesPushControllerMessenger;\n}): (env: PushNotificationEnv) => Promise<() => void> {\n return async function (env: PushNotificationEnv): Promise<() => void> {\n const onBackgroundMessageSub = await listenToPushNotificationsReceived(\n env,\n async (analyticsPayload): Promise<void> => {\n props.messenger.publish(\n 'NotificationServicesPushController:onNewNotifications',\n analyticsPayload,\n );\n await props.onReceivedHandler(analyticsPayload);\n },\n );\n const onClickSub = listenToPushNotificationsClicked(\n (event, analyticsPayload): void => {\n props.messenger.publish(\n 'NotificationServicesPushController:pushNotificationClicked',\n analyticsPayload,\n );\n props.onClickHandler(event, analyticsPayload);\n },\n );\n\n const unsubscribe = (): void => {\n onBackgroundMessageSub?.();\n onClickSub();\n };\n\n return unsubscribe;\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"push-utils.cjs","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/web/push-utils.ts"],"names":[],"mappings":"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","sourcesContent":["// We are defining that this file uses a webworker global scope.\n// eslint-disable-next-line spaced-comment\n/// <reference lib=\"webworker\" />\nimport type { FirebaseApp } from 'firebase/app';\nimport { getApp, initializeApp } from 'firebase/app';\nimport { getToken, deleteToken } from 'firebase/messaging';\nimport {\n getMessaging,\n onBackgroundMessage,\n isSupported,\n} from 'firebase/messaging/sw';\nimport type { Messaging, MessagePayload } from 'firebase/messaging/sw';\nimport log from 'loglevel';\n\nimport type { Types } from '../../NotificationServicesController';\nimport {\n isOnChainRawNotification,\n safeProcessNotification,\n} from '../../NotificationServicesController';\nimport { toRawAPINotification } from '../../shared/to-raw-notification';\nimport type { NotificationServicesPushControllerMessenger } from '../NotificationServicesPushController';\nimport type { PushNotificationEnv } from '../types/firebase';\n\ndeclare const self: ServiceWorkerGlobalScope;\n\n// Exported to help testing\n// eslint-disable-next-line import-x/no-mutable-exports\nexport let supportedCache: boolean | null = null;\n\nconst getPushAvailability = async (): Promise<boolean> => {\n // Race condition is acceptable here - worst case is isSupported() is called\n // multiple times during initialization, which is harmless for caching a boolean\n // eslint-disable-next-line require-atomic-updates\n supportedCache ??= await isSupported();\n return supportedCache;\n};\n\nconst createFirebaseApp = async (\n env: PushNotificationEnv,\n): Promise<FirebaseApp> => {\n try {\n return getApp();\n } catch {\n const firebaseConfig = {\n apiKey: env.apiKey,\n authDomain: env.authDomain,\n storageBucket: env.storageBucket,\n projectId: env.projectId,\n messagingSenderId: env.messagingSenderId,\n appId: env.appId,\n measurementId: env.measurementId,\n };\n return initializeApp(firebaseConfig);\n }\n};\n\nconst getFirebaseMessaging = async (\n env: PushNotificationEnv,\n): Promise<Messaging | null> => {\n const supported = await getPushAvailability();\n if (!supported) {\n return null;\n }\n\n const app = await createFirebaseApp(env);\n return getMessaging(app);\n};\n\n/**\n * Creates a registration token for Firebase Cloud Messaging.\n *\n * @param env - env to configure push notifications\n * @returns A promise that resolves with the registration token or null if an error occurs.\n */\nexport async function createRegToken(\n env: PushNotificationEnv,\n): Promise<string | null> {\n try {\n const messaging = await getFirebaseMessaging(env);\n if (!messaging) {\n return null;\n }\n\n const token = await getToken(messaging, {\n serviceWorkerRegistration: self.registration,\n vapidKey: env.vapidKey,\n });\n return token;\n } catch {\n return null;\n }\n}\n\n/**\n * Deletes the Firebase Cloud Messaging registration token.\n *\n * @param env - env to configure push notifications\n * @returns A promise that resolves with true if the token was successfully deleted, false otherwise.\n */\nexport async function deleteRegToken(\n env: PushNotificationEnv,\n): Promise<boolean> {\n try {\n const messaging = await getFirebaseMessaging(env);\n if (!messaging) {\n return true;\n }\n\n await deleteToken(messaging);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Service Worker Listener for when push notifications are received.\n *\n * @param env - push notification environment\n * @param handler - handler to actually showing notification, MUST BE PROVIDED\n * @returns unsubscribe handler\n */\nasync function listenToPushNotificationsReceived(\n env: PushNotificationEnv,\n handler?: (notification: Types.INotification) => void | Promise<void>,\n): Promise<(() => void) | null> {\n const messaging = await getFirebaseMessaging(env);\n if (!messaging) {\n return null;\n }\n\n const unsubscribePushNotifications = onBackgroundMessage(\n messaging,\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async (payload: MessagePayload): Promise<void> => {\n try {\n // MessagePayload shapes are not known\n // TODO - provide open-api unfied backend/frontend types\n // TODO - we will replace the underlying Data payload with the same Notification payload used by mobile\n const data: unknown | null = JSON.parse(payload?.data?.data ?? 'null');\n\n if (!data) {\n return;\n }\n\n if (!isOnChainRawNotification(data)) {\n return;\n }\n\n const notificationData = toRawAPINotification(data);\n const notification = safeProcessNotification(notificationData);\n\n if (!notification) {\n return;\n }\n\n await handler?.(notification);\n } catch (error) {\n // Do Nothing, cannot parse a bad notification\n log.error('Unable to send push notification:', {\n notification: payload?.data?.data,\n error,\n });\n }\n },\n );\n\n const unsubscribe = (): void => unsubscribePushNotifications();\n return unsubscribe;\n}\n\n/**\n * Service Worker Listener for when a notification is clicked\n *\n * @param handler - listen to NotificationEvent from the service worker\n * @returns unsubscribe handler\n */\nfunction listenToPushNotificationsClicked(\n handler: (e: NotificationEvent, notification: Types.INotification) => void,\n): () => void {\n const clickHandler = (event: NotificationEvent): void => {\n // Get Data\n const data: Types.INotification = event?.notification?.data;\n handler(event, data);\n };\n\n self.addEventListener('notificationclick', clickHandler);\n const unsubscribe = (): void =>\n self.removeEventListener('notificationclick', clickHandler);\n return unsubscribe;\n}\n\n/**\n * A creator function that assists creating web-specific push notification subscription:\n * 1. Creates subscriptions for receiving and clicking notifications\n * 2. Creates click events when a notification is clicked\n * 3. Publishes controller messenger events\n *\n * @param props - props for this creator function.\n * @param props.onReceivedHandler - allows the developer to handle showing a notification\n * @param props.onClickHandler - allows the developer to handle clicking the notification\n * @param props.messenger - the controller messenger to publish the `onNewNotifications` and `pushNotificationsClicked` events\n * @returns a function that can be used by the controller\n */\nexport function createSubscribeToPushNotifications(props: {\n onReceivedHandler: (\n notification: Types.INotification,\n ) => void | Promise<void>;\n onClickHandler: (\n e: NotificationEvent,\n notification: Types.INotification,\n ) => void;\n messenger: NotificationServicesPushControllerMessenger;\n}): (env: PushNotificationEnv) => Promise<() => void> {\n return async function (env: PushNotificationEnv): Promise<() => void> {\n const onBackgroundMessageSub = await listenToPushNotificationsReceived(\n env,\n async (notification): Promise<void> => {\n props.messenger.publish(\n 'NotificationServicesPushController:onNewNotifications',\n notification,\n );\n await props.onReceivedHandler(notification);\n },\n );\n const onClickSub = listenToPushNotificationsClicked(\n (event, notification): void => {\n props.messenger.publish(\n 'NotificationServicesPushController:pushNotificationClicked',\n notification,\n );\n props.onClickHandler(event, notification);\n },\n );\n\n const unsubscribe = (): void => {\n onBackgroundMessageSub?.();\n onClickSub();\n };\n\n return unsubscribe;\n };\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference lib="webworker" />
|
|
2
|
+
import type { Types } from "../../NotificationServicesController/index.cjs";
|
|
2
3
|
import type { NotificationServicesPushControllerMessenger } from "../NotificationServicesPushController.cjs";
|
|
3
|
-
import type { PushAnalyticsPayload } from "../types/index.cjs";
|
|
4
4
|
import type { PushNotificationEnv } from "../types/firebase.cjs";
|
|
5
5
|
export declare let supportedCache: boolean | null;
|
|
6
6
|
/**
|
|
@@ -30,8 +30,8 @@ export declare function deleteRegToken(env: PushNotificationEnv): Promise<boolea
|
|
|
30
30
|
* @returns a function that can be used by the controller
|
|
31
31
|
*/
|
|
32
32
|
export declare function createSubscribeToPushNotifications(props: {
|
|
33
|
-
onReceivedHandler: (
|
|
34
|
-
onClickHandler: (e: NotificationEvent,
|
|
33
|
+
onReceivedHandler: (notification: Types.INotification) => void | Promise<void>;
|
|
34
|
+
onClickHandler: (e: NotificationEvent, notification: Types.INotification) => void;
|
|
35
35
|
messenger: NotificationServicesPushControllerMessenger;
|
|
36
36
|
}): (env: PushNotificationEnv) => Promise<() => void>;
|
|
37
37
|
//# sourceMappingURL=push-utils.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push-utils.d.cts","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/web/push-utils.ts"],"names":[],"mappings":";AAcA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"push-utils.d.cts","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/web/push-utils.ts"],"names":[],"mappings":";AAcA,OAAO,KAAK,EAAE,KAAK,EAAE,uDAA6C;AAMlE,OAAO,KAAK,EAAE,2CAA2C,EAAE,kDAA8C;AACzG,OAAO,KAAK,EAAE,mBAAmB,EAAE,8BAA0B;AAM7D,eAAO,IAAI,cAAc,EAAE,OAAO,GAAG,IAAW,CAAC;AAyCjD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,mBAAmB,GACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAexB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,mBAAmB,GACvB,OAAO,CAAC,OAAO,CAAC,CAYlB;AA+ED;;;;;;;;;;;GAWG;AACH,wBAAgB,kCAAkC,CAAC,KAAK,EAAE;IACxD,iBAAiB,EAAE,CACjB,YAAY,EAAE,KAAK,CAAC,aAAa,KAC9B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,cAAc,EAAE,CACd,CAAC,EAAE,iBAAiB,EACpB,YAAY,EAAE,KAAK,CAAC,aAAa,KAC9B,IAAI,CAAC;IACV,SAAS,EAAE,2CAA2C,CAAC;CACxD,GAAG,CAAC,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,MAAM,IAAI,CAAC,CA6BpD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference lib="webworker" />
|
|
2
|
+
import type { Types } from "../../NotificationServicesController/index.mjs";
|
|
2
3
|
import type { NotificationServicesPushControllerMessenger } from "../NotificationServicesPushController.mjs";
|
|
3
|
-
import type { PushAnalyticsPayload } from "../types/index.mjs";
|
|
4
4
|
import type { PushNotificationEnv } from "../types/firebase.mjs";
|
|
5
5
|
export declare let supportedCache: boolean | null;
|
|
6
6
|
/**
|
|
@@ -30,8 +30,8 @@ export declare function deleteRegToken(env: PushNotificationEnv): Promise<boolea
|
|
|
30
30
|
* @returns a function that can be used by the controller
|
|
31
31
|
*/
|
|
32
32
|
export declare function createSubscribeToPushNotifications(props: {
|
|
33
|
-
onReceivedHandler: (
|
|
34
|
-
onClickHandler: (e: NotificationEvent,
|
|
33
|
+
onReceivedHandler: (notification: Types.INotification) => void | Promise<void>;
|
|
34
|
+
onClickHandler: (e: NotificationEvent, notification: Types.INotification) => void;
|
|
35
35
|
messenger: NotificationServicesPushControllerMessenger;
|
|
36
36
|
}): (env: PushNotificationEnv) => Promise<() => void>;
|
|
37
37
|
//# sourceMappingURL=push-utils.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push-utils.d.mts","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/web/push-utils.ts"],"names":[],"mappings":";AAcA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"push-utils.d.mts","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/web/push-utils.ts"],"names":[],"mappings":";AAcA,OAAO,KAAK,EAAE,KAAK,EAAE,uDAA6C;AAMlE,OAAO,KAAK,EAAE,2CAA2C,EAAE,kDAA8C;AACzG,OAAO,KAAK,EAAE,mBAAmB,EAAE,8BAA0B;AAM7D,eAAO,IAAI,cAAc,EAAE,OAAO,GAAG,IAAW,CAAC;AAyCjD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,mBAAmB,GACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAexB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,mBAAmB,GACvB,OAAO,CAAC,OAAO,CAAC,CAYlB;AA+ED;;;;;;;;;;;GAWG;AACH,wBAAgB,kCAAkC,CAAC,KAAK,EAAE;IACxD,iBAAiB,EAAE,CACjB,YAAY,EAAE,KAAK,CAAC,aAAa,KAC9B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,cAAc,EAAE,CACd,CAAC,EAAE,iBAAiB,EACpB,YAAY,EAAE,KAAK,CAAC,aAAa,KAC9B,IAAI,CAAC;IACV,SAAS,EAAE,2CAA2C,CAAC;CACxD,GAAG,CAAC,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,MAAM,IAAI,CAAC,CA6BpD"}
|
|
@@ -9,7 +9,8 @@ import { getToken, deleteToken } from "firebase/messaging";
|
|
|
9
9
|
import { getMessaging, onBackgroundMessage, isSupported } from "firebase/messaging/sw";
|
|
10
10
|
import $log from "loglevel";
|
|
11
11
|
const log = $importDefault($log);
|
|
12
|
-
import {
|
|
12
|
+
import { isOnChainRawNotification, safeProcessNotification } from "../../NotificationServicesController/index.mjs";
|
|
13
|
+
import { toRawAPINotification } from "../../shared/to-raw-notification.mjs";
|
|
13
14
|
// Exported to help testing
|
|
14
15
|
// eslint-disable-next-line import-x/no-mutable-exports
|
|
15
16
|
export let supportedCache = null;
|
|
@@ -102,16 +103,27 @@ async function listenToPushNotificationsReceived(env, handler) {
|
|
|
102
103
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
103
104
|
async (payload) => {
|
|
104
105
|
try {
|
|
105
|
-
|
|
106
|
-
|
|
106
|
+
// MessagePayload shapes are not known
|
|
107
|
+
// TODO - provide open-api unfied backend/frontend types
|
|
108
|
+
// TODO - we will replace the underlying Data payload with the same Notification payload used by mobile
|
|
109
|
+
const data = JSON.parse(payload?.data?.data ?? 'null');
|
|
110
|
+
if (!data) {
|
|
107
111
|
return;
|
|
108
112
|
}
|
|
109
|
-
|
|
113
|
+
if (!isOnChainRawNotification(data)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const notificationData = toRawAPINotification(data);
|
|
117
|
+
const notification = safeProcessNotification(notificationData);
|
|
118
|
+
if (!notification) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
await handler?.(notification);
|
|
110
122
|
}
|
|
111
123
|
catch (error) {
|
|
112
|
-
// Do Nothing, cannot
|
|
113
|
-
log.error('Unable to
|
|
114
|
-
notification: payload?.data,
|
|
124
|
+
// Do Nothing, cannot parse a bad notification
|
|
125
|
+
log.error('Unable to send push notification:', {
|
|
126
|
+
notification: payload?.data?.data,
|
|
115
127
|
error,
|
|
116
128
|
});
|
|
117
129
|
}
|
|
@@ -149,13 +161,13 @@ function listenToPushNotificationsClicked(handler) {
|
|
|
149
161
|
*/
|
|
150
162
|
export function createSubscribeToPushNotifications(props) {
|
|
151
163
|
return async function (env) {
|
|
152
|
-
const onBackgroundMessageSub = await listenToPushNotificationsReceived(env, async (
|
|
153
|
-
props.messenger.publish('NotificationServicesPushController:onNewNotifications',
|
|
154
|
-
await props.onReceivedHandler(
|
|
164
|
+
const onBackgroundMessageSub = await listenToPushNotificationsReceived(env, async (notification) => {
|
|
165
|
+
props.messenger.publish('NotificationServicesPushController:onNewNotifications', notification);
|
|
166
|
+
await props.onReceivedHandler(notification);
|
|
155
167
|
});
|
|
156
|
-
const onClickSub = listenToPushNotificationsClicked((event,
|
|
157
|
-
props.messenger.publish('NotificationServicesPushController:pushNotificationClicked',
|
|
158
|
-
props.onClickHandler(event,
|
|
168
|
+
const onClickSub = listenToPushNotificationsClicked((event, notification) => {
|
|
169
|
+
props.messenger.publish('NotificationServicesPushController:pushNotificationClicked', notification);
|
|
170
|
+
props.onClickHandler(event, notification);
|
|
159
171
|
});
|
|
160
172
|
const unsubscribe = () => {
|
|
161
173
|
onBackgroundMessageSub?.();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push-utils.mjs","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/web/push-utils.ts"],"names":[],"mappings":"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","sourcesContent":["// We are defining that this file uses a webworker global scope.\n// eslint-disable-next-line spaced-comment\n/// <reference lib=\"webworker\" />\nimport type { FirebaseApp } from 'firebase/app';\nimport { getApp, initializeApp } from 'firebase/app';\nimport { getToken, deleteToken } from 'firebase/messaging';\nimport {\n getMessaging,\n onBackgroundMessage,\n isSupported,\n} from 'firebase/messaging/sw';\nimport type { Messaging, MessagePayload } from 'firebase/messaging/sw';\nimport log from 'loglevel';\n\nimport type { NotificationServicesPushControllerMessenger } from '../NotificationServicesPushController';\nimport type { PushAnalyticsPayload } from '../types';\nimport type { PushNotificationEnv } from '../types/firebase';\nimport { toPushAnalyticsPayload } from '../utils/to-push-analytics-payload';\n\ndeclare const self: ServiceWorkerGlobalScope;\n\n// Exported to help testing\n// eslint-disable-next-line import-x/no-mutable-exports\nexport let supportedCache: boolean | null = null;\n\nconst getPushAvailability = async (): Promise<boolean> => {\n // Race condition is acceptable here - worst case is isSupported() is called\n // multiple times during initialization, which is harmless for caching a boolean\n // eslint-disable-next-line require-atomic-updates\n supportedCache ??= await isSupported();\n return supportedCache;\n};\n\nconst createFirebaseApp = async (\n env: PushNotificationEnv,\n): Promise<FirebaseApp> => {\n try {\n return getApp();\n } catch {\n const firebaseConfig = {\n apiKey: env.apiKey,\n authDomain: env.authDomain,\n storageBucket: env.storageBucket,\n projectId: env.projectId,\n messagingSenderId: env.messagingSenderId,\n appId: env.appId,\n measurementId: env.measurementId,\n };\n return initializeApp(firebaseConfig);\n }\n};\n\nconst getFirebaseMessaging = async (\n env: PushNotificationEnv,\n): Promise<Messaging | null> => {\n const supported = await getPushAvailability();\n if (!supported) {\n return null;\n }\n\n const app = await createFirebaseApp(env);\n return getMessaging(app);\n};\n\n/**\n * Creates a registration token for Firebase Cloud Messaging.\n *\n * @param env - env to configure push notifications\n * @returns A promise that resolves with the registration token or null if an error occurs.\n */\nexport async function createRegToken(\n env: PushNotificationEnv,\n): Promise<string | null> {\n try {\n const messaging = await getFirebaseMessaging(env);\n if (!messaging) {\n return null;\n }\n\n const token = await getToken(messaging, {\n serviceWorkerRegistration: self.registration,\n vapidKey: env.vapidKey,\n });\n return token;\n } catch {\n return null;\n }\n}\n\n/**\n * Deletes the Firebase Cloud Messaging registration token.\n *\n * @param env - env to configure push notifications\n * @returns A promise that resolves with true if the token was successfully deleted, false otherwise.\n */\nexport async function deleteRegToken(\n env: PushNotificationEnv,\n): Promise<boolean> {\n try {\n const messaging = await getFirebaseMessaging(env);\n if (!messaging) {\n return true;\n }\n\n await deleteToken(messaging);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Service Worker Listener for when push notifications are received.\n *\n * @param env - push notification environment\n * @param handler - handler to actually showing notification, MUST BE PROVIDED\n * @returns unsubscribe handler\n */\nasync function listenToPushNotificationsReceived(\n env: PushNotificationEnv,\n handler?: (payload: PushAnalyticsPayload) => void | Promise<void>,\n): Promise<(() => void) | null> {\n const messaging = await getFirebaseMessaging(env);\n if (!messaging) {\n return null;\n }\n\n const unsubscribePushNotifications = onBackgroundMessage(\n messaging,\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async (payload: MessagePayload): Promise<void> => {\n try {\n const analyticsPayload = toPushAnalyticsPayload(payload?.data);\n\n if (!analyticsPayload) {\n return;\n }\n\n await handler?.(analyticsPayload);\n } catch (error) {\n // Do Nothing, cannot handle a bad notification\n log.error('Unable to handle push notification:', {\n notification: payload?.data,\n error,\n });\n }\n },\n );\n\n const unsubscribe = (): void => unsubscribePushNotifications();\n return unsubscribe;\n}\n\n/**\n * Service Worker Listener for when a notification is clicked\n *\n * @param handler - listen to NotificationEvent from the service worker\n * @returns unsubscribe handler\n */\nfunction listenToPushNotificationsClicked(\n handler: (e: NotificationEvent, payload: PushAnalyticsPayload) => void,\n): () => void {\n const clickHandler = (event: NotificationEvent): void => {\n // Get Data\n const data: PushAnalyticsPayload = event?.notification?.data;\n handler(event, data);\n };\n\n self.addEventListener('notificationclick', clickHandler);\n const unsubscribe = (): void =>\n self.removeEventListener('notificationclick', clickHandler);\n return unsubscribe;\n}\n\n/**\n * A creator function that assists creating web-specific push notification subscription:\n * 1. Creates subscriptions for receiving and clicking notifications\n * 2. Creates click events when a notification is clicked\n * 3. Publishes controller messenger events\n *\n * @param props - props for this creator function.\n * @param props.onReceivedHandler - allows the developer to handle showing a notification\n * @param props.onClickHandler - allows the developer to handle clicking the notification\n * @param props.messenger - the controller messenger to publish the `onNewNotifications` and `pushNotificationsClicked` events\n * @returns a function that can be used by the controller\n */\nexport function createSubscribeToPushNotifications(props: {\n onReceivedHandler: (payload: PushAnalyticsPayload) => void | Promise<void>;\n onClickHandler: (e: NotificationEvent, payload: PushAnalyticsPayload) => void;\n messenger: NotificationServicesPushControllerMessenger;\n}): (env: PushNotificationEnv) => Promise<() => void> {\n return async function (env: PushNotificationEnv): Promise<() => void> {\n const onBackgroundMessageSub = await listenToPushNotificationsReceived(\n env,\n async (analyticsPayload): Promise<void> => {\n props.messenger.publish(\n 'NotificationServicesPushController:onNewNotifications',\n analyticsPayload,\n );\n await props.onReceivedHandler(analyticsPayload);\n },\n );\n const onClickSub = listenToPushNotificationsClicked(\n (event, analyticsPayload): void => {\n props.messenger.publish(\n 'NotificationServicesPushController:pushNotificationClicked',\n analyticsPayload,\n );\n props.onClickHandler(event, analyticsPayload);\n },\n );\n\n const unsubscribe = (): void => {\n onBackgroundMessageSub?.();\n onClickSub();\n };\n\n return unsubscribe;\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"push-utils.mjs","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/web/push-utils.ts"],"names":[],"mappings":"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","sourcesContent":["// We are defining that this file uses a webworker global scope.\n// eslint-disable-next-line spaced-comment\n/// <reference lib=\"webworker\" />\nimport type { FirebaseApp } from 'firebase/app';\nimport { getApp, initializeApp } from 'firebase/app';\nimport { getToken, deleteToken } from 'firebase/messaging';\nimport {\n getMessaging,\n onBackgroundMessage,\n isSupported,\n} from 'firebase/messaging/sw';\nimport type { Messaging, MessagePayload } from 'firebase/messaging/sw';\nimport log from 'loglevel';\n\nimport type { Types } from '../../NotificationServicesController';\nimport {\n isOnChainRawNotification,\n safeProcessNotification,\n} from '../../NotificationServicesController';\nimport { toRawAPINotification } from '../../shared/to-raw-notification';\nimport type { NotificationServicesPushControllerMessenger } from '../NotificationServicesPushController';\nimport type { PushNotificationEnv } from '../types/firebase';\n\ndeclare const self: ServiceWorkerGlobalScope;\n\n// Exported to help testing\n// eslint-disable-next-line import-x/no-mutable-exports\nexport let supportedCache: boolean | null = null;\n\nconst getPushAvailability = async (): Promise<boolean> => {\n // Race condition is acceptable here - worst case is isSupported() is called\n // multiple times during initialization, which is harmless for caching a boolean\n // eslint-disable-next-line require-atomic-updates\n supportedCache ??= await isSupported();\n return supportedCache;\n};\n\nconst createFirebaseApp = async (\n env: PushNotificationEnv,\n): Promise<FirebaseApp> => {\n try {\n return getApp();\n } catch {\n const firebaseConfig = {\n apiKey: env.apiKey,\n authDomain: env.authDomain,\n storageBucket: env.storageBucket,\n projectId: env.projectId,\n messagingSenderId: env.messagingSenderId,\n appId: env.appId,\n measurementId: env.measurementId,\n };\n return initializeApp(firebaseConfig);\n }\n};\n\nconst getFirebaseMessaging = async (\n env: PushNotificationEnv,\n): Promise<Messaging | null> => {\n const supported = await getPushAvailability();\n if (!supported) {\n return null;\n }\n\n const app = await createFirebaseApp(env);\n return getMessaging(app);\n};\n\n/**\n * Creates a registration token for Firebase Cloud Messaging.\n *\n * @param env - env to configure push notifications\n * @returns A promise that resolves with the registration token or null if an error occurs.\n */\nexport async function createRegToken(\n env: PushNotificationEnv,\n): Promise<string | null> {\n try {\n const messaging = await getFirebaseMessaging(env);\n if (!messaging) {\n return null;\n }\n\n const token = await getToken(messaging, {\n serviceWorkerRegistration: self.registration,\n vapidKey: env.vapidKey,\n });\n return token;\n } catch {\n return null;\n }\n}\n\n/**\n * Deletes the Firebase Cloud Messaging registration token.\n *\n * @param env - env to configure push notifications\n * @returns A promise that resolves with true if the token was successfully deleted, false otherwise.\n */\nexport async function deleteRegToken(\n env: PushNotificationEnv,\n): Promise<boolean> {\n try {\n const messaging = await getFirebaseMessaging(env);\n if (!messaging) {\n return true;\n }\n\n await deleteToken(messaging);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Service Worker Listener for when push notifications are received.\n *\n * @param env - push notification environment\n * @param handler - handler to actually showing notification, MUST BE PROVIDED\n * @returns unsubscribe handler\n */\nasync function listenToPushNotificationsReceived(\n env: PushNotificationEnv,\n handler?: (notification: Types.INotification) => void | Promise<void>,\n): Promise<(() => void) | null> {\n const messaging = await getFirebaseMessaging(env);\n if (!messaging) {\n return null;\n }\n\n const unsubscribePushNotifications = onBackgroundMessage(\n messaging,\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async (payload: MessagePayload): Promise<void> => {\n try {\n // MessagePayload shapes are not known\n // TODO - provide open-api unfied backend/frontend types\n // TODO - we will replace the underlying Data payload with the same Notification payload used by mobile\n const data: unknown | null = JSON.parse(payload?.data?.data ?? 'null');\n\n if (!data) {\n return;\n }\n\n if (!isOnChainRawNotification(data)) {\n return;\n }\n\n const notificationData = toRawAPINotification(data);\n const notification = safeProcessNotification(notificationData);\n\n if (!notification) {\n return;\n }\n\n await handler?.(notification);\n } catch (error) {\n // Do Nothing, cannot parse a bad notification\n log.error('Unable to send push notification:', {\n notification: payload?.data?.data,\n error,\n });\n }\n },\n );\n\n const unsubscribe = (): void => unsubscribePushNotifications();\n return unsubscribe;\n}\n\n/**\n * Service Worker Listener for when a notification is clicked\n *\n * @param handler - listen to NotificationEvent from the service worker\n * @returns unsubscribe handler\n */\nfunction listenToPushNotificationsClicked(\n handler: (e: NotificationEvent, notification: Types.INotification) => void,\n): () => void {\n const clickHandler = (event: NotificationEvent): void => {\n // Get Data\n const data: Types.INotification = event?.notification?.data;\n handler(event, data);\n };\n\n self.addEventListener('notificationclick', clickHandler);\n const unsubscribe = (): void =>\n self.removeEventListener('notificationclick', clickHandler);\n return unsubscribe;\n}\n\n/**\n * A creator function that assists creating web-specific push notification subscription:\n * 1. Creates subscriptions for receiving and clicking notifications\n * 2. Creates click events when a notification is clicked\n * 3. Publishes controller messenger events\n *\n * @param props - props for this creator function.\n * @param props.onReceivedHandler - allows the developer to handle showing a notification\n * @param props.onClickHandler - allows the developer to handle clicking the notification\n * @param props.messenger - the controller messenger to publish the `onNewNotifications` and `pushNotificationsClicked` events\n * @returns a function that can be used by the controller\n */\nexport function createSubscribeToPushNotifications(props: {\n onReceivedHandler: (\n notification: Types.INotification,\n ) => void | Promise<void>;\n onClickHandler: (\n e: NotificationEvent,\n notification: Types.INotification,\n ) => void;\n messenger: NotificationServicesPushControllerMessenger;\n}): (env: PushNotificationEnv) => Promise<() => void> {\n return async function (env: PushNotificationEnv): Promise<() => void> {\n const onBackgroundMessageSub = await listenToPushNotificationsReceived(\n env,\n async (notification): Promise<void> => {\n props.messenger.publish(\n 'NotificationServicesPushController:onNewNotifications',\n notification,\n );\n await props.onReceivedHandler(notification);\n },\n );\n const onClickSub = listenToPushNotificationsClicked(\n (event, notification): void => {\n props.messenger.publish(\n 'NotificationServicesPushController:pushNotificationClicked',\n notification,\n );\n props.onClickHandler(event, notification);\n },\n );\n\n const unsubscribe = (): void => {\n onBackgroundMessageSub?.();\n onClickSub();\n };\n\n return unsubscribe;\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getNotificationSubtype = void 0;
|
|
4
|
-
const notification_schema_1 = require("../constants/notification-schema.cjs");
|
|
5
|
-
/**
|
|
6
|
-
* Derives the normalised `notification_subtype` for a processed in-app
|
|
7
|
-
* notification. This is the team-owned axis (e.g. `eth_received`) and is
|
|
8
|
-
* always derivable from an `INotification`, so every consumer (both clients)
|
|
9
|
-
* pulls it from one place rather than recomputing a fallback chain.
|
|
10
|
-
*
|
|
11
|
-
* - on-chain: the trigger kind (`payload.data.kind`, e.g. `eth_received`).
|
|
12
|
-
* - snap: the snap notification type (`snap`, already snake_case).
|
|
13
|
-
* - feature-announcement: §5.3 calls for a stable per-campaign id, pending
|
|
14
|
-
* confirmation from the announcements team that one exists. Until confirmed,
|
|
15
|
-
* we use the `features_announcement` label as the single value.
|
|
16
|
-
* - platform: the server-set `notification_subtype`. The backend stores it
|
|
17
|
-
* (notify-notification-services §4.3), but the `/api/v3/notifications` inbox
|
|
18
|
-
* response does not expose it yet, so it is absent from the generated
|
|
19
|
-
* `schema.ts` and we fall back to `type` (`platform`).
|
|
20
|
-
*
|
|
21
|
-
* @param notification - a raw or processed notification.
|
|
22
|
-
* @returns the normalised subtype string.
|
|
23
|
-
*/
|
|
24
|
-
function getNotificationSubtype(notification) {
|
|
25
|
-
switch (notification.type) {
|
|
26
|
-
case notification_schema_1.TRIGGER_TYPES.FEATURES_ANNOUNCEMENT:
|
|
27
|
-
// §5.3 calls for a stable per-campaign id here, pending confirmation from
|
|
28
|
-
// the announcements team that one exists. Until confirmed, use the
|
|
29
|
-
// `features_announcement` label as the single value.
|
|
30
|
-
return notification_schema_1.TRIGGER_TYPES.FEATURES_ANNOUNCEMENT;
|
|
31
|
-
case notification_schema_1.TRIGGER_TYPES.SNAP:
|
|
32
|
-
// Snap notification type, already snake_case in the existing shape.
|
|
33
|
-
return notification_schema_1.TRIGGER_TYPES.SNAP;
|
|
34
|
-
default:
|
|
35
|
-
// On-chain: the trigger kind (e.g. `eth_received`).
|
|
36
|
-
if (notification.notification_type === 'on-chain') {
|
|
37
|
-
return notification.payload.data.kind;
|
|
38
|
-
}
|
|
39
|
-
// Platform: §5.3 wants the server-set `notification_subtype`. It is
|
|
40
|
-
// stored backend-side (§4.3) but not returned on the `/api/v3/notifications`
|
|
41
|
-
// inbox response, so it is absent from `schema.ts`. Fall back to `type`
|
|
42
|
-
// (`platform`) until the inbox API exposes it.
|
|
43
|
-
// TODO: return notification.notification_subtype once the inbox API
|
|
44
|
-
// response includes it (needs a notify-notification-services change).
|
|
45
|
-
return notification.type;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
exports.getNotificationSubtype = getNotificationSubtype;
|
|
49
|
-
//# sourceMappingURL=get-notification-subtype.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"get-notification-subtype.cjs","sourceRoot":"","sources":["../../../src/NotificationServicesController/utils/get-notification-subtype.ts"],"names":[],"mappings":";;;AAAA,8EAAiE;AAGjE;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,sBAAsB,CACpC,YAAkC;IAElC,QAAQ,YAAY,CAAC,IAAI,EAAE,CAAC;QAC1B,KAAK,mCAAa,CAAC,qBAAqB;YACtC,0EAA0E;YAC1E,mEAAmE;YACnE,qDAAqD;YACrD,OAAO,mCAAa,CAAC,qBAAqB,CAAC;QAC7C,KAAK,mCAAa,CAAC,IAAI;YACrB,oEAAoE;YACpE,OAAO,mCAAa,CAAC,IAAI,CAAC;QAC5B;YACE,oDAAoD;YACpD,IAAI,YAAY,CAAC,iBAAiB,KAAK,UAAU,EAAE,CAAC;gBAClD,OAAO,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YACxC,CAAC;YACD,oEAAoE;YACpE,6EAA6E;YAC7E,wEAAwE;YACxE,+CAA+C;YAC/C,oEAAoE;YACpE,sEAAsE;YACtE,OAAO,YAAY,CAAC,IAAI,CAAC;IAC7B,CAAC;AACH,CAAC;AAzBD,wDAyBC","sourcesContent":["import { TRIGGER_TYPES } from '../constants/notification-schema';\nimport type { RawNotificationUnion } from '../types/notification/notification';\n\n/**\n * Derives the normalised `notification_subtype` for a processed in-app\n * notification. This is the team-owned axis (e.g. `eth_received`) and is\n * always derivable from an `INotification`, so every consumer (both clients)\n * pulls it from one place rather than recomputing a fallback chain.\n *\n * - on-chain: the trigger kind (`payload.data.kind`, e.g. `eth_received`).\n * - snap: the snap notification type (`snap`, already snake_case).\n * - feature-announcement: §5.3 calls for a stable per-campaign id, pending\n * confirmation from the announcements team that one exists. Until confirmed,\n * we use the `features_announcement` label as the single value.\n * - platform: the server-set `notification_subtype`. The backend stores it\n * (notify-notification-services §4.3), but the `/api/v3/notifications` inbox\n * response does not expose it yet, so it is absent from the generated\n * `schema.ts` and we fall back to `type` (`platform`).\n *\n * @param notification - a raw or processed notification.\n * @returns the normalised subtype string.\n */\nexport function getNotificationSubtype(\n notification: RawNotificationUnion,\n): string {\n switch (notification.type) {\n case TRIGGER_TYPES.FEATURES_ANNOUNCEMENT:\n // §5.3 calls for a stable per-campaign id here, pending confirmation from\n // the announcements team that one exists. Until confirmed, use the\n // `features_announcement` label as the single value.\n return TRIGGER_TYPES.FEATURES_ANNOUNCEMENT;\n case TRIGGER_TYPES.SNAP:\n // Snap notification type, already snake_case in the existing shape.\n return TRIGGER_TYPES.SNAP;\n default:\n // On-chain: the trigger kind (e.g. `eth_received`).\n if (notification.notification_type === 'on-chain') {\n return notification.payload.data.kind;\n }\n // Platform: §5.3 wants the server-set `notification_subtype`. It is\n // stored backend-side (§4.3) but not returned on the `/api/v3/notifications`\n // inbox response, so it is absent from `schema.ts`. Fall back to `type`\n // (`platform`) until the inbox API exposes it.\n // TODO: return notification.notification_subtype once the inbox API\n // response includes it (needs a notify-notification-services change).\n return notification.type;\n }\n}\n"]}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { RawNotificationUnion } from "../types/notification/notification.cjs";
|
|
2
|
-
/**
|
|
3
|
-
* Derives the normalised `notification_subtype` for a processed in-app
|
|
4
|
-
* notification. This is the team-owned axis (e.g. `eth_received`) and is
|
|
5
|
-
* always derivable from an `INotification`, so every consumer (both clients)
|
|
6
|
-
* pulls it from one place rather than recomputing a fallback chain.
|
|
7
|
-
*
|
|
8
|
-
* - on-chain: the trigger kind (`payload.data.kind`, e.g. `eth_received`).
|
|
9
|
-
* - snap: the snap notification type (`snap`, already snake_case).
|
|
10
|
-
* - feature-announcement: §5.3 calls for a stable per-campaign id, pending
|
|
11
|
-
* confirmation from the announcements team that one exists. Until confirmed,
|
|
12
|
-
* we use the `features_announcement` label as the single value.
|
|
13
|
-
* - platform: the server-set `notification_subtype`. The backend stores it
|
|
14
|
-
* (notify-notification-services §4.3), but the `/api/v3/notifications` inbox
|
|
15
|
-
* response does not expose it yet, so it is absent from the generated
|
|
16
|
-
* `schema.ts` and we fall back to `type` (`platform`).
|
|
17
|
-
*
|
|
18
|
-
* @param notification - a raw or processed notification.
|
|
19
|
-
* @returns the normalised subtype string.
|
|
20
|
-
*/
|
|
21
|
-
export declare function getNotificationSubtype(notification: RawNotificationUnion): string;
|
|
22
|
-
//# sourceMappingURL=get-notification-subtype.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"get-notification-subtype.d.cts","sourceRoot":"","sources":["../../../src/NotificationServicesController/utils/get-notification-subtype.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,+CAA2C;AAE/E;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,oBAAoB,GACjC,MAAM,CAuBR"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { RawNotificationUnion } from "../types/notification/notification.mjs";
|
|
2
|
-
/**
|
|
3
|
-
* Derives the normalised `notification_subtype` for a processed in-app
|
|
4
|
-
* notification. This is the team-owned axis (e.g. `eth_received`) and is
|
|
5
|
-
* always derivable from an `INotification`, so every consumer (both clients)
|
|
6
|
-
* pulls it from one place rather than recomputing a fallback chain.
|
|
7
|
-
*
|
|
8
|
-
* - on-chain: the trigger kind (`payload.data.kind`, e.g. `eth_received`).
|
|
9
|
-
* - snap: the snap notification type (`snap`, already snake_case).
|
|
10
|
-
* - feature-announcement: §5.3 calls for a stable per-campaign id, pending
|
|
11
|
-
* confirmation from the announcements team that one exists. Until confirmed,
|
|
12
|
-
* we use the `features_announcement` label as the single value.
|
|
13
|
-
* - platform: the server-set `notification_subtype`. The backend stores it
|
|
14
|
-
* (notify-notification-services §4.3), but the `/api/v3/notifications` inbox
|
|
15
|
-
* response does not expose it yet, so it is absent from the generated
|
|
16
|
-
* `schema.ts` and we fall back to `type` (`platform`).
|
|
17
|
-
*
|
|
18
|
-
* @param notification - a raw or processed notification.
|
|
19
|
-
* @returns the normalised subtype string.
|
|
20
|
-
*/
|
|
21
|
-
export declare function getNotificationSubtype(notification: RawNotificationUnion): string;
|
|
22
|
-
//# sourceMappingURL=get-notification-subtype.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"get-notification-subtype.d.mts","sourceRoot":"","sources":["../../../src/NotificationServicesController/utils/get-notification-subtype.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,+CAA2C;AAE/E;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,oBAAoB,GACjC,MAAM,CAuBR"}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { TRIGGER_TYPES } from "../constants/notification-schema.mjs";
|
|
2
|
-
/**
|
|
3
|
-
* Derives the normalised `notification_subtype` for a processed in-app
|
|
4
|
-
* notification. This is the team-owned axis (e.g. `eth_received`) and is
|
|
5
|
-
* always derivable from an `INotification`, so every consumer (both clients)
|
|
6
|
-
* pulls it from one place rather than recomputing a fallback chain.
|
|
7
|
-
*
|
|
8
|
-
* - on-chain: the trigger kind (`payload.data.kind`, e.g. `eth_received`).
|
|
9
|
-
* - snap: the snap notification type (`snap`, already snake_case).
|
|
10
|
-
* - feature-announcement: §5.3 calls for a stable per-campaign id, pending
|
|
11
|
-
* confirmation from the announcements team that one exists. Until confirmed,
|
|
12
|
-
* we use the `features_announcement` label as the single value.
|
|
13
|
-
* - platform: the server-set `notification_subtype`. The backend stores it
|
|
14
|
-
* (notify-notification-services §4.3), but the `/api/v3/notifications` inbox
|
|
15
|
-
* response does not expose it yet, so it is absent from the generated
|
|
16
|
-
* `schema.ts` and we fall back to `type` (`platform`).
|
|
17
|
-
*
|
|
18
|
-
* @param notification - a raw or processed notification.
|
|
19
|
-
* @returns the normalised subtype string.
|
|
20
|
-
*/
|
|
21
|
-
export function getNotificationSubtype(notification) {
|
|
22
|
-
switch (notification.type) {
|
|
23
|
-
case TRIGGER_TYPES.FEATURES_ANNOUNCEMENT:
|
|
24
|
-
// §5.3 calls for a stable per-campaign id here, pending confirmation from
|
|
25
|
-
// the announcements team that one exists. Until confirmed, use the
|
|
26
|
-
// `features_announcement` label as the single value.
|
|
27
|
-
return TRIGGER_TYPES.FEATURES_ANNOUNCEMENT;
|
|
28
|
-
case TRIGGER_TYPES.SNAP:
|
|
29
|
-
// Snap notification type, already snake_case in the existing shape.
|
|
30
|
-
return TRIGGER_TYPES.SNAP;
|
|
31
|
-
default:
|
|
32
|
-
// On-chain: the trigger kind (e.g. `eth_received`).
|
|
33
|
-
if (notification.notification_type === 'on-chain') {
|
|
34
|
-
return notification.payload.data.kind;
|
|
35
|
-
}
|
|
36
|
-
// Platform: §5.3 wants the server-set `notification_subtype`. It is
|
|
37
|
-
// stored backend-side (§4.3) but not returned on the `/api/v3/notifications`
|
|
38
|
-
// inbox response, so it is absent from `schema.ts`. Fall back to `type`
|
|
39
|
-
// (`platform`) until the inbox API exposes it.
|
|
40
|
-
// TODO: return notification.notification_subtype once the inbox API
|
|
41
|
-
// response includes it (needs a notify-notification-services change).
|
|
42
|
-
return notification.type;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
//# sourceMappingURL=get-notification-subtype.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"get-notification-subtype.mjs","sourceRoot":"","sources":["../../../src/NotificationServicesController/utils/get-notification-subtype.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,6CAAyC;AAGjE;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,sBAAsB,CACpC,YAAkC;IAElC,QAAQ,YAAY,CAAC,IAAI,EAAE,CAAC;QAC1B,KAAK,aAAa,CAAC,qBAAqB;YACtC,0EAA0E;YAC1E,mEAAmE;YACnE,qDAAqD;YACrD,OAAO,aAAa,CAAC,qBAAqB,CAAC;QAC7C,KAAK,aAAa,CAAC,IAAI;YACrB,oEAAoE;YACpE,OAAO,aAAa,CAAC,IAAI,CAAC;QAC5B;YACE,oDAAoD;YACpD,IAAI,YAAY,CAAC,iBAAiB,KAAK,UAAU,EAAE,CAAC;gBAClD,OAAO,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YACxC,CAAC;YACD,oEAAoE;YACpE,6EAA6E;YAC7E,wEAAwE;YACxE,+CAA+C;YAC/C,oEAAoE;YACpE,sEAAsE;YACtE,OAAO,YAAY,CAAC,IAAI,CAAC;IAC7B,CAAC;AACH,CAAC","sourcesContent":["import { TRIGGER_TYPES } from '../constants/notification-schema';\nimport type { RawNotificationUnion } from '../types/notification/notification';\n\n/**\n * Derives the normalised `notification_subtype` for a processed in-app\n * notification. This is the team-owned axis (e.g. `eth_received`) and is\n * always derivable from an `INotification`, so every consumer (both clients)\n * pulls it from one place rather than recomputing a fallback chain.\n *\n * - on-chain: the trigger kind (`payload.data.kind`, e.g. `eth_received`).\n * - snap: the snap notification type (`snap`, already snake_case).\n * - feature-announcement: §5.3 calls for a stable per-campaign id, pending\n * confirmation from the announcements team that one exists. Until confirmed,\n * we use the `features_announcement` label as the single value.\n * - platform: the server-set `notification_subtype`. The backend stores it\n * (notify-notification-services §4.3), but the `/api/v3/notifications` inbox\n * response does not expose it yet, so it is absent from the generated\n * `schema.ts` and we fall back to `type` (`platform`).\n *\n * @param notification - a raw or processed notification.\n * @returns the normalised subtype string.\n */\nexport function getNotificationSubtype(\n notification: RawNotificationUnion,\n): string {\n switch (notification.type) {\n case TRIGGER_TYPES.FEATURES_ANNOUNCEMENT:\n // §5.3 calls for a stable per-campaign id here, pending confirmation from\n // the announcements team that one exists. Until confirmed, use the\n // `features_announcement` label as the single value.\n return TRIGGER_TYPES.FEATURES_ANNOUNCEMENT;\n case TRIGGER_TYPES.SNAP:\n // Snap notification type, already snake_case in the existing shape.\n return TRIGGER_TYPES.SNAP;\n default:\n // On-chain: the trigger kind (e.g. `eth_received`).\n if (notification.notification_type === 'on-chain') {\n return notification.payload.data.kind;\n }\n // Platform: §5.3 wants the server-set `notification_subtype`. It is\n // stored backend-side (§4.3) but not returned on the `/api/v3/notifications`\n // inbox response, so it is absent from `schema.ts`. Fall back to `type`\n // (`platform`) until the inbox API exposes it.\n // TODO: return notification.notification_subtype once the inbox API\n // response includes it (needs a notify-notification-services change).\n return notification.type;\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"push-analytics.cjs","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/types/push-analytics.ts"],"names":[],"mappings":";AAAA,6DAA6D;AAC7D,yDAAyD","sourcesContent":["// snake_case mirrors the FCM payload and Segment schema keys\n/* eslint-disable @typescript-eslint/naming-convention */\n\n/**\n * Analytics fields carried by the `NotificationServicesPushController` messenger\n * events (`onNewNotifications`, `pushNotificationClicked`). Read directly from\n * top-level FCM payload keys, so clients build Segment events without fallback\n * chains or parsing a `metadata` blob.\n */\nexport type PushAnalyticsPayload = {\n notification_id: string;\n /** Free-form snake_case label set by the producer. */\n notification_type: string;\n /** Team-owned, open-ended (e.g. `eth_received`). */\n notification_subtype: string;\n /** Server-side cross-check; clients prefer their own AuthController source. */\n profile_id?: string;\n /** Only present when the notification has a chain context. */\n chain_id?: number;\n /** Platform notifications only; the CTA link to route to on tap. */\n deeplink?: string;\n};\n"]}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Analytics fields carried by the `NotificationServicesPushController` messenger
|
|
3
|
-
* events (`onNewNotifications`, `pushNotificationClicked`). Read directly from
|
|
4
|
-
* top-level FCM payload keys, so clients build Segment events without fallback
|
|
5
|
-
* chains or parsing a `metadata` blob.
|
|
6
|
-
*/
|
|
7
|
-
export type PushAnalyticsPayload = {
|
|
8
|
-
notification_id: string;
|
|
9
|
-
/** Free-form snake_case label set by the producer. */
|
|
10
|
-
notification_type: string;
|
|
11
|
-
/** Team-owned, open-ended (e.g. `eth_received`). */
|
|
12
|
-
notification_subtype: string;
|
|
13
|
-
/** Server-side cross-check; clients prefer their own AuthController source. */
|
|
14
|
-
profile_id?: string;
|
|
15
|
-
/** Only present when the notification has a chain context. */
|
|
16
|
-
chain_id?: number;
|
|
17
|
-
/** Platform notifications only; the CTA link to route to on tap. */
|
|
18
|
-
deeplink?: string;
|
|
19
|
-
};
|
|
20
|
-
//# sourceMappingURL=push-analytics.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"push-analytics.d.cts","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/types/push-analytics.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Analytics fields carried by the `NotificationServicesPushController` messenger
|
|
3
|
-
* events (`onNewNotifications`, `pushNotificationClicked`). Read directly from
|
|
4
|
-
* top-level FCM payload keys, so clients build Segment events without fallback
|
|
5
|
-
* chains or parsing a `metadata` blob.
|
|
6
|
-
*/
|
|
7
|
-
export type PushAnalyticsPayload = {
|
|
8
|
-
notification_id: string;
|
|
9
|
-
/** Free-form snake_case label set by the producer. */
|
|
10
|
-
notification_type: string;
|
|
11
|
-
/** Team-owned, open-ended (e.g. `eth_received`). */
|
|
12
|
-
notification_subtype: string;
|
|
13
|
-
/** Server-side cross-check; clients prefer their own AuthController source. */
|
|
14
|
-
profile_id?: string;
|
|
15
|
-
/** Only present when the notification has a chain context. */
|
|
16
|
-
chain_id?: number;
|
|
17
|
-
/** Platform notifications only; the CTA link to route to on tap. */
|
|
18
|
-
deeplink?: string;
|
|
19
|
-
};
|
|
20
|
-
//# sourceMappingURL=push-analytics.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"push-analytics.d.mts","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/types/push-analytics.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"push-analytics.mjs","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/types/push-analytics.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,yDAAyD","sourcesContent":["// snake_case mirrors the FCM payload and Segment schema keys\n/* eslint-disable @typescript-eslint/naming-convention */\n\n/**\n * Analytics fields carried by the `NotificationServicesPushController` messenger\n * events (`onNewNotifications`, `pushNotificationClicked`). Read directly from\n * top-level FCM payload keys, so clients build Segment events without fallback\n * chains or parsing a `metadata` blob.\n */\nexport type PushAnalyticsPayload = {\n notification_id: string;\n /** Free-form snake_case label set by the producer. */\n notification_type: string;\n /** Team-owned, open-ended (e.g. `eth_received`). */\n notification_subtype: string;\n /** Server-side cross-check; clients prefer their own AuthController source. */\n profile_id?: string;\n /** Only present when the notification has a chain context. */\n chain_id?: number;\n /** Platform notifications only; the CTA link to route to on tap. */\n deeplink?: string;\n};\n"]}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toPushAnalyticsPayload = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Builds the first-class push analytics payload from the top-level FCM `data`
|
|
6
|
-
* keys written by push-services. Returns `null` when the required identity
|
|
7
|
-
* fields are missing (e.g. a malformed or legacy payload), so callers can
|
|
8
|
-
* safely bail out.
|
|
9
|
-
*
|
|
10
|
-
* @param data - the top-level FCM `data` map (all values are strings).
|
|
11
|
-
* @returns the analytics payload, or `null` if required fields are absent.
|
|
12
|
-
*/
|
|
13
|
-
function toPushAnalyticsPayload(data) {
|
|
14
|
-
if (!data?.notification_id || !data?.notification_type) {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
return {
|
|
18
|
-
notification_id: data.notification_id,
|
|
19
|
-
notification_type: data.notification_type,
|
|
20
|
-
notification_subtype: data.notification_subtype ?? '',
|
|
21
|
-
profile_id: data.profile_id || undefined,
|
|
22
|
-
chain_id: data.chain_id ? Number(data.chain_id) : undefined,
|
|
23
|
-
deeplink: data.deeplink || undefined,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
exports.toPushAnalyticsPayload = toPushAnalyticsPayload;
|
|
27
|
-
//# sourceMappingURL=to-push-analytics-payload.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"to-push-analytics-payload.cjs","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/utils/to-push-analytics-payload.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;GAQG;AACH,SAAgB,sBAAsB,CACpC,IAAwC;IAExC,IAAI,CAAC,IAAI,EAAE,eAAe,IAAI,CAAC,IAAI,EAAE,iBAAiB,EAAE,CAAC;QACvD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,eAAe,EAAE,IAAI,CAAC,eAAe;QACrC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;QACzC,oBAAoB,EAAE,IAAI,CAAC,oBAAoB,IAAI,EAAE;QACrD,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,SAAS;QACxC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS;QAC3D,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,SAAS;KACrC,CAAC;AACJ,CAAC;AAfD,wDAeC","sourcesContent":["import type { PushAnalyticsPayload } from '../types';\n\n/**\n * Builds the first-class push analytics payload from the top-level FCM `data`\n * keys written by push-services. Returns `null` when the required identity\n * fields are missing (e.g. a malformed or legacy payload), so callers can\n * safely bail out.\n *\n * @param data - the top-level FCM `data` map (all values are strings).\n * @returns the analytics payload, or `null` if required fields are absent.\n */\nexport function toPushAnalyticsPayload(\n data: Record<string, string> | undefined,\n): PushAnalyticsPayload | null {\n if (!data?.notification_id || !data?.notification_type) {\n return null;\n }\n\n return {\n notification_id: data.notification_id,\n notification_type: data.notification_type,\n notification_subtype: data.notification_subtype ?? '',\n profile_id: data.profile_id || undefined,\n chain_id: data.chain_id ? Number(data.chain_id) : undefined,\n deeplink: data.deeplink || undefined,\n };\n}\n"]}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { PushAnalyticsPayload } from "../types/index.cjs";
|
|
2
|
-
/**
|
|
3
|
-
* Builds the first-class push analytics payload from the top-level FCM `data`
|
|
4
|
-
* keys written by push-services. Returns `null` when the required identity
|
|
5
|
-
* fields are missing (e.g. a malformed or legacy payload), so callers can
|
|
6
|
-
* safely bail out.
|
|
7
|
-
*
|
|
8
|
-
* @param data - the top-level FCM `data` map (all values are strings).
|
|
9
|
-
* @returns the analytics payload, or `null` if required fields are absent.
|
|
10
|
-
*/
|
|
11
|
-
export declare function toPushAnalyticsPayload(data: Record<string, string> | undefined): PushAnalyticsPayload | null;
|
|
12
|
-
//# sourceMappingURL=to-push-analytics-payload.d.cts.map
|