@adobe/alloy 2.29.0 → 2.30.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/libEs5/components/PushNotifications/helpers/constants.js +19 -0
  2. package/libEs5/components/PushNotifications/helpers/readFromIndexedDb.js +41 -0
  3. package/libEs5/components/PushNotifications/helpers/saveToIndexedDb.js +50 -0
  4. package/libEs5/components/PushNotifications/helpers/serviceWorkerNotificationClickListener.js +85 -0
  5. package/libEs5/components/PushNotifications/helpers/serviceWorkerPushListener.js +70 -0
  6. package/libEs5/components/PushNotifications/index.js +43 -10
  7. package/libEs5/components/PushNotifications/request/createSendPushSubscriptionPayload.js +3 -3
  8. package/libEs5/components/PushNotifications/request/makeSendPushSubscriptionRequest.js +8 -3
  9. package/libEs5/components/PushNotifications/request/makeSendServiceWorkerTrackingData.js +146 -0
  10. package/libEs5/components/PushNotifications/serviceWorker.js +91 -0
  11. package/libEs5/components/PushNotifications/types.js +81 -0
  12. package/libEs5/constants/libraryVersion.js +1 -1
  13. package/libEs5/utils/index.js +19 -0
  14. package/libEs5/utils/indexedDb.js +73 -0
  15. package/libEs6/components/PushNotifications/helpers/constants.js +16 -0
  16. package/libEs6/components/PushNotifications/helpers/readFromIndexedDb.js +40 -0
  17. package/libEs6/components/PushNotifications/helpers/saveToIndexedDb.js +48 -0
  18. package/libEs6/components/PushNotifications/helpers/serviceWorkerNotificationClickListener.js +82 -0
  19. package/libEs6/components/PushNotifications/helpers/serviceWorkerPushListener.js +69 -0
  20. package/libEs6/components/PushNotifications/index.js +43 -10
  21. package/libEs6/components/PushNotifications/request/createSendPushSubscriptionPayload.js +3 -3
  22. package/libEs6/components/PushNotifications/request/makeSendPushSubscriptionRequest.js +8 -3
  23. package/libEs6/components/PushNotifications/request/makeSendServiceWorkerTrackingData.js +146 -0
  24. package/libEs6/components/PushNotifications/serviceWorker.js +90 -0
  25. package/libEs6/components/PushNotifications/types.js +81 -0
  26. package/libEs6/constants/libraryVersion.js +1 -1
  27. package/libEs6/utils/index.js +1 -0
  28. package/libEs6/utils/indexedDb.js +67 -0
  29. package/package.json +29 -36
  30. package/scripts/alloyBuilder.js +130 -4
  31. package/types/components/PushNotifications/helpers/constants.d.ts +5 -0
  32. package/types/components/PushNotifications/helpers/constants.d.ts.map +1 -0
  33. package/types/components/PushNotifications/helpers/readFromIndexedDb.d.ts +4 -0
  34. package/types/components/PushNotifications/helpers/readFromIndexedDb.d.ts.map +1 -0
  35. package/types/components/PushNotifications/helpers/saveToIndexedDb.d.ts +9 -0
  36. package/types/components/PushNotifications/helpers/saveToIndexedDb.d.ts.map +1 -0
  37. package/types/components/PushNotifications/helpers/serviceWorkerNotificationClickListener.d.ts +9 -0
  38. package/types/components/PushNotifications/helpers/serviceWorkerNotificationClickListener.d.ts.map +1 -0
  39. package/types/components/PushNotifications/helpers/serviceWorkerPushListener.d.ts +8 -0
  40. package/types/components/PushNotifications/helpers/serviceWorkerPushListener.d.ts.map +1 -0
  41. package/types/components/PushNotifications/index.d.ts +11 -3
  42. package/types/components/PushNotifications/index.d.ts.map +1 -1
  43. package/types/components/PushNotifications/request/createSendPushSubscriptionPayload.d.ts +2 -2
  44. package/types/components/PushNotifications/request/createSendPushSubscriptionPayload.d.ts.map +1 -1
  45. package/types/components/PushNotifications/request/makeSendPushSubscriptionRequest.d.ts +2 -1
  46. package/types/components/PushNotifications/request/makeSendPushSubscriptionRequest.d.ts.map +1 -1
  47. package/types/components/PushNotifications/request/makeSendServiceWorkerTrackingData.d.ts +11 -0
  48. package/types/components/PushNotifications/request/makeSendServiceWorkerTrackingData.d.ts.map +1 -0
  49. package/types/components/PushNotifications/serviceWorker.d.ts +2 -0
  50. package/types/components/PushNotifications/serviceWorker.d.ts.map +1 -0
  51. package/types/components/PushNotifications/types.d.ts +167 -0
  52. package/types/components/PushNotifications/types.d.ts.map +1 -1
  53. package/types/utils/index.d.ts +1 -0
  54. package/types/utils/indexedDb.d.ts +4 -0
  55. package/types/utils/indexedDb.d.ts.map +1 -0
