@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.
- package/libEs5/components/PushNotifications/helpers/constants.js +19 -0
- package/libEs5/components/PushNotifications/helpers/readFromIndexedDb.js +41 -0
- package/libEs5/components/PushNotifications/helpers/saveToIndexedDb.js +50 -0
- package/libEs5/components/PushNotifications/helpers/serviceWorkerNotificationClickListener.js +85 -0
- package/libEs5/components/PushNotifications/helpers/serviceWorkerPushListener.js +70 -0
- package/libEs5/components/PushNotifications/index.js +43 -10
- package/libEs5/components/PushNotifications/request/createSendPushSubscriptionPayload.js +3 -3
- package/libEs5/components/PushNotifications/request/makeSendPushSubscriptionRequest.js +8 -3
- package/libEs5/components/PushNotifications/request/makeSendServiceWorkerTrackingData.js +146 -0
- package/libEs5/components/PushNotifications/serviceWorker.js +91 -0
- package/libEs5/components/PushNotifications/types.js +81 -0
- package/libEs5/constants/libraryVersion.js +1 -1
- package/libEs5/utils/index.js +19 -0
- package/libEs5/utils/indexedDb.js +73 -0
- package/libEs6/components/PushNotifications/helpers/constants.js +16 -0
- package/libEs6/components/PushNotifications/helpers/readFromIndexedDb.js +40 -0
- package/libEs6/components/PushNotifications/helpers/saveToIndexedDb.js +48 -0
- package/libEs6/components/PushNotifications/helpers/serviceWorkerNotificationClickListener.js +82 -0
- package/libEs6/components/PushNotifications/helpers/serviceWorkerPushListener.js +69 -0
- package/libEs6/components/PushNotifications/index.js +43 -10
- package/libEs6/components/PushNotifications/request/createSendPushSubscriptionPayload.js +3 -3
- package/libEs6/components/PushNotifications/request/makeSendPushSubscriptionRequest.js +8 -3
- package/libEs6/components/PushNotifications/request/makeSendServiceWorkerTrackingData.js +146 -0
- package/libEs6/components/PushNotifications/serviceWorker.js +90 -0
- package/libEs6/components/PushNotifications/types.js +81 -0
- package/libEs6/constants/libraryVersion.js +1 -1
- package/libEs6/utils/index.js +1 -0
- package/libEs6/utils/indexedDb.js +67 -0
- package/package.json +29 -36
- package/scripts/alloyBuilder.js +130 -4
- package/types/components/PushNotifications/helpers/constants.d.ts +5 -0
- package/types/components/PushNotifications/helpers/constants.d.ts.map +1 -0
- package/types/components/PushNotifications/helpers/readFromIndexedDb.d.ts +4 -0
- package/types/components/PushNotifications/helpers/readFromIndexedDb.d.ts.map +1 -0
- package/types/components/PushNotifications/helpers/saveToIndexedDb.d.ts +9 -0
- package/types/components/PushNotifications/helpers/saveToIndexedDb.d.ts.map +1 -0
- package/types/components/PushNotifications/helpers/serviceWorkerNotificationClickListener.d.ts +9 -0
- package/types/components/PushNotifications/helpers/serviceWorkerNotificationClickListener.d.ts.map +1 -0
- package/types/components/PushNotifications/helpers/serviceWorkerPushListener.d.ts +8 -0
- package/types/components/PushNotifications/helpers/serviceWorkerPushListener.d.ts.map +1 -0
- package/types/components/PushNotifications/index.d.ts +11 -3
- package/types/components/PushNotifications/index.d.ts.map +1 -1
- package/types/components/PushNotifications/request/createSendPushSubscriptionPayload.d.ts +2 -2
- package/types/components/PushNotifications/request/createSendPushSubscriptionPayload.d.ts.map +1 -1
- package/types/components/PushNotifications/request/makeSendPushSubscriptionRequest.d.ts +2 -1
- package/types/components/PushNotifications/request/makeSendPushSubscriptionRequest.d.ts.map +1 -1
- package/types/components/PushNotifications/request/makeSendServiceWorkerTrackingData.d.ts +11 -0
- package/types/components/PushNotifications/request/makeSendServiceWorkerTrackingData.d.ts.map +1 -0
- package/types/components/PushNotifications/serviceWorker.d.ts +2 -0
- package/types/components/PushNotifications/serviceWorker.d.ts.map +1 -0
- package/types/components/PushNotifications/types.d.ts +167 -0
- package/types/components/PushNotifications/types.d.ts.map +1 -1
- package/types/utils/index.d.ts +1 -0
- package/types/utils/indexedDb.d.ts +4 -0
- 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.
|
|
17
|
+
var _default = exports.default = "2.30.0-beta.1";
|
package/libEs5/utils/index.js
CHANGED
|
@@ -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 {{
|
|
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.
|
|
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 {
|
|
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
|
-
|
|
40
|
+
appId
|
|
41
41
|
}) => {
|
|
42
42
|
const event = eventManager.createEvent();
|
|
43
43
|
event.setUserData({
|
|
44
44
|
pushNotificationDetails: [{
|
|
45
|
-
appID:
|
|
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
|
-
|
|
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
|
};
|