@metamask-previews/notification-services-controller 0.15.0-preview-579728ba → 0.15.0-preview-209dbcc
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/dist/NotificationServicesPushController/services/push/push-web.cjs +21 -1
- package/dist/NotificationServicesPushController/services/push/push-web.cjs.map +1 -1
- package/dist/NotificationServicesPushController/services/push/push-web.d.cts +2 -1
- package/dist/NotificationServicesPushController/services/push/push-web.d.cts.map +1 -1
- package/dist/NotificationServicesPushController/services/push/push-web.d.mts +2 -1
- package/dist/NotificationServicesPushController/services/push/push-web.d.mts.map +1 -1
- package/dist/NotificationServicesPushController/services/push/push-web.mjs +21 -1
- package/dist/NotificationServicesPushController/services/push/push-web.mjs.map +1 -1
- package/dist/NotificationServicesPushController/services/services.cjs +1 -1
- package/dist/NotificationServicesPushController/services/services.cjs.map +1 -1
- package/dist/NotificationServicesPushController/services/services.mjs +1 -1
- package/dist/NotificationServicesPushController/services/services.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -3,13 +3,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.listenToPushNotificationsClicked = exports.listenToPushNotificationsReceived = exports.deleteRegToken = exports.createRegToken = void 0;
|
|
6
|
+
exports.listenToPushNotificationsClicked = exports.listenToPushNotificationsReceived = exports.deleteRegToken = exports.createRegToken = exports.supportedCache = void 0;
|
|
7
7
|
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
11
|
const NotificationServicesController_1 = require("../../../NotificationServicesController/index.cjs");
|
|
12
12
|
const to_raw_notification_1 = require("../../../shared/to-raw-notification.cjs");
|
|
13
|
+
// Exported to help testing
|
|
14
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
15
|
+
exports.supportedCache = null;
|
|
16
|
+
const getPushAvailability = async () => {
|
|
17
|
+
exports.supportedCache ?? (exports.supportedCache = await (0, sw_1.isSupported)());
|
|
18
|
+
return exports.supportedCache;
|
|
19
|
+
};
|
|
13
20
|
const createFirebaseApp = async (env) => {
|
|
14
21
|
try {
|
|
15
22
|
return (0, app_1.getApp)();
|
|
@@ -28,6 +35,10 @@ const createFirebaseApp = async (env) => {
|
|
|
28
35
|
}
|
|
29
36
|
};
|
|
30
37
|
const getFirebaseMessaging = async (env) => {
|
|
38
|
+
const supported = await getPushAvailability();
|
|
39
|
+
if (!supported) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
31
42
|
const app = await createFirebaseApp(env);
|
|
32
43
|
return (0, sw_1.getMessaging)(app);
|
|
33
44
|
};
|
|
@@ -40,6 +51,9 @@ const getFirebaseMessaging = async (env) => {
|
|
|
40
51
|
async function createRegToken(env) {
|
|
41
52
|
try {
|
|
42
53
|
const messaging = await getFirebaseMessaging(env);
|
|
54
|
+
if (!messaging) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
43
57
|
const token = await (0, messaging_1.getToken)(messaging, {
|
|
44
58
|
serviceWorkerRegistration: self.registration,
|
|
45
59
|
vapidKey: env.vapidKey,
|
|
@@ -60,6 +74,9 @@ exports.createRegToken = createRegToken;
|
|
|
60
74
|
async function deleteRegToken(env) {
|
|
61
75
|
try {
|
|
62
76
|
const messaging = await getFirebaseMessaging(env);
|
|
77
|
+
if (!messaging) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
63
80
|
await (0, messaging_1.deleteToken)(messaging);
|
|
64
81
|
return true;
|
|
65
82
|
}
|
|
@@ -76,6 +93,9 @@ exports.deleteRegToken = deleteRegToken;
|
|
|
76
93
|
*/
|
|
77
94
|
async function listenToPushNotificationsReceived(env, handler) {
|
|
78
95
|
const messaging = await getFirebaseMessaging(env);
|
|
96
|
+
if (!messaging) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
79
99
|
const unsubscribePushNotifications = (0, sw_1.onBackgroundMessage)(messaging,
|
|
80
100
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
81
101
|
async (payload) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push-web.cjs","sourceRoot":"","sources":["../../../../src/NotificationServicesPushController/services/push/push-web.ts"],"names":[],"mappings":";;;;;;AAIA,sCAAqD;AACrD,kDAA2D;AAC3D,
|
|
1
|
+
{"version":3,"file":"push-web.cjs","sourceRoot":"","sources":["../../../../src/NotificationServicesPushController/services/push/push-web.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 { Processors } from '../../../NotificationServicesController';\nimport { toRawOnChainNotification } from '../../../shared/to-raw-notification';\nimport type { PushNotificationEnv } from '../../types/firebase';\n\ndeclare const self: ServiceWorkerGlobalScope;\n\n// Exported to help testing\n// eslint-disable-next-line import/no-mutable-exports\nexport let supportedCache: boolean | null = null;\n\nconst getPushAvailability = async () => {\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 (error) {\n return false;\n }\n}\n\n/**\n * Service Worker Listener for when push notifications are received.\n * @param env - push notification environment\n * @param handler - handler to actually showing notification, MUST BE PROVEDED\n * @returns unsubscribe handler\n */\nexport async 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) => {\n try {\n const data: Types.UnprocessedOnChainRawNotification | undefined =\n payload?.data?.data ? JSON.parse(payload?.data?.data) : undefined;\n\n if (!data) {\n return;\n }\n\n const notificationData = toRawOnChainNotification(data);\n const notification = Processors.processNotification(notificationData);\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 throw new Error('Unable to send push notification');\n }\n },\n );\n\n const unsubscribe = () => 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 */\nexport function listenToPushNotificationsClicked(\n handler: (e: NotificationEvent, notification?: Types.INotification) => void,\n) {\n const clickHandler = (event: NotificationEvent) => {\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 = () =>\n self.removeEventListener('notificationclick', clickHandler);\n return unsubscribe;\n}\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference lib="webworker" />
|
|
2
2
|
import type { Types } from "../../../NotificationServicesController/index.cjs";
|
|
3
3
|
import type { PushNotificationEnv } from "../../types/firebase.cjs";
|
|
4
|
+
export declare let supportedCache: boolean | null;
|
|
4
5
|
/**
|
|
5
6
|
* Creates a registration token for Firebase Cloud Messaging.
|
|
6
7
|
*
|
|
@@ -21,7 +22,7 @@ export declare function deleteRegToken(env: PushNotificationEnv): Promise<boolea
|
|
|
21
22
|
* @param handler - handler to actually showing notification, MUST BE PROVEDED
|
|
22
23
|
* @returns unsubscribe handler
|
|
23
24
|
*/
|
|
24
|
-
export declare function listenToPushNotificationsReceived(env: PushNotificationEnv, handler: (notification: Types.INotification) => void | Promise<void>): Promise<() => void>;
|
|
25
|
+
export declare function listenToPushNotificationsReceived(env: PushNotificationEnv, handler: (notification: Types.INotification) => void | Promise<void>): Promise<(() => void) | null>;
|
|
25
26
|
/**
|
|
26
27
|
* Service Worker Listener for when a notification is clicked
|
|
27
28
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push-web.d.cts","sourceRoot":"","sources":["../../../../src/NotificationServicesPushController/services/push/push-web.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"push-web.d.cts","sourceRoot":"","sources":["../../../../src/NotificationServicesPushController/services/push/push-web.ts"],"names":[],"mappings":";AAcA,OAAO,KAAK,EAAE,KAAK,EAAE,0DAAgD;AAGrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,iCAA6B;AAMhE,eAAO,IAAI,cAAc,EAAE,OAAO,GAAG,IAAW,CAAC;AAsCjD;;;;;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;AAED;;;;;GAKG;AACH,wBAAsB,iCAAiC,CACrD,GAAG,EAAE,mBAAmB,EACxB,OAAO,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACnE,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,CAkC9B;AAED;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,CAAC,CAAC,EAAE,iBAAiB,EAAE,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa,KAAK,IAAI,cAY5E"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference lib="webworker" />
|
|
2
2
|
import type { Types } from "../../../NotificationServicesController/index.mjs";
|
|
3
3
|
import type { PushNotificationEnv } from "../../types/firebase.mjs";
|
|
4
|
+
export declare let supportedCache: boolean | null;
|
|
4
5
|
/**
|
|
5
6
|
* Creates a registration token for Firebase Cloud Messaging.
|
|
6
7
|
*
|
|
@@ -21,7 +22,7 @@ export declare function deleteRegToken(env: PushNotificationEnv): Promise<boolea
|
|
|
21
22
|
* @param handler - handler to actually showing notification, MUST BE PROVEDED
|
|
22
23
|
* @returns unsubscribe handler
|
|
23
24
|
*/
|
|
24
|
-
export declare function listenToPushNotificationsReceived(env: PushNotificationEnv, handler: (notification: Types.INotification) => void | Promise<void>): Promise<() => void>;
|
|
25
|
+
export declare function listenToPushNotificationsReceived(env: PushNotificationEnv, handler: (notification: Types.INotification) => void | Promise<void>): Promise<(() => void) | null>;
|
|
25
26
|
/**
|
|
26
27
|
* Service Worker Listener for when a notification is clicked
|
|
27
28
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push-web.d.mts","sourceRoot":"","sources":["../../../../src/NotificationServicesPushController/services/push/push-web.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"push-web.d.mts","sourceRoot":"","sources":["../../../../src/NotificationServicesPushController/services/push/push-web.ts"],"names":[],"mappings":";AAcA,OAAO,KAAK,EAAE,KAAK,EAAE,0DAAgD;AAGrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,iCAA6B;AAMhE,eAAO,IAAI,cAAc,EAAE,OAAO,GAAG,IAAW,CAAC;AAsCjD;;;;;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;AAED;;;;;GAKG;AACH,wBAAsB,iCAAiC,CACrD,GAAG,EAAE,mBAAmB,EACxB,OAAO,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACnE,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,CAkC9B;AAED;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,CAAC,CAAC,EAAE,iBAAiB,EAAE,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa,KAAK,IAAI,cAY5E"}
|
|
@@ -6,11 +6,18 @@ function $importDefault(module) {
|
|
|
6
6
|
}
|
|
7
7
|
import { getApp, initializeApp } from "firebase/app";
|
|
8
8
|
import { getToken, deleteToken } from "firebase/messaging";
|
|
9
|
-
import { getMessaging, onBackgroundMessage } from "firebase/messaging/sw";
|
|
9
|
+
import { getMessaging, onBackgroundMessage, isSupported } from "firebase/messaging/sw";
|
|
10
10
|
import $log from "loglevel";
|
|
11
11
|
const log = $importDefault($log);
|
|
12
12
|
import { Processors } from "../../../NotificationServicesController/index.mjs";
|
|
13
13
|
import { toRawOnChainNotification } from "../../../shared/to-raw-notification.mjs";
|
|
14
|
+
// Exported to help testing
|
|
15
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
16
|
+
export let supportedCache = null;
|
|
17
|
+
const getPushAvailability = async () => {
|
|
18
|
+
supportedCache ?? (supportedCache = await isSupported());
|
|
19
|
+
return supportedCache;
|
|
20
|
+
};
|
|
14
21
|
const createFirebaseApp = async (env) => {
|
|
15
22
|
try {
|
|
16
23
|
return getApp();
|
|
@@ -29,6 +36,10 @@ const createFirebaseApp = async (env) => {
|
|
|
29
36
|
}
|
|
30
37
|
};
|
|
31
38
|
const getFirebaseMessaging = async (env) => {
|
|
39
|
+
const supported = await getPushAvailability();
|
|
40
|
+
if (!supported) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
32
43
|
const app = await createFirebaseApp(env);
|
|
33
44
|
return getMessaging(app);
|
|
34
45
|
};
|
|
@@ -41,6 +52,9 @@ const getFirebaseMessaging = async (env) => {
|
|
|
41
52
|
export async function createRegToken(env) {
|
|
42
53
|
try {
|
|
43
54
|
const messaging = await getFirebaseMessaging(env);
|
|
55
|
+
if (!messaging) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
44
58
|
const token = await getToken(messaging, {
|
|
45
59
|
serviceWorkerRegistration: self.registration,
|
|
46
60
|
vapidKey: env.vapidKey,
|
|
@@ -60,6 +74,9 @@ export async function createRegToken(env) {
|
|
|
60
74
|
export async function deleteRegToken(env) {
|
|
61
75
|
try {
|
|
62
76
|
const messaging = await getFirebaseMessaging(env);
|
|
77
|
+
if (!messaging) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
63
80
|
await deleteToken(messaging);
|
|
64
81
|
return true;
|
|
65
82
|
}
|
|
@@ -75,6 +92,9 @@ export async function deleteRegToken(env) {
|
|
|
75
92
|
*/
|
|
76
93
|
export async function listenToPushNotificationsReceived(env, handler) {
|
|
77
94
|
const messaging = await getFirebaseMessaging(env);
|
|
95
|
+
if (!messaging) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
78
98
|
const unsubscribePushNotifications = onBackgroundMessage(messaging,
|
|
79
99
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
80
100
|
async (payload) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push-web.mjs","sourceRoot":"","sources":["../../../../src/NotificationServicesPushController/services/push/push-web.ts"],"names":[],"mappings":";;;;;;AAIA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,qBAAqB;AACrD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,2BAA2B;AAC3D,OAAO,
|
|
1
|
+
{"version":3,"file":"push-web.mjs","sourceRoot":"","sources":["../../../../src/NotificationServicesPushController/services/push/push-web.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 { Processors } from '../../../NotificationServicesController';\nimport { toRawOnChainNotification } from '../../../shared/to-raw-notification';\nimport type { PushNotificationEnv } from '../../types/firebase';\n\ndeclare const self: ServiceWorkerGlobalScope;\n\n// Exported to help testing\n// eslint-disable-next-line import/no-mutable-exports\nexport let supportedCache: boolean | null = null;\n\nconst getPushAvailability = async () => {\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 (error) {\n return false;\n }\n}\n\n/**\n * Service Worker Listener for when push notifications are received.\n * @param env - push notification environment\n * @param handler - handler to actually showing notification, MUST BE PROVEDED\n * @returns unsubscribe handler\n */\nexport async 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) => {\n try {\n const data: Types.UnprocessedOnChainRawNotification | undefined =\n payload?.data?.data ? JSON.parse(payload?.data?.data) : undefined;\n\n if (!data) {\n return;\n }\n\n const notificationData = toRawOnChainNotification(data);\n const notification = Processors.processNotification(notificationData);\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 throw new Error('Unable to send push notification');\n }\n },\n );\n\n const unsubscribe = () => 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 */\nexport function listenToPushNotificationsClicked(\n handler: (e: NotificationEvent, notification?: Types.INotification) => void,\n) {\n const clickHandler = (event: NotificationEvent) => {\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 = () =>\n self.removeEventListener('notificationclick', clickHandler);\n return unsubscribe;\n}\n"]}
|
|
@@ -188,7 +188,7 @@ async function listenToPushNotifications(params) {
|
|
|
188
188
|
const unsubscribePushNotifications = await (0, push_web_1.listenToPushNotificationsReceived)(env, listenToPushReceived);
|
|
189
189
|
const unsubscribeNotificationClicks = (0, push_web_1.listenToPushNotificationsClicked)(listenToPushClicked);
|
|
190
190
|
const unsubscribe = () => {
|
|
191
|
-
unsubscribePushNotifications();
|
|
191
|
+
unsubscribePushNotifications?.();
|
|
192
192
|
unsubscribeNotificationClicks();
|
|
193
193
|
};
|
|
194
194
|
return unsubscribe;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.cjs","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/services/services.ts"],"names":[],"mappings":"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","sourcesContent":["import log from 'loglevel';\n\nimport type { Types } from '../../NotificationServicesController';\nimport type { PushNotificationEnv } from '../types';\nimport * as endpoints from './endpoints';\nimport type { CreateRegToken, DeleteRegToken } from './push';\nimport {\n listenToPushNotificationsClicked,\n listenToPushNotificationsReceived,\n} from './push/push-web';\n\nexport type RegToken = {\n token: string;\n platform: 'extension' | 'mobile' | 'portfolio';\n};\n\n/**\n * Links API Response Shape\n */\nexport type LinksResult = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n trigger_ids: string[];\n // eslint-disable-next-line @typescript-eslint/naming-convention\n registration_tokens: RegToken[];\n};\n\n/**\n * Fetches push notification links from a remote endpoint using a BearerToken for authorization.\n *\n * @param bearerToken - The JSON Web Token used for authorization.\n * @returns A promise that resolves with the links result or null if an error occurs.\n */\nexport async function getPushNotificationLinks(\n bearerToken: string,\n): Promise<LinksResult | null> {\n try {\n const response = await fetch(endpoints.REGISTRATION_TOKENS_ENDPOINT, {\n headers: { Authorization: `Bearer ${bearerToken}` },\n });\n if (!response.ok) {\n log.error('Failed to fetch the push notification links');\n throw new Error('Failed to fetch the push notification links');\n }\n return response.json() as Promise<LinksResult>;\n } catch (error) {\n log.error('Failed to fetch the push notification links', error);\n return null;\n }\n}\n\n/**\n * Updates the push notification links on a remote API.\n *\n * @param bearerToken - The JSON Web Token used for authorization.\n * @param triggers - An array of trigger identifiers.\n * @param regTokens - An array of registration tokens.\n * @returns A promise that resolves with true if the update was successful, false otherwise.\n */\nexport async function updateLinksAPI(\n bearerToken: string,\n triggers: string[],\n regTokens: RegToken[],\n): Promise<boolean> {\n try {\n const body: LinksResult = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n trigger_ids: triggers,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n registration_tokens: regTokens,\n };\n const response = await fetch(endpoints.REGISTRATION_TOKENS_ENDPOINT, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${bearerToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n });\n return response.status === 200;\n } catch {\n return false;\n }\n}\n\ntype ActivatePushNotificationsParams = {\n // Push Links\n bearerToken: string;\n triggers: string[];\n\n // Push Registration\n env: PushNotificationEnv;\n createRegToken: CreateRegToken;\n platform: 'extension' | 'mobile' | 'portfolio';\n fcmToken?: string;\n};\n\n/**\n * Enables push notifications by registering the device and linking triggers.\n *\n * @param params - Activate Push Params\n * @returns A promise that resolves with an object containing the success status and the BearerToken token.\n */\nexport async function activatePushNotifications(\n params: ActivatePushNotificationsParams,\n): Promise<string | null> {\n const { bearerToken, triggers, env, createRegToken, platform, fcmToken } =\n params;\n\n const notificationLinks = await getPushNotificationLinks(bearerToken);\n\n if (!notificationLinks) {\n return null;\n }\n\n const regToken = fcmToken ?? (await createRegToken(env).catch(() => null));\n if (!regToken) {\n return null;\n }\n\n const newRegTokens = new Set(notificationLinks.registration_tokens);\n newRegTokens.add({ token: regToken, platform });\n\n await updateLinksAPI(bearerToken, triggers, Array.from(newRegTokens));\n return regToken;\n}\n\ntype DeactivatePushNotificationsParams = {\n // Push Links\n regToken: string;\n bearerToken: string;\n triggers: string[];\n\n // Push Un-registration\n env: PushNotificationEnv;\n deleteRegToken: DeleteRegToken;\n};\n\n/**\n * Disables push notifications by removing the registration token and unlinking triggers.\n *\n * @param params - Deactivate Push Params\n * @returns A promise that resolves with true if notifications were successfully disabled, false otherwise.\n */\nexport async function deactivatePushNotifications(\n params: DeactivatePushNotificationsParams,\n): Promise<boolean> {\n const { regToken, bearerToken, triggers, env, deleteRegToken } = params;\n\n // if we don't have a reg token, then we can early return\n if (!regToken) {\n return true;\n }\n\n const notificationLinks = await getPushNotificationLinks(bearerToken);\n if (!notificationLinks) {\n return false;\n }\n\n const filteredRegTokens = notificationLinks.registration_tokens.filter(\n (r) => r.token !== regToken,\n );\n\n const isTokenRemovedFromAPI = await updateLinksAPI(\n bearerToken,\n triggers,\n filteredRegTokens,\n );\n if (!isTokenRemovedFromAPI) {\n return false;\n }\n\n const isTokenRemovedFromFCM = await deleteRegToken(env);\n if (!isTokenRemovedFromFCM) {\n return false;\n }\n\n return true;\n}\n\ntype UpdateTriggerPushNotificationsParams = {\n // Push Links\n regToken: string;\n bearerToken: string;\n triggers: string[];\n\n // Push Registration\n env: PushNotificationEnv;\n createRegToken: CreateRegToken;\n platform: 'extension' | 'mobile' | 'portfolio';\n\n // Push Un-registration\n deleteRegToken: DeleteRegToken;\n};\n\n/**\n * Updates the triggers linked to push notifications for a given registration token.\n * If the provided registration token does not exist or is not in the current set of registration tokens,\n * a new registration token is created and used for the update.\n *\n * @param params - Update Push Params\n * @returns A promise that resolves with an object containing:\n * - isTriggersLinkedToPushNotifications: boolean indicating if the triggers were successfully updated.\n * - fcmToken: the new or existing Firebase Cloud Messaging token used for the update, if applicable.\n */\nexport async function updateTriggerPushNotifications(\n params: UpdateTriggerPushNotificationsParams,\n): Promise<{\n isTriggersLinkedToPushNotifications: boolean;\n fcmToken?: string | null;\n}> {\n const {\n bearerToken,\n regToken,\n triggers,\n createRegToken,\n platform,\n deleteRegToken,\n env,\n } = params;\n\n const notificationLinks = await getPushNotificationLinks(bearerToken);\n if (!notificationLinks) {\n return { isTriggersLinkedToPushNotifications: false };\n }\n // Create new registration token if doesn't exist\n const hasRegToken = Boolean(\n regToken &&\n notificationLinks.registration_tokens.some((r) => r.token === regToken),\n );\n\n let newRegToken: string | null = null;\n if (!hasRegToken) {\n await deleteRegToken(env);\n newRegToken = await createRegToken(env);\n if (!newRegToken) {\n throw new Error('Failed to create a new registration token');\n }\n notificationLinks.registration_tokens.push({\n token: newRegToken,\n platform,\n });\n }\n\n const isTriggersLinkedToPushNotifications = await updateLinksAPI(\n bearerToken,\n triggers,\n notificationLinks.registration_tokens,\n );\n\n return {\n isTriggersLinkedToPushNotifications,\n fcmToken: newRegToken ?? null,\n };\n}\n\ntype ListenToPushNotificationsParams = {\n env: PushNotificationEnv;\n listenToPushReceived: (\n notification: Types.INotification,\n ) => void | Promise<void>;\n listenToPushClicked: (\n event: NotificationEvent,\n notification?: Types.INotification,\n ) => void;\n};\n\n/**\n * Listens to push notifications and invokes the provided callback function with the received notification data.\n *\n * @param params - listen params\n * @returns A promise that resolves to an unsubscribe function to stop listening to push notifications.\n */\nexport async function listenToPushNotifications(\n params: ListenToPushNotificationsParams,\n): Promise<() => void> {\n const { env, listenToPushReceived, listenToPushClicked } = params;\n\n /*\n Push notifications require 2 listeners that need tracking (when creating and for tearing down):\n 1. handling receiving a push notification (and the content we want to display)\n 2. handling when a user clicks on a push notification\n */\n const unsubscribePushNotifications = await listenToPushNotificationsReceived(\n env,\n listenToPushReceived,\n );\n const unsubscribeNotificationClicks =\n listenToPushNotificationsClicked(listenToPushClicked);\n\n const unsubscribe = () => {\n unsubscribePushNotifications();\n unsubscribeNotificationClicks();\n };\n\n return unsubscribe;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"services.cjs","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/services/services.ts"],"names":[],"mappings":"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","sourcesContent":["import log from 'loglevel';\n\nimport type { Types } from '../../NotificationServicesController';\nimport type { PushNotificationEnv } from '../types';\nimport * as endpoints from './endpoints';\nimport type { CreateRegToken, DeleteRegToken } from './push';\nimport {\n listenToPushNotificationsClicked,\n listenToPushNotificationsReceived,\n} from './push/push-web';\n\nexport type RegToken = {\n token: string;\n platform: 'extension' | 'mobile' | 'portfolio';\n};\n\n/**\n * Links API Response Shape\n */\nexport type LinksResult = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n trigger_ids: string[];\n // eslint-disable-next-line @typescript-eslint/naming-convention\n registration_tokens: RegToken[];\n};\n\n/**\n * Fetches push notification links from a remote endpoint using a BearerToken for authorization.\n *\n * @param bearerToken - The JSON Web Token used for authorization.\n * @returns A promise that resolves with the links result or null if an error occurs.\n */\nexport async function getPushNotificationLinks(\n bearerToken: string,\n): Promise<LinksResult | null> {\n try {\n const response = await fetch(endpoints.REGISTRATION_TOKENS_ENDPOINT, {\n headers: { Authorization: `Bearer ${bearerToken}` },\n });\n if (!response.ok) {\n log.error('Failed to fetch the push notification links');\n throw new Error('Failed to fetch the push notification links');\n }\n return response.json() as Promise<LinksResult>;\n } catch (error) {\n log.error('Failed to fetch the push notification links', error);\n return null;\n }\n}\n\n/**\n * Updates the push notification links on a remote API.\n *\n * @param bearerToken - The JSON Web Token used for authorization.\n * @param triggers - An array of trigger identifiers.\n * @param regTokens - An array of registration tokens.\n * @returns A promise that resolves with true if the update was successful, false otherwise.\n */\nexport async function updateLinksAPI(\n bearerToken: string,\n triggers: string[],\n regTokens: RegToken[],\n): Promise<boolean> {\n try {\n const body: LinksResult = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n trigger_ids: triggers,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n registration_tokens: regTokens,\n };\n const response = await fetch(endpoints.REGISTRATION_TOKENS_ENDPOINT, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${bearerToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n });\n return response.status === 200;\n } catch {\n return false;\n }\n}\n\ntype ActivatePushNotificationsParams = {\n // Push Links\n bearerToken: string;\n triggers: string[];\n\n // Push Registration\n env: PushNotificationEnv;\n createRegToken: CreateRegToken;\n platform: 'extension' | 'mobile' | 'portfolio';\n fcmToken?: string;\n};\n\n/**\n * Enables push notifications by registering the device and linking triggers.\n *\n * @param params - Activate Push Params\n * @returns A promise that resolves with an object containing the success status and the BearerToken token.\n */\nexport async function activatePushNotifications(\n params: ActivatePushNotificationsParams,\n): Promise<string | null> {\n const { bearerToken, triggers, env, createRegToken, platform, fcmToken } =\n params;\n\n const notificationLinks = await getPushNotificationLinks(bearerToken);\n\n if (!notificationLinks) {\n return null;\n }\n\n const regToken = fcmToken ?? (await createRegToken(env).catch(() => null));\n if (!regToken) {\n return null;\n }\n\n const newRegTokens = new Set(notificationLinks.registration_tokens);\n newRegTokens.add({ token: regToken, platform });\n\n await updateLinksAPI(bearerToken, triggers, Array.from(newRegTokens));\n return regToken;\n}\n\ntype DeactivatePushNotificationsParams = {\n // Push Links\n regToken: string;\n bearerToken: string;\n triggers: string[];\n\n // Push Un-registration\n env: PushNotificationEnv;\n deleteRegToken: DeleteRegToken;\n};\n\n/**\n * Disables push notifications by removing the registration token and unlinking triggers.\n *\n * @param params - Deactivate Push Params\n * @returns A promise that resolves with true if notifications were successfully disabled, false otherwise.\n */\nexport async function deactivatePushNotifications(\n params: DeactivatePushNotificationsParams,\n): Promise<boolean> {\n const { regToken, bearerToken, triggers, env, deleteRegToken } = params;\n\n // if we don't have a reg token, then we can early return\n if (!regToken) {\n return true;\n }\n\n const notificationLinks = await getPushNotificationLinks(bearerToken);\n if (!notificationLinks) {\n return false;\n }\n\n const filteredRegTokens = notificationLinks.registration_tokens.filter(\n (r) => r.token !== regToken,\n );\n\n const isTokenRemovedFromAPI = await updateLinksAPI(\n bearerToken,\n triggers,\n filteredRegTokens,\n );\n if (!isTokenRemovedFromAPI) {\n return false;\n }\n\n const isTokenRemovedFromFCM = await deleteRegToken(env);\n if (!isTokenRemovedFromFCM) {\n return false;\n }\n\n return true;\n}\n\ntype UpdateTriggerPushNotificationsParams = {\n // Push Links\n regToken: string;\n bearerToken: string;\n triggers: string[];\n\n // Push Registration\n env: PushNotificationEnv;\n createRegToken: CreateRegToken;\n platform: 'extension' | 'mobile' | 'portfolio';\n\n // Push Un-registration\n deleteRegToken: DeleteRegToken;\n};\n\n/**\n * Updates the triggers linked to push notifications for a given registration token.\n * If the provided registration token does not exist or is not in the current set of registration tokens,\n * a new registration token is created and used for the update.\n *\n * @param params - Update Push Params\n * @returns A promise that resolves with an object containing:\n * - isTriggersLinkedToPushNotifications: boolean indicating if the triggers were successfully updated.\n * - fcmToken: the new or existing Firebase Cloud Messaging token used for the update, if applicable.\n */\nexport async function updateTriggerPushNotifications(\n params: UpdateTriggerPushNotificationsParams,\n): Promise<{\n isTriggersLinkedToPushNotifications: boolean;\n fcmToken?: string | null;\n}> {\n const {\n bearerToken,\n regToken,\n triggers,\n createRegToken,\n platform,\n deleteRegToken,\n env,\n } = params;\n\n const notificationLinks = await getPushNotificationLinks(bearerToken);\n if (!notificationLinks) {\n return { isTriggersLinkedToPushNotifications: false };\n }\n // Create new registration token if doesn't exist\n const hasRegToken = Boolean(\n regToken &&\n notificationLinks.registration_tokens.some((r) => r.token === regToken),\n );\n\n let newRegToken: string | null = null;\n if (!hasRegToken) {\n await deleteRegToken(env);\n newRegToken = await createRegToken(env);\n if (!newRegToken) {\n throw new Error('Failed to create a new registration token');\n }\n notificationLinks.registration_tokens.push({\n token: newRegToken,\n platform,\n });\n }\n\n const isTriggersLinkedToPushNotifications = await updateLinksAPI(\n bearerToken,\n triggers,\n notificationLinks.registration_tokens,\n );\n\n return {\n isTriggersLinkedToPushNotifications,\n fcmToken: newRegToken ?? null,\n };\n}\n\ntype ListenToPushNotificationsParams = {\n env: PushNotificationEnv;\n listenToPushReceived: (\n notification: Types.INotification,\n ) => void | Promise<void>;\n listenToPushClicked: (\n event: NotificationEvent,\n notification?: Types.INotification,\n ) => void;\n};\n\n/**\n * Listens to push notifications and invokes the provided callback function with the received notification data.\n *\n * @param params - listen params\n * @returns A promise that resolves to an unsubscribe function to stop listening to push notifications.\n */\nexport async function listenToPushNotifications(\n params: ListenToPushNotificationsParams,\n): Promise<() => void> {\n const { env, listenToPushReceived, listenToPushClicked } = params;\n\n /*\n Push notifications require 2 listeners that need tracking (when creating and for tearing down):\n 1. handling receiving a push notification (and the content we want to display)\n 2. handling when a user clicks on a push notification\n */\n const unsubscribePushNotifications = await listenToPushNotificationsReceived(\n env,\n listenToPushReceived,\n );\n const unsubscribeNotificationClicks =\n listenToPushNotificationsClicked(listenToPushClicked);\n\n const unsubscribe = () => {\n unsubscribePushNotifications?.();\n unsubscribeNotificationClicks();\n };\n\n return unsubscribe;\n}\n"]}
|
|
@@ -161,7 +161,7 @@ export async function listenToPushNotifications(params) {
|
|
|
161
161
|
const unsubscribePushNotifications = await listenToPushNotificationsReceived(env, listenToPushReceived);
|
|
162
162
|
const unsubscribeNotificationClicks = listenToPushNotificationsClicked(listenToPushClicked);
|
|
163
163
|
const unsubscribe = () => {
|
|
164
|
-
unsubscribePushNotifications();
|
|
164
|
+
unsubscribePushNotifications?.();
|
|
165
165
|
unsubscribeNotificationClicks();
|
|
166
166
|
};
|
|
167
167
|
return unsubscribe;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.mjs","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/services/services.ts"],"names":[],"mappings":"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","sourcesContent":["import log from 'loglevel';\n\nimport type { Types } from '../../NotificationServicesController';\nimport type { PushNotificationEnv } from '../types';\nimport * as endpoints from './endpoints';\nimport type { CreateRegToken, DeleteRegToken } from './push';\nimport {\n listenToPushNotificationsClicked,\n listenToPushNotificationsReceived,\n} from './push/push-web';\n\nexport type RegToken = {\n token: string;\n platform: 'extension' | 'mobile' | 'portfolio';\n};\n\n/**\n * Links API Response Shape\n */\nexport type LinksResult = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n trigger_ids: string[];\n // eslint-disable-next-line @typescript-eslint/naming-convention\n registration_tokens: RegToken[];\n};\n\n/**\n * Fetches push notification links from a remote endpoint using a BearerToken for authorization.\n *\n * @param bearerToken - The JSON Web Token used for authorization.\n * @returns A promise that resolves with the links result or null if an error occurs.\n */\nexport async function getPushNotificationLinks(\n bearerToken: string,\n): Promise<LinksResult | null> {\n try {\n const response = await fetch(endpoints.REGISTRATION_TOKENS_ENDPOINT, {\n headers: { Authorization: `Bearer ${bearerToken}` },\n });\n if (!response.ok) {\n log.error('Failed to fetch the push notification links');\n throw new Error('Failed to fetch the push notification links');\n }\n return response.json() as Promise<LinksResult>;\n } catch (error) {\n log.error('Failed to fetch the push notification links', error);\n return null;\n }\n}\n\n/**\n * Updates the push notification links on a remote API.\n *\n * @param bearerToken - The JSON Web Token used for authorization.\n * @param triggers - An array of trigger identifiers.\n * @param regTokens - An array of registration tokens.\n * @returns A promise that resolves with true if the update was successful, false otherwise.\n */\nexport async function updateLinksAPI(\n bearerToken: string,\n triggers: string[],\n regTokens: RegToken[],\n): Promise<boolean> {\n try {\n const body: LinksResult = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n trigger_ids: triggers,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n registration_tokens: regTokens,\n };\n const response = await fetch(endpoints.REGISTRATION_TOKENS_ENDPOINT, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${bearerToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n });\n return response.status === 200;\n } catch {\n return false;\n }\n}\n\ntype ActivatePushNotificationsParams = {\n // Push Links\n bearerToken: string;\n triggers: string[];\n\n // Push Registration\n env: PushNotificationEnv;\n createRegToken: CreateRegToken;\n platform: 'extension' | 'mobile' | 'portfolio';\n fcmToken?: string;\n};\n\n/**\n * Enables push notifications by registering the device and linking triggers.\n *\n * @param params - Activate Push Params\n * @returns A promise that resolves with an object containing the success status and the BearerToken token.\n */\nexport async function activatePushNotifications(\n params: ActivatePushNotificationsParams,\n): Promise<string | null> {\n const { bearerToken, triggers, env, createRegToken, platform, fcmToken } =\n params;\n\n const notificationLinks = await getPushNotificationLinks(bearerToken);\n\n if (!notificationLinks) {\n return null;\n }\n\n const regToken = fcmToken ?? (await createRegToken(env).catch(() => null));\n if (!regToken) {\n return null;\n }\n\n const newRegTokens = new Set(notificationLinks.registration_tokens);\n newRegTokens.add({ token: regToken, platform });\n\n await updateLinksAPI(bearerToken, triggers, Array.from(newRegTokens));\n return regToken;\n}\n\ntype DeactivatePushNotificationsParams = {\n // Push Links\n regToken: string;\n bearerToken: string;\n triggers: string[];\n\n // Push Un-registration\n env: PushNotificationEnv;\n deleteRegToken: DeleteRegToken;\n};\n\n/**\n * Disables push notifications by removing the registration token and unlinking triggers.\n *\n * @param params - Deactivate Push Params\n * @returns A promise that resolves with true if notifications were successfully disabled, false otherwise.\n */\nexport async function deactivatePushNotifications(\n params: DeactivatePushNotificationsParams,\n): Promise<boolean> {\n const { regToken, bearerToken, triggers, env, deleteRegToken } = params;\n\n // if we don't have a reg token, then we can early return\n if (!regToken) {\n return true;\n }\n\n const notificationLinks = await getPushNotificationLinks(bearerToken);\n if (!notificationLinks) {\n return false;\n }\n\n const filteredRegTokens = notificationLinks.registration_tokens.filter(\n (r) => r.token !== regToken,\n );\n\n const isTokenRemovedFromAPI = await updateLinksAPI(\n bearerToken,\n triggers,\n filteredRegTokens,\n );\n if (!isTokenRemovedFromAPI) {\n return false;\n }\n\n const isTokenRemovedFromFCM = await deleteRegToken(env);\n if (!isTokenRemovedFromFCM) {\n return false;\n }\n\n return true;\n}\n\ntype UpdateTriggerPushNotificationsParams = {\n // Push Links\n regToken: string;\n bearerToken: string;\n triggers: string[];\n\n // Push Registration\n env: PushNotificationEnv;\n createRegToken: CreateRegToken;\n platform: 'extension' | 'mobile' | 'portfolio';\n\n // Push Un-registration\n deleteRegToken: DeleteRegToken;\n};\n\n/**\n * Updates the triggers linked to push notifications for a given registration token.\n * If the provided registration token does not exist or is not in the current set of registration tokens,\n * a new registration token is created and used for the update.\n *\n * @param params - Update Push Params\n * @returns A promise that resolves with an object containing:\n * - isTriggersLinkedToPushNotifications: boolean indicating if the triggers were successfully updated.\n * - fcmToken: the new or existing Firebase Cloud Messaging token used for the update, if applicable.\n */\nexport async function updateTriggerPushNotifications(\n params: UpdateTriggerPushNotificationsParams,\n): Promise<{\n isTriggersLinkedToPushNotifications: boolean;\n fcmToken?: string | null;\n}> {\n const {\n bearerToken,\n regToken,\n triggers,\n createRegToken,\n platform,\n deleteRegToken,\n env,\n } = params;\n\n const notificationLinks = await getPushNotificationLinks(bearerToken);\n if (!notificationLinks) {\n return { isTriggersLinkedToPushNotifications: false };\n }\n // Create new registration token if doesn't exist\n const hasRegToken = Boolean(\n regToken &&\n notificationLinks.registration_tokens.some((r) => r.token === regToken),\n );\n\n let newRegToken: string | null = null;\n if (!hasRegToken) {\n await deleteRegToken(env);\n newRegToken = await createRegToken(env);\n if (!newRegToken) {\n throw new Error('Failed to create a new registration token');\n }\n notificationLinks.registration_tokens.push({\n token: newRegToken,\n platform,\n });\n }\n\n const isTriggersLinkedToPushNotifications = await updateLinksAPI(\n bearerToken,\n triggers,\n notificationLinks.registration_tokens,\n );\n\n return {\n isTriggersLinkedToPushNotifications,\n fcmToken: newRegToken ?? null,\n };\n}\n\ntype ListenToPushNotificationsParams = {\n env: PushNotificationEnv;\n listenToPushReceived: (\n notification: Types.INotification,\n ) => void | Promise<void>;\n listenToPushClicked: (\n event: NotificationEvent,\n notification?: Types.INotification,\n ) => void;\n};\n\n/**\n * Listens to push notifications and invokes the provided callback function with the received notification data.\n *\n * @param params - listen params\n * @returns A promise that resolves to an unsubscribe function to stop listening to push notifications.\n */\nexport async function listenToPushNotifications(\n params: ListenToPushNotificationsParams,\n): Promise<() => void> {\n const { env, listenToPushReceived, listenToPushClicked } = params;\n\n /*\n Push notifications require 2 listeners that need tracking (when creating and for tearing down):\n 1. handling receiving a push notification (and the content we want to display)\n 2. handling when a user clicks on a push notification\n */\n const unsubscribePushNotifications = await listenToPushNotificationsReceived(\n env,\n listenToPushReceived,\n );\n const unsubscribeNotificationClicks =\n listenToPushNotificationsClicked(listenToPushClicked);\n\n const unsubscribe = () => {\n unsubscribePushNotifications();\n unsubscribeNotificationClicks();\n };\n\n return unsubscribe;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"services.mjs","sourceRoot":"","sources":["../../../src/NotificationServicesPushController/services/services.ts"],"names":[],"mappings":"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","sourcesContent":["import log from 'loglevel';\n\nimport type { Types } from '../../NotificationServicesController';\nimport type { PushNotificationEnv } from '../types';\nimport * as endpoints from './endpoints';\nimport type { CreateRegToken, DeleteRegToken } from './push';\nimport {\n listenToPushNotificationsClicked,\n listenToPushNotificationsReceived,\n} from './push/push-web';\n\nexport type RegToken = {\n token: string;\n platform: 'extension' | 'mobile' | 'portfolio';\n};\n\n/**\n * Links API Response Shape\n */\nexport type LinksResult = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n trigger_ids: string[];\n // eslint-disable-next-line @typescript-eslint/naming-convention\n registration_tokens: RegToken[];\n};\n\n/**\n * Fetches push notification links from a remote endpoint using a BearerToken for authorization.\n *\n * @param bearerToken - The JSON Web Token used for authorization.\n * @returns A promise that resolves with the links result or null if an error occurs.\n */\nexport async function getPushNotificationLinks(\n bearerToken: string,\n): Promise<LinksResult | null> {\n try {\n const response = await fetch(endpoints.REGISTRATION_TOKENS_ENDPOINT, {\n headers: { Authorization: `Bearer ${bearerToken}` },\n });\n if (!response.ok) {\n log.error('Failed to fetch the push notification links');\n throw new Error('Failed to fetch the push notification links');\n }\n return response.json() as Promise<LinksResult>;\n } catch (error) {\n log.error('Failed to fetch the push notification links', error);\n return null;\n }\n}\n\n/**\n * Updates the push notification links on a remote API.\n *\n * @param bearerToken - The JSON Web Token used for authorization.\n * @param triggers - An array of trigger identifiers.\n * @param regTokens - An array of registration tokens.\n * @returns A promise that resolves with true if the update was successful, false otherwise.\n */\nexport async function updateLinksAPI(\n bearerToken: string,\n triggers: string[],\n regTokens: RegToken[],\n): Promise<boolean> {\n try {\n const body: LinksResult = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n trigger_ids: triggers,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n registration_tokens: regTokens,\n };\n const response = await fetch(endpoints.REGISTRATION_TOKENS_ENDPOINT, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${bearerToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n });\n return response.status === 200;\n } catch {\n return false;\n }\n}\n\ntype ActivatePushNotificationsParams = {\n // Push Links\n bearerToken: string;\n triggers: string[];\n\n // Push Registration\n env: PushNotificationEnv;\n createRegToken: CreateRegToken;\n platform: 'extension' | 'mobile' | 'portfolio';\n fcmToken?: string;\n};\n\n/**\n * Enables push notifications by registering the device and linking triggers.\n *\n * @param params - Activate Push Params\n * @returns A promise that resolves with an object containing the success status and the BearerToken token.\n */\nexport async function activatePushNotifications(\n params: ActivatePushNotificationsParams,\n): Promise<string | null> {\n const { bearerToken, triggers, env, createRegToken, platform, fcmToken } =\n params;\n\n const notificationLinks = await getPushNotificationLinks(bearerToken);\n\n if (!notificationLinks) {\n return null;\n }\n\n const regToken = fcmToken ?? (await createRegToken(env).catch(() => null));\n if (!regToken) {\n return null;\n }\n\n const newRegTokens = new Set(notificationLinks.registration_tokens);\n newRegTokens.add({ token: regToken, platform });\n\n await updateLinksAPI(bearerToken, triggers, Array.from(newRegTokens));\n return regToken;\n}\n\ntype DeactivatePushNotificationsParams = {\n // Push Links\n regToken: string;\n bearerToken: string;\n triggers: string[];\n\n // Push Un-registration\n env: PushNotificationEnv;\n deleteRegToken: DeleteRegToken;\n};\n\n/**\n * Disables push notifications by removing the registration token and unlinking triggers.\n *\n * @param params - Deactivate Push Params\n * @returns A promise that resolves with true if notifications were successfully disabled, false otherwise.\n */\nexport async function deactivatePushNotifications(\n params: DeactivatePushNotificationsParams,\n): Promise<boolean> {\n const { regToken, bearerToken, triggers, env, deleteRegToken } = params;\n\n // if we don't have a reg token, then we can early return\n if (!regToken) {\n return true;\n }\n\n const notificationLinks = await getPushNotificationLinks(bearerToken);\n if (!notificationLinks) {\n return false;\n }\n\n const filteredRegTokens = notificationLinks.registration_tokens.filter(\n (r) => r.token !== regToken,\n );\n\n const isTokenRemovedFromAPI = await updateLinksAPI(\n bearerToken,\n triggers,\n filteredRegTokens,\n );\n if (!isTokenRemovedFromAPI) {\n return false;\n }\n\n const isTokenRemovedFromFCM = await deleteRegToken(env);\n if (!isTokenRemovedFromFCM) {\n return false;\n }\n\n return true;\n}\n\ntype UpdateTriggerPushNotificationsParams = {\n // Push Links\n regToken: string;\n bearerToken: string;\n triggers: string[];\n\n // Push Registration\n env: PushNotificationEnv;\n createRegToken: CreateRegToken;\n platform: 'extension' | 'mobile' | 'portfolio';\n\n // Push Un-registration\n deleteRegToken: DeleteRegToken;\n};\n\n/**\n * Updates the triggers linked to push notifications for a given registration token.\n * If the provided registration token does not exist or is not in the current set of registration tokens,\n * a new registration token is created and used for the update.\n *\n * @param params - Update Push Params\n * @returns A promise that resolves with an object containing:\n * - isTriggersLinkedToPushNotifications: boolean indicating if the triggers were successfully updated.\n * - fcmToken: the new or existing Firebase Cloud Messaging token used for the update, if applicable.\n */\nexport async function updateTriggerPushNotifications(\n params: UpdateTriggerPushNotificationsParams,\n): Promise<{\n isTriggersLinkedToPushNotifications: boolean;\n fcmToken?: string | null;\n}> {\n const {\n bearerToken,\n regToken,\n triggers,\n createRegToken,\n platform,\n deleteRegToken,\n env,\n } = params;\n\n const notificationLinks = await getPushNotificationLinks(bearerToken);\n if (!notificationLinks) {\n return { isTriggersLinkedToPushNotifications: false };\n }\n // Create new registration token if doesn't exist\n const hasRegToken = Boolean(\n regToken &&\n notificationLinks.registration_tokens.some((r) => r.token === regToken),\n );\n\n let newRegToken: string | null = null;\n if (!hasRegToken) {\n await deleteRegToken(env);\n newRegToken = await createRegToken(env);\n if (!newRegToken) {\n throw new Error('Failed to create a new registration token');\n }\n notificationLinks.registration_tokens.push({\n token: newRegToken,\n platform,\n });\n }\n\n const isTriggersLinkedToPushNotifications = await updateLinksAPI(\n bearerToken,\n triggers,\n notificationLinks.registration_tokens,\n );\n\n return {\n isTriggersLinkedToPushNotifications,\n fcmToken: newRegToken ?? null,\n };\n}\n\ntype ListenToPushNotificationsParams = {\n env: PushNotificationEnv;\n listenToPushReceived: (\n notification: Types.INotification,\n ) => void | Promise<void>;\n listenToPushClicked: (\n event: NotificationEvent,\n notification?: Types.INotification,\n ) => void;\n};\n\n/**\n * Listens to push notifications and invokes the provided callback function with the received notification data.\n *\n * @param params - listen params\n * @returns A promise that resolves to an unsubscribe function to stop listening to push notifications.\n */\nexport async function listenToPushNotifications(\n params: ListenToPushNotificationsParams,\n): Promise<() => void> {\n const { env, listenToPushReceived, listenToPushClicked } = params;\n\n /*\n Push notifications require 2 listeners that need tracking (when creating and for tearing down):\n 1. handling receiving a push notification (and the content we want to display)\n 2. handling when a user clicks on a push notification\n */\n const unsubscribePushNotifications = await listenToPushNotificationsReceived(\n env,\n listenToPushReceived,\n );\n const unsubscribeNotificationClicks =\n listenToPushNotificationsClicked(listenToPushClicked);\n\n const unsubscribe = () => {\n unsubscribePushNotifications?.();\n unsubscribeNotificationClicks();\n };\n\n return unsubscribe;\n}\n"]}
|
package/package.json
CHANGED