@@ -11,4 +11,85 @@ exports.Types = void 0;
11
11
  * @property {string|null} keys.auth - The authentication secret as an ArrayBuffer, or null if not available
12
12
  */
13
13
 
14
+ /**
15
+ * @typedef {Object} CustomerJourneyManagement
16
+ * @property {Object} messageExecution
17
+ * @property {string} messageExecution.messageExecutionID
18
+ * @property {string} messageExecution.messageID
19
+ * @property {string} messageExecution.messageType
20
+ * @property {string} messageExecution.campaignID
21
+ * @property {string} messageExecution.campaignVersionID
22
+ * @property {string} messageExecution.batchInstanceID
23
+ * @property {Object} [pushChannelContext]
24
+ * @property {"web"} [pushChannelContext.platform]
25
+ * @property {Object} [messageProfile]
26
+ * @property {Object} [messageProfile.channel]
27
+ * @property {string} [messageProfile.channel._id]
28
+ */
29
+
30
+ /**
31
+ * @typedef {Object} Decisioning
32
+ * @property {Object[]} propositions
33
+ * @property {Object} propositions[].scopeDetails
34
+ * @property {string} propositions[].scopeDetails.correlationID
35
+ */
36
+
37
+ /**
38
+ * @typedef {Object} XdmTrackingContext
39
+ * @property {Object} _experience
40
+ * @property {CustomerJourneyManagement} _experience.customerJourneyManagement
41
+ * @property {Decisioning} _experience.decisioning
42
+ */
43
+
44
+ /**
45
+ * @typedef {Object} PushNotificationData
46
+ * @property {Object} web
47
+ * @property {string} web.title
48
+ * @property {string} web.body
49
+ * @property {string|null} web.media
50
+ * @property {Object} web.interaction
51
+ * @property {string} web.interaction.type
52
+ * @property {string|null} web.interaction.uri
53
+ * @property {Object} web.actions
54
+ * @property {Object[]} web.actions.buttons
55
+ * @property {string} web.actions.buttons[].label
56
+ * @property {string} web.actions.buttons[].type
57
+ * @property {string} web.actions.buttons[].uri
58
+ * @property {string} web.priority
59
+ * @property {Object} web._xdm
60
+ * @property {XdmTrackingContext} web._xdm.mixins
61
+ */
62
+
63
+ /**
64
+ * @typedef {Object} TrackingDataPayload
65
+ * @property {Object[]} events
66
+ * @property {Object} events[].xdm
67
+ * @property {Object} events[].xdm.identityMap
68
+ * @property {Object[]} events[].xdm.identityMap.ECID
69
+ * @property {string} events[].xdm.identityMap.ECID[].id
70
+ * @property {string} events[].xdm.timestamp
71
+ * @property {Object} events[].xdm.pushNotificationTracking
72
+ * @property {string} events[].xdm.pushNotificationTracking.pushProviderMessageID
73
+ * @property {string} events[].xdm.pushNotificationTracking.pushProvider
74
+ * @property {Object} [events[].xdm.pushNotificationTracking.customAction]
75
+ * @property {string} [events[].xdm.pushNotificationTracking.customAction.actionID]
76
+ * @property {Object} events[].xdm.application
77
+ * @property {Object} events[].xdm.application.launches
78
+ * @property {number} events[].xdm.application.launches.value
79
+ * @property {string} events[].xdm.eventType
80
+ * @property {Object} events[].xdm._experience
81
+ * @property {CustomerJourneyManagement} events[].xdm._experience.customerJourneyManagement
82
+ * @property {Decisioning} events[].xdm._experience.decisioning
83
+ * @property {Object} events[].meta
84
+ * @property {Object} events[].meta.collect
85
+ * @property {string} events[].meta.collect.datasetId
86
+ */
87
+
88
+ /**
89
+ * @typedef {Object} ServiceWorkerLogger
90
+ * @property {string} namespace
91
+ * @property {(...args: any[]) => void} info
92
+ * @property {(...args: any[]) => void} error
93
+ */
94
+
14
95
  const Types = exports.Types = {};
@@ -14,4 +14,4 @@ governing permissions and limitations under the License.
14
14
  */
15
15
  // The __VERSION__ keyword will be replace at alloy build time with the package.json version.
16
16
  // see babel-plugin-version
17
- var _default = exports.default = "2.29.0";
17
+ var _default = exports.default = "2.30.0-beta.1";
@@ -96,6 +96,12 @@ Object.defineProperty(exports, "getApexDomain", {
96
96
  return _getApexDomain.default;
97
97
  }
98
98
  });
99
+ Object.defineProperty(exports, "getFromIndexedDbStore", {
100
+ enumerable: true,
101
+ get: function () {
102
+ return _indexedDb.getFromIndexedDbStore;
103
+ }
104
+ });
99
105
  Object.defineProperty(exports, "getLastArrayItems", {
100
106
  enumerable: true,
101
107
  get: function () {
@@ -222,6 +228,12 @@ Object.defineProperty(exports, "noop", {
222
228
  return _noop.default;
223
229
  }
224
230
  });
231
+ Object.defineProperty(exports, "openIndexedDb", {
232
+ enumerable: true,
233
+ get: function () {
234
+ return _indexedDb.openIndexedDb;
235
+ }
236
+ });
225
237
  Object.defineProperty(exports, "parseUrl", {
226
238
  enumerable: true,
227
239
  get: function () {
@@ -234,6 +246,12 @@ Object.defineProperty(exports, "prepareConfigOverridesForEdge", {
234
246
  return _prepareConfigOverridesForEdge.default;
235
247
  }
236
248
  });
249
+ Object.defineProperty(exports, "putToIndexedDbStore", {
250
+ enumerable: true,
251
+ get: function () {
252
+ return _indexedDb.putToIndexedDbStore;
253
+ }
254
+ });
237
255
  Object.defineProperty(exports, "queryString", {
238
256
  enumerable: true,
239
257
  get: function () {
@@ -333,6 +351,7 @@ var _getNamespacedCookieName = require("./getNamespacedCookieName.js");
333
351
  var _groupBy = require("./groupBy.js");
334
352
  var _injectAreThirdPartyCookiesSupportedByDefault = require("./injectAreThirdPartyCookiesSupportedByDefault.js");
335
353
  var _injectDoesIdentityCookieExist = require("./injectDoesIdentityCookieExist.js");
354
+ var _indexedDb = require("./indexedDb.js");
336
355
  var _injectGetBrowser = require("./injectGetBrowser.js");
337
356
  var _injectStorage = require("./injectStorage.js");
338
357
  var _intersection = require("./intersection.js");
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+
3
+ exports.putToIndexedDbStore = exports.openIndexedDb = exports.getFromIndexedDbStore = void 0;
4
+ /*
5
+ Copyright 2025 Adobe. All rights reserved.
6
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License. You may obtain a copy
8
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software distributed under
11
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
12
+ OF ANY KIND, either express or implied. See the License for the specific language
13
+ governing permissions and limitations under the License.
14
+ */
15
+
16
+ /**
17
+ * @param {string} dbName
18
+ * @param {number} dbVersion
19
+ * @param {Function} [upgradeCallback] - Optional callback function to handle database upgrades.
20
+ * Called with the database instance when the database is being upgraded.
21
+ * @returns {Promise<IDBDatabase>}
22
+ */
23
+ const openIndexedDb = (dbName, dbVersion, upgradeCallback) => {
24
+ return new Promise((resolve, reject) => {
25
+ const request = indexedDB.open(dbName, dbVersion);
26
+ request.onerror = () => reject(request.error);
27
+ request.onsuccess = () => resolve(request.result);
28
+ request.onupgradeneeded = event => {
29
+ const db = /** @type {IDBOpenDBRequest} */event.target.result;
30
+ if (upgradeCallback) {
31
+ upgradeCallback(db);
32
+ }
33
+ };
34
+ });
35
+ };
36
+
37
+ /**
38
+ * @param {IDBDatabase} db
39
+ * @param {string} storeName
40
+ * @param {string|number|Date|ArrayBuffer|Array} key
41
+ *
42
+ * @returns {Promise<any>}
43
+ */
44
+ exports.openIndexedDb = openIndexedDb;
45
+ const getFromIndexedDbStore = (db, storeName, key) => {
46
+ return new Promise((resolve, reject) => {
47
+ const transaction = db.transaction([storeName], "readonly");
48
+ const store = transaction.objectStore(storeName);
49
+ const request = store.get(key);
50
+ request.onerror = () => reject(request.error);
51
+ request.onsuccess = () => resolve(request.result);
52
+ });
53
+ };
54
+
55
+ /**
56
+ *
57
+ * @param {IDBDatabase} db
58
+ * @param {string} storeName
59
+ * @param {any} data
60
+ *
61
+ * @returns {Promise<any>}
62
+ */
63
+ exports.getFromIndexedDbStore = getFromIndexedDbStore;
64
+ const putToIndexedDbStore = (db, storeName, data) => {
65
+ return new Promise((resolve, reject) => {
66
+ const transaction = db.transaction([storeName], "readwrite");
67
+ const store = transaction.objectStore(storeName);
68
+ const request = store.put(data);
69
+ request.onerror = () => reject(request.error);
70
+ request.onsuccess = () => resolve(request.result);
71
+ });
72
+ };
73
+ exports.putToIndexedDbStore = putToIndexedDbStore;
@@ -0,0 +1,16 @@
1
+ /*
2
+ Copyright 2025 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under
8
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ OF ANY KIND, either express or implied. See the License for the specific language
10
+ governing permissions and limitations under the License.
11
+ */
12
+
13
+ export const DB_NAME = "alloyPushNotifications";
14
+ export const DB_VERSION = 1;
15
+ export const STORE_NAME = "config";
16
+ export const INDEX_KEY = "alloyConfig";
@@ -0,0 +1,40 @@
1
+ /*
2
+ Copyright 2025 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under
8
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ OF ANY KIND, either express or implied. See the License for the specific language
10
+ governing permissions and limitations under the License.
11
+ */
12
+
13
+ /** @import { ServiceWorkerLogger } from '../types.js' */
14
+
15
+ import { getFromIndexedDbStore, openIndexedDb } from "../../../utils/indexedDb.js";
16
+ import { DB_NAME, DB_VERSION, STORE_NAME, INDEX_KEY } from "./constants.js";
17
+
18
+ /**
19
+ * @param {ServiceWorkerLogger} logger
20
+ * @returns {Promise<Object|undefined>}
21
+ * @throws {Error}
22
+ */
23
+ export default async logger => {
24
+ try {
25
+ const db = await openIndexedDb(DB_NAME, DB_VERSION, (/** @type {IDBDatabase} */db) => {
26
+ if (!db.objectStoreNames.contains(STORE_NAME)) {
27
+ db.createObjectStore(STORE_NAME, {
28
+ keyPath: "id"
29
+ });
30
+ }
31
+ });
32
+ const existingConfigData = await getFromIndexedDbStore(db, STORE_NAME, INDEX_KEY);
33
+ db.close();
34
+ return existingConfigData;
35
+ } catch (error) {
36
+ logger.error("Failed to read data from IndexedDB", {
37
+ error
38
+ });
39
+ }
40
+ };
@@ -0,0 +1,48 @@
1
+ /*
2
+ Copyright 2025 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under
8
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ OF ANY KIND, either express or implied. See the License for the specific language
10
+ governing permissions and limitations under the License.
11
+ */
12
+
13
+ /** @import { Logger } from '../../../core/types.js' */
14
+
15
+ import { openIndexedDb, getFromIndexedDbStore, putToIndexedDbStore } from "../../../utils/index.js";
16
+ import { DB_NAME, DB_VERSION, STORE_NAME, INDEX_KEY } from "./constants.js";
17
+
18
+ /**
19
+ * @param {Object} data
20
+ * @param {Logger} logger
21
+ *
22
+ * @returns {Promise<void>}
23
+ */
24
+ export default async function saveToIndexedDB(data, logger) {
25
+ try {
26
+ const db = await openIndexedDb(DB_NAME, DB_VERSION, (/** @type {IDBDatabase} */db) => {
27
+ if (!db.objectStoreNames.contains(STORE_NAME)) {
28
+ db.createObjectStore(STORE_NAME, {
29
+ keyPath: "id"
30
+ });
31
+ }
32
+ });
33
+ const existingConfigData = await getFromIndexedDbStore(db, STORE_NAME, INDEX_KEY);
34
+ const updatedConfigData = {
35
+ ...(existingConfigData || {}),
36
+ ...data,
37
+ id: INDEX_KEY,
38
+ timestamp: Date.now()
39
+ };
40
+ await putToIndexedDbStore(db, STORE_NAME, updatedConfigData);
41
+ db.close();
42
+ logger.info("Successfully saved web SDK config to IndexedDB", updatedConfigData);
43
+ } catch (error) {
44
+ logger.error("Failed to save config to IndexedDB", {
45
+ error
46
+ });
47
+ }
48
+ }
@@ -0,0 +1,82 @@
1
+ /*
2
+ Copyright 2025 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under
8
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ OF ANY KIND, either express or implied. See the License for the specific language
10
+ governing permissions and limitations under the License.
11
+ */
12
+
13
+ // @ts-check
14
+ /// <reference lib="webworker" />
15
+
16
+ /** @import { ServiceWorkerLogger } from '../types.js' */
17
+
18
+ import makeSendServiceWorkerTrackingData from "../request/makeSendServiceWorkerTrackingData.js";
19
+
20
+ /**
21
+ * @param {string} type
22
+ * @returns {boolean}
23
+ */
24
+ const canHandleUrl = type => ["DEEPLINK", "WEBURL"].includes(type);
25
+
26
+ /**
27
+ * @function
28
+ *
29
+ * @param {Object} options
30
+ * @param {ServiceWorkerGlobalScope} options.sw
31
+ * @param {NotificationEvent} options.event
32
+ * @param {(url: string, options: object) => Promise<Response>} options.fetch
33
+ * @param {ServiceWorkerLogger} options.logger
34
+ */
35
+ export default ({
36
+ event,
37
+ sw,
38
+ logger,
39
+ fetch
40
+ }) => {
41
+ event.notification.close();
42
+ const data = event.notification.data;
43
+ let targetUrl = null;
44
+ let actionLabel = null;
45
+ if (event.action) {
46
+ const actionIndex = parseInt(event.action.replace("action_", ""), 10);
47
+ if (data?.actions?.buttons[actionIndex]) {
48
+ const button = data.actions.buttons[actionIndex];
49
+ actionLabel = button.label;
50
+ if (canHandleUrl(button.type) && button.uri) {
51
+ targetUrl = button.uri;
52
+ }
53
+ }
54
+ } else if (canHandleUrl(data?.interaction?.type) && data?.interaction?.uri) {
55
+ targetUrl = data.interaction.uri;
56
+ }
57
+ makeSendServiceWorkerTrackingData({
58
+ // eslint-disable-next-line no-underscore-dangle
59
+ xdm: data._xdm.mixins,
60
+ actionLabel,
61
+ applicationLaunches: 1
62
+ }, {
63
+ logger,
64
+ fetch
65
+ }).catch(error => {
66
+ logger.error("Failed to send tracking call:", error);
67
+ });
68
+ if (targetUrl) {
69
+ event.waitUntil(sw.clients.matchAll({
70
+ type: "window"
71
+ }).then(clientList => {
72
+ for (const client of clientList) {
73
+ if (client.url === targetUrl && "focus" in client) {
74
+ return client.focus();
75
+ }
76
+ }
77
+ if (sw.clients.openWindow) {
78
+ return sw.clients.openWindow(targetUrl);
79
+ }
80
+ }));
81
+ }
82
+ };
@@ -0,0 +1,69 @@
1
+ /*
2
+ Copyright 2025 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under
8
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ OF ANY KIND, either express or implied. See the License for the specific language
10
+ governing permissions and limitations under the License.
11
+ */
12
+
13
+ // @ts-check
14
+ /// <reference lib="webworker" />
15
+
16
+ /** @import { PushNotificationData } from '../types.js' */
17
+ /** @import { ServiceWorkerLogger } from '../types.js' */
18
+
19
+ /**
20
+ * @async
21
+ * @function
22
+ *
23
+ * @param {Object} options
24
+ * @param {ServiceWorkerGlobalScope} options.sw
25
+ * @param {PushEvent} options.event
26
+ * @param {ServiceWorkerLogger} options.logger
27
+ * @returns {Promise<void>}
28
+ */
29
+ export default async ({
30
+ sw,
31
+ event,
32
+ logger
33
+ }) => {
34
+ if (!event.data) {
35
+ return;
36
+ }
37
+
38
+ /** @type {PushNotificationData} */
39
+ let notificationData;
40
+ try {
41
+ notificationData = event.data.json();
42
+ } catch (error) {
43
+ logger.error("Error decoding notification JSON data:", error);
44
+ return;
45
+ }
46
+ const webData = notificationData.web;
47
+ if (!webData?.title) {
48
+ return;
49
+ }
50
+ const notificationOptions = {
51
+ body: webData.body,
52
+ icon: webData.media,
53
+ image: webData.media,
54
+ data: webData,
55
+ actions: []
56
+ };
57
+ Object.keys(notificationOptions).forEach(k => {
58
+ if (notificationOptions[k] == null) {
59
+ delete notificationOptions[k];
60
+ }
61
+ });
62
+ if (webData.actions && webData.actions.buttons) {
63
+ notificationOptions.actions = webData.actions.buttons.map((button, index) => ({
64
+ action: `action_${index}`,
65
+ title: button.label
66
+ }));
67
+ }
68
+ return sw.registration.showNotification(webData.title, notificationOptions);
69
+ };
@@ -19,27 +19,33 @@ governing permissions and limitations under the License.
19
19
  import { objectOf, string } from "../../utils/validation/index.js";
20
20
  import { sanitizeOrgIdForCookieName } from "../../utils/index.js";
21
21
  import makeSendPushSubscriptionRequest from "./request/makeSendPushSubscriptionRequest.js";
22
+ import saveToIndexedDb from "./helpers/saveToIndexedDb.js";
22
23
  const isComponentConfigured = ({
23
24
  orgId,
24
25
  pushNotifications: {
25
- vapidPublicKey
26
+ vapidPublicKey,
27
+ appId,
28
+ trackingDatasetId
26
29
  } = {
27
- vapidPublicKey: undefined
30
+ vapidPublicKey: undefined,
31
+ appId: undefined,
32
+ trackingDatasetId: undefined
28
33
  }
29
- }) => orgId && vapidPublicKey;
34
+ }) => orgId && vapidPublicKey && appId && trackingDatasetId;
30
35
 
31
36
  /**
32
37
  * @function
33
38
  *
34
39
  * @param {Object} options
35
- * @param {{ orgId: string, pushNotifications: { vapidPublicKey: string }}} options.config
40
+ * @param {{ orgId: string, datastreamId: string, edgeDomain: string, edgeBasePath: string, pushNotifications: { vapidPublicKey: string, appId: string, trackingDatasetId: string }}} options.config
36
41
  * @param {StorageCreator} options.createNamespacedStorage
37
42
  * @param {EventManager} options.eventManager
38
43
  * @param {Logger} options.logger
39
44
  * @param {ConsentManager} options.consent
40
45
  * @param {IdentityManager} options.identity
46
+ * @param {function(): string} options.getBrowser
41
47
  * @param {EdgeRequestExecutor} options.sendEdgeNetworkRequest
42
- * @returns {{ commands: { sendPushSubscription: object } }}
48
+ * @returns {{ lifecycle: object, commands: { sendPushSubscription: object } }}
43
49
  */
44
50
  const createPushNotifications = ({
45
51
  createNamespacedStorage,
@@ -48,27 +54,52 @@ const createPushNotifications = ({
48
54
  logger,
49
55
  consent,
50
56
  identity,
57
+ getBrowser,
51
58
  sendEdgeNetworkRequest
52
59
  }) => {
53
60
  return {
61
+ lifecycle: {
62
+ async onComponentsRegistered() {
63
+ if (isComponentConfigured(config)) {
64
+ const {
65
+ datastreamId,
66
+ edgeDomain,
67
+ edgeBasePath,
68
+ pushNotifications: {
69
+ trackingDatasetId
70
+ }
71
+ } = config;
72
+ await saveToIndexedDb({
73
+ datastreamId,
74
+ edgeDomain,
75
+ edgeBasePath,
76
+ datasetId: trackingDatasetId,
77
+ browser: getBrowser()
78
+ }, logger);
79
+ }
80
+ }
81
+ },
54
82
  commands: {
55
83
  sendPushSubscription: {
56
84
  run: async () => {
57
85
  if (!isComponentConfigured(config)) {
58
- throw new Error("Push notifications module is not configured. No VAPID public key was provided.");
86
+ throw new Error("Push notifications module is not configured.");
59
87
  }
60
88
  const {
61
89
  orgId,
62
90
  pushNotifications: {
63
- vapidPublicKey
91
+ vapidPublicKey,
92
+ appId
64
93
  } = {
65
- vapidPublicKey: undefined
94
+ vapidPublicKey: undefined,
95
+ appId: undefined
66
96
  }
67
97
  } = config || {};
68
98
  const storage = createNamespacedStorage(`${sanitizeOrgIdForCookieName(orgId)}.pushNotifications.`);
69
99
  return makeSendPushSubscriptionRequest({
70
100
  config: {
71
- vapidPublicKey
101
+ vapidPublicKey,
102
+ appId
72
103
  },
73
104
  storage: storage.persistent,
74
105
  logger,
@@ -87,7 +118,9 @@ const createPushNotifications = ({
87
118
  createPushNotifications.namespace = "Push Notifications";
88
119
  createPushNotifications.configValidators = objectOf({
89
120
  pushNotifications: objectOf({
90
- vapidPublicKey: string().required()
121
+ vapidPublicKey: string().required(),
122
+ appId: string().required(),
123
+ trackingDatasetId: string().required()
91
124
  }).noUnknownFields()
92
125
  });
93
126
  export default createPushNotifications;
@@ -29,7 +29,7 @@ import createDataCollectionRequestPayload from "../../../utils/request/createDat
29
29
  * @param {string} options.ecid
30
30
  * @param {EventManager} options.eventManager
31
31
  * @param {string} options.serializedPushSubscriptionDetails
32
- * @param {Window} options.window
32
+ * @param {string} options.appId
33
33
  *
34
34
  * @returns {Promise<DataCollectionRequestPayload>}
35
35
  */
@@ -37,12 +37,12 @@ export default async ({
37
37
  ecid,
38
38
  eventManager,
39
39
  serializedPushSubscriptionDetails,
40
- window
40
+ appId
41
41
  }) => {
42
42
  const event = eventManager.createEvent();
43
43
  event.setUserData({
44
44
  pushNotificationDetails: [{
45
- appID: window.location.host,
45
+ appID: appId,
46
46
  token: serializedPushSubscriptionDetails,
47
47
  platform: "web",
48
48
  denylisted: false,
@@ -20,6 +20,7 @@ import { sortObjectKeysRecursively } from "../../../utils/index.js";
20
20
  import getPushSubscriptionDetails from "../helpers/getPushSubscriptionDetails.js";
21
21
  import createSendPushSubscriptionRequest from "./createSendPushSubscriptionRequest.js";
22
22
  import createSendPushSubscriptionPayload from "./createSendPushSubscriptionPayload.js";
23
+ import saveToIndexedDb from "../helpers/saveToIndexedDb.js";
23
24
  const SUBSCRIPTION_DETAILS = "subscriptionDetails";
24
25
 
25
26
  /**
@@ -32,7 +33,7 @@ const SUBSCRIPTION_DETAILS = "subscriptionDetails";
32
33
  * @function
33
34
  *
34
35
  * @param {Object} options
35
- * @param {{vapidPublicKey: string}} options.config
36
+ * @param {{vapidPublicKey: string, appId: string}} options.config
36
37
  * @param {Storage} options.storage
37
38
  * @param {Logger} options.logger
38
39
  * @param {EventManager} options.eventManager
@@ -45,7 +46,8 @@ const SUBSCRIPTION_DETAILS = "subscriptionDetails";
45
46
  */
46
47
  export default async ({
47
48
  config: {
48
- vapidPublicKey
49
+ vapidPublicKey,
50
+ appId
49
51
  },
50
52
  storage,
51
53
  logger,
@@ -72,7 +74,7 @@ export default async ({
72
74
  eventManager,
73
75
  ecid,
74
76
  serializedPushSubscriptionDetails,
75
- window
77
+ appId
76
78
  });
77
79
  const request = createSendPushSubscriptionRequest({
78
80
  payload
@@ -81,4 +83,7 @@ export default async ({
81
83
  await sendEdgeNetworkRequest({
82
84
  request
83
85
  });
86
+ await saveToIndexedDb({
87
+ ecid
88
+ }, logger);
84
89
  };