@adobe/alloy 2.34.2-beta.3 → 2.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/alloy.js +287 -91
- package/dist/alloy.min.js +1 -1
- package/dist/alloyServiceWorker.js +85 -14
- package/dist/alloyServiceWorker.min.js +1 -1
- package/dist/types/browser/src/components/ActivityCollector/configValidators.d.ts +2 -2
- package/dist/types/browser/src/components/Advertising/configValidators.d.ts +1 -1
- package/dist/types/browser/src/components/Context/index.d.ts +1 -1
- package/dist/types/browser/src/components/Personalization/index.d.ts +1 -1
- package/dist/types/browser/src/components/PushNotifications/helpers/readFromIndexedDb.d.ts +2 -1
- package/dist/types/browser/src/components/PushNotifications/helpers/saveToIndexedDb.d.ts +3 -2
- package/dist/types/browser/src/components/PushNotifications/helpers/serviceWorkerPushListener.d.ts +3 -1
- package/dist/types/browser/src/components/PushNotifications/index.d.ts +1 -1
- package/dist/types/browser/src/components/PushNotifications/request/makeSendPushSubscriptionRequest.d.ts +5 -1
- package/dist/types/browser/src/components/PushNotifications/request/makeSendServiceWorkerTrackingData.d.ts +4 -2
- package/dist/types/browser/src/components/PushNotifications/types.d.ts +28 -0
- package/dist/types/core/src/components/BrandConcierge/configValidators.d.ts +1 -1
- package/dist/types/core/src/components/Consent/configValidators.d.ts +1 -1
- package/dist/types/core/src/components/Consent/validateSetConsentOptions.d.ts +1 -1
- package/dist/types/core/src/components/Identity/configValidators.d.ts +1 -1
- package/dist/types/core/src/components/RulesEngine/index.d.ts +1 -1
- package/dist/types/core/src/components/StreamingMedia/configValidators.d.ts +1 -1
- package/dist/types/core/src/core/config/createCoreConfigs.d.ts +1 -1
- package/dist/types/core/src/utils/bytes.d.ts +1 -1
- package/dist/types/core/src/utils/validateConfigOverride.d.ts +1 -1
- package/dist/types/core/src/utils/validateIdentityMap.d.ts +1 -1
- package/dist/types/core/src/utils/validation/index.d.ts +23 -11
- package/dist/types/core/src/utils/validation/types.d.ts +133 -0
- package/dist/types/core/src/utils/validation/utils.d.ts +4 -3
- package/package.json +2 -2
- package/src/components/Context/injectOneTimeAnalyticsReferrer.js +1 -1
- package/src/components/PushNotifications/helpers/getPushSubscriptionDetails.js +10 -8
- package/src/components/PushNotifications/helpers/readFromIndexedDb.js +3 -2
- package/src/components/PushNotifications/helpers/saveToIndexedDb.js +2 -1
- package/src/components/PushNotifications/helpers/serviceWorkerNotificationClickListener.js +0 -1
- package/src/components/PushNotifications/helpers/serviceWorkerPushListener.js +58 -2
- package/src/components/PushNotifications/index.js +7 -6
- package/src/components/PushNotifications/request/makeSendPushSubscriptionRequest.js +2 -1
- package/src/components/PushNotifications/request/makeSendServiceWorkerTrackingData.js +14 -6
- package/src/components/PushNotifications/types.js +15 -0
- package/src/createEventListeners.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/alloy",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.35.0",
|
|
4
4
|
"description": "Adobe Experience Platform Web SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"commander": "^14.0.2",
|
|
70
70
|
"rollup": "^4.60.3",
|
|
71
71
|
"rollup-plugin-license": "^3.7.1",
|
|
72
|
-
"@adobe/alloy-core": "^1.2.2
|
|
72
|
+
"@adobe/alloy-core": "^1.2.2"
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
75
75
|
"glob": "^13.0.6",
|
|
@@ -30,7 +30,7 @@ export default (window) => {
|
|
|
30
30
|
|
|
31
31
|
// Allow customers to explicitly set the referrer (for SPA view changes)
|
|
32
32
|
// Otherwise, use document.referrer
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
const explicitReferrer = content.data?.__adobe?.analytics?.referrer;
|
|
35
35
|
const currentReferrer =
|
|
36
36
|
explicitReferrer !== undefined
|
|
@@ -46,8 +46,7 @@ const getPushSubscriptionDetails = async ({ vapidPublicKey, window }) => {
|
|
|
46
46
|
throw new Error("Push notifications are not supported in this browser.");
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
/** @type {
|
|
50
|
-
const notification = window.Notification;
|
|
49
|
+
const notification = /** @type {typeof Notification} */ (window.Notification);
|
|
51
50
|
if (notification.permission !== "granted") {
|
|
52
51
|
throw new Error(
|
|
53
52
|
"The user has not given permission to send push notifications.",
|
|
@@ -92,15 +91,18 @@ const getPushSubscriptionDetails = async ({ vapidPublicKey, window }) => {
|
|
|
92
91
|
subscriptionOptions,
|
|
93
92
|
);
|
|
94
93
|
|
|
94
|
+
const p256dhKey = subscription.getKey("p256dh");
|
|
95
|
+
const authKey = subscription.getKey("auth");
|
|
96
|
+
|
|
95
97
|
return {
|
|
96
98
|
endpoint: subscription.endpoint,
|
|
97
99
|
keys: {
|
|
98
|
-
p256dh:
|
|
99
|
-
urlSafe: true
|
|
100
|
-
|
|
101
|
-
auth:
|
|
102
|
-
urlSafe: true
|
|
103
|
-
|
|
100
|
+
p256dh: p256dhKey
|
|
101
|
+
? bytesToBase64(new Uint8Array(p256dhKey), { urlSafe: true })
|
|
102
|
+
: null,
|
|
103
|
+
auth: authKey
|
|
104
|
+
? bytesToBase64(new Uint8Array(authKey), { urlSafe: true })
|
|
105
|
+
: null,
|
|
104
106
|
},
|
|
105
107
|
};
|
|
106
108
|
} catch (e) {
|
|
@@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag
|
|
|
10
10
|
governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
/** @import { ServiceWorkerLogger } from '../types.js' */
|
|
13
|
+
/** @import { ServiceWorkerLogger, PushServiceWorkerConfig } from '../types.js' */
|
|
14
14
|
|
|
15
15
|
import {
|
|
16
16
|
getFromIndexedDbStore,
|
|
@@ -20,7 +20,7 @@ import { DB_NAME, DB_VERSION, STORE_NAME, INDEX_KEY } from "./constants.js";
|
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* @param {ServiceWorkerLogger} logger
|
|
23
|
-
* @returns {Promise<
|
|
23
|
+
* @returns {Promise<PushServiceWorkerConfig|undefined>}
|
|
24
24
|
* @throws {Error}
|
|
25
25
|
*/
|
|
26
26
|
export default async (logger) => {
|
|
@@ -46,5 +46,6 @@ export default async (logger) => {
|
|
|
46
46
|
return existingConfigData;
|
|
47
47
|
} catch (error) {
|
|
48
48
|
logger.error("Failed to read data from IndexedDB", { error });
|
|
49
|
+
throw error;
|
|
49
50
|
}
|
|
50
51
|
};
|
|
@@ -11,6 +11,7 @@ governing permissions and limitations under the License.
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
/** @import { Logger } from '@adobe/alloy-core/core/types.js' */
|
|
14
|
+
/** @import { PushServiceWorkerConfig } from '../types.js' */
|
|
14
15
|
|
|
15
16
|
import {
|
|
16
17
|
openIndexedDb,
|
|
@@ -21,7 +22,7 @@ import {
|
|
|
21
22
|
import { DB_NAME, DB_VERSION, STORE_NAME, INDEX_KEY } from "./constants.js";
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
|
-
* @param {
|
|
25
|
+
* @param {Partial<PushServiceWorkerConfig>} data
|
|
25
26
|
* @param {Logger} logger
|
|
26
27
|
*
|
|
27
28
|
* @returns {Promise<boolean>} Whether the data was successfully saved.
|
|
@@ -14,7 +14,53 @@ governing permissions and limitations under the License.
|
|
|
14
14
|
/// <reference lib="webworker" />
|
|
15
15
|
|
|
16
16
|
/** @import { PushNotificationData } from '../types.js' */
|
|
17
|
-
/** @import { ServiceWorkerLogger } from '../types.js' */
|
|
17
|
+
/** @import { ServiceWorkerLogger, PushServiceWorkerConfig } from '../types.js' */
|
|
18
|
+
|
|
19
|
+
import ecidNamespace from "@adobe/alloy-core/constants/ecidNamespace.js";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Determines whether a notification targeted at a specific identity should be
|
|
23
|
+
* shown on this browser. When the payload contains an `identity` with the ECID
|
|
24
|
+
* namespace, the notification is only shown if the ECID in the payload matches
|
|
25
|
+
* the ECID stored in IndexedDB for this browser. When there is no identity, or
|
|
26
|
+
* the namespace is not ECID, the notification is always shown.
|
|
27
|
+
*
|
|
28
|
+
* @param {Object} options
|
|
29
|
+
* @param {PushNotificationData["web"]} options.webData
|
|
30
|
+
* @param {(logger: ServiceWorkerLogger) => Promise<PushServiceWorkerConfig|undefined>} options.readFromIndexedDb
|
|
31
|
+
* @param {ServiceWorkerLogger} options.logger
|
|
32
|
+
* @returns {Promise<boolean>}
|
|
33
|
+
*/
|
|
34
|
+
const shouldShowNotification = async ({
|
|
35
|
+
webData,
|
|
36
|
+
readFromIndexedDb,
|
|
37
|
+
logger,
|
|
38
|
+
}) => {
|
|
39
|
+
const { identity } = webData;
|
|
40
|
+
|
|
41
|
+
if (!identity || identity.namespace?.toUpperCase() !== ecidNamespace) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let storedConfig;
|
|
46
|
+
try {
|
|
47
|
+
storedConfig = await readFromIndexedDb(logger);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
50
|
+
logger.error(`Unable to read the stored ECID for this browser. ${message}`);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
const storedEcid = storedConfig?.ecid;
|
|
54
|
+
|
|
55
|
+
if (identity.id !== storedEcid) {
|
|
56
|
+
logger.info(
|
|
57
|
+
"Suppressing push notification: payload ECID does not match the ECID stored for this browser.",
|
|
58
|
+
);
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return true;
|
|
63
|
+
};
|
|
18
64
|
|
|
19
65
|
/**
|
|
20
66
|
* @async
|
|
@@ -24,9 +70,10 @@ governing permissions and limitations under the License.
|
|
|
24
70
|
* @param {ServiceWorkerGlobalScope} options.sw
|
|
25
71
|
* @param {PushEvent} options.event
|
|
26
72
|
* @param {ServiceWorkerLogger} options.logger
|
|
73
|
+
* @param {(logger: ServiceWorkerLogger) => Promise<PushServiceWorkerConfig|undefined>} options.readFromIndexedDb
|
|
27
74
|
* @returns {Promise<void>}
|
|
28
75
|
*/
|
|
29
|
-
export default async ({ sw, event, logger }) => {
|
|
76
|
+
export default async ({ sw, event, logger, readFromIndexedDb }) => {
|
|
30
77
|
if (!event.data) {
|
|
31
78
|
return;
|
|
32
79
|
}
|
|
@@ -45,6 +92,15 @@ export default async ({ sw, event, logger }) => {
|
|
|
45
92
|
return;
|
|
46
93
|
}
|
|
47
94
|
|
|
95
|
+
const showNotification = await shouldShowNotification({
|
|
96
|
+
webData,
|
|
97
|
+
readFromIndexedDb,
|
|
98
|
+
logger,
|
|
99
|
+
});
|
|
100
|
+
if (!showNotification) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
48
104
|
/** @type {Record<string, unknown>} */
|
|
49
105
|
const notificationOptions = {
|
|
50
106
|
data: webData,
|
|
@@ -21,6 +21,10 @@ import { sanitizeOrgIdForCookieName } from "@adobe/alloy-core/utils";
|
|
|
21
21
|
import makeSendPushSubscriptionRequest from "./request/makeSendPushSubscriptionRequest.js";
|
|
22
22
|
import saveToIndexedDb from "./helpers/saveToIndexedDb.js";
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* @param {{ orgId?: string, pushNotifications?: { vapidPublicKey?: string, appId?: string, trackingDatasetId?: string } }} config
|
|
26
|
+
* @returns {boolean}
|
|
27
|
+
*/
|
|
24
28
|
const isComponentConfigured = ({
|
|
25
29
|
orgId,
|
|
26
30
|
pushNotifications: { vapidPublicKey, appId, trackingDatasetId } = {
|
|
@@ -28,7 +32,7 @@ const isComponentConfigured = ({
|
|
|
28
32
|
appId: undefined,
|
|
29
33
|
trackingDatasetId: undefined,
|
|
30
34
|
},
|
|
31
|
-
}) => orgId && vapidPublicKey && appId && trackingDatasetId;
|
|
35
|
+
}) => Boolean(orgId && vapidPublicKey && appId && trackingDatasetId);
|
|
32
36
|
|
|
33
37
|
/**
|
|
34
38
|
* @function
|
|
@@ -86,11 +90,8 @@ const createPushNotifications = ({
|
|
|
86
90
|
|
|
87
91
|
const {
|
|
88
92
|
orgId,
|
|
89
|
-
pushNotifications: { vapidPublicKey, appId }
|
|
90
|
-
|
|
91
|
-
appId: undefined,
|
|
92
|
-
},
|
|
93
|
-
} = config || {};
|
|
93
|
+
pushNotifications: { vapidPublicKey, appId },
|
|
94
|
+
} = config;
|
|
94
95
|
|
|
95
96
|
const storage = platformServices.storage.createNamespacedStorage(
|
|
96
97
|
`${sanitizeOrgIdForCookieName(orgId)}.pushNotifications.`,
|
|
@@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag
|
|
|
10
10
|
governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
/** @import { Storage } from '@adobe/alloy-core/
|
|
13
|
+
/** @import { Storage } from '@adobe/alloy-core/services' */
|
|
14
14
|
/** @import { EventManager, Logger } from '@adobe/alloy-core/core/types.js' */
|
|
15
15
|
/** @import { IdentityManager } from '@adobe/alloy-core/core/identity/types.js' */
|
|
16
16
|
/** @import { ConsentManager } from '@adobe/alloy-core/core/consent/types.js' */
|
|
@@ -42,6 +42,7 @@ const SUBSCRIPTION_DETAILS = "subscriptionDetails";
|
|
|
42
42
|
* @param {EdgeRequestExecutor} options.sendEdgeNetworkRequest
|
|
43
43
|
* @param {ConsentManager} options.consent
|
|
44
44
|
* @param {Window} options.window
|
|
45
|
+
* @param {typeof getPushSubscriptionDetailsDefault} [options.getPushSubscriptionDetails]
|
|
45
46
|
*
|
|
46
47
|
* @returns {Promise<void>}
|
|
47
48
|
*/
|
|
@@ -12,14 +12,16 @@ governing permissions and limitations under the License.
|
|
|
12
12
|
|
|
13
13
|
/** @import { ServiceWorkerLogger } from '../types.js' */
|
|
14
14
|
/** @import { TrackingDataPayload } from '../types.js' */
|
|
15
|
+
/** @import { PushServiceWorkerConfig } from '../types.js' */
|
|
16
|
+
/** @import { XdmTrackingContext } from '../types.js' */
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* @param {Object} dependencies
|
|
18
|
-
* @param {(logger: ServiceWorkerLogger) => Promise<
|
|
20
|
+
* @param {(logger: ServiceWorkerLogger) => Promise<PushServiceWorkerConfig>} dependencies.readFromIndexedDb
|
|
19
21
|
* @param {() => string} dependencies.uuidv4
|
|
20
22
|
* @param {ServiceWorkerLogger} dependencies.logger
|
|
21
23
|
* @param {(url: string, options: object) => Promise<Response>} dependencies.fetch
|
|
22
|
-
* @returns {(options: { xdm:
|
|
24
|
+
* @returns {(options: { xdm: XdmTrackingContext, actionLabel?: string, applicationLaunches?: number }) => Promise<boolean>}
|
|
23
25
|
*/
|
|
24
26
|
export const createMakeSendServiceWorkerTrackingData = ({
|
|
25
27
|
readFromIndexedDb,
|
|
@@ -31,7 +33,7 @@ export const createMakeSendServiceWorkerTrackingData = ({
|
|
|
31
33
|
* @async
|
|
32
34
|
* @function
|
|
33
35
|
* @param {Object} options
|
|
34
|
-
* @param {
|
|
36
|
+
* @param {XdmTrackingContext} options.xdm
|
|
35
37
|
* @param {string} [options.actionLabel]
|
|
36
38
|
* @param {number} [options.applicationLaunches=0]
|
|
37
39
|
*
|
|
@@ -50,6 +52,7 @@ export const createMakeSendServiceWorkerTrackingData = ({
|
|
|
50
52
|
};
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
/** @type {{ name: keyof PushServiceWorkerConfig, errorField: string }[]} */
|
|
53
56
|
const requiredFields = [
|
|
54
57
|
{ name: "browser", errorField: "Browser" },
|
|
55
58
|
{ name: "ecid", errorField: "ECID" },
|
|
@@ -82,19 +85,24 @@ export const createMakeSendServiceWorkerTrackingData = ({
|
|
|
82
85
|
|
|
83
86
|
const url = `https://${edgeDomain}/${edgeBasePath}/v1/interact?configId=${datastreamId}&requestId=${uuidv4()}`;
|
|
84
87
|
|
|
88
|
+
// The requiredFields loop above guarantees these are defined strings.
|
|
89
|
+
const validEcid = /** @type {string} */ (ecid);
|
|
90
|
+
const validBrowser = /** @type {string} */ (browser);
|
|
91
|
+
const validDatasetId = /** @type {string} */ (datasetId);
|
|
92
|
+
|
|
85
93
|
/** @type {TrackingDataPayload} */
|
|
86
94
|
const payload = {
|
|
87
95
|
events: [
|
|
88
96
|
{
|
|
89
97
|
xdm: {
|
|
90
98
|
identityMap: {
|
|
91
|
-
ECID: [{ id:
|
|
99
|
+
ECID: [{ id: validEcid }],
|
|
92
100
|
},
|
|
93
101
|
timestamp: new Date().toISOString(),
|
|
94
102
|
pushNotificationTracking: {
|
|
95
103
|
...customActionData,
|
|
96
104
|
pushProviderMessageID: uuidv4(),
|
|
97
|
-
pushProvider:
|
|
105
|
+
pushProvider: validBrowser.toLowerCase(),
|
|
98
106
|
},
|
|
99
107
|
application: {
|
|
100
108
|
launches: {
|
|
@@ -121,7 +129,7 @@ export const createMakeSendServiceWorkerTrackingData = ({
|
|
|
121
129
|
},
|
|
122
130
|
meta: {
|
|
123
131
|
collect: {
|
|
124
|
-
datasetId,
|
|
132
|
+
datasetId: validDatasetId,
|
|
125
133
|
},
|
|
126
134
|
},
|
|
127
135
|
},
|
|
@@ -56,6 +56,9 @@ governing permissions and limitations under the License.
|
|
|
56
56
|
* @property {string} web.title
|
|
57
57
|
* @property {string} web.body
|
|
58
58
|
* @property {string|null} web.media
|
|
59
|
+
* @property {Object} [web.identity]
|
|
60
|
+
* @property {string} [web.identity.id]
|
|
61
|
+
* @property {string} [web.identity.namespace]
|
|
59
62
|
* @property {Object} web.interaction
|
|
60
63
|
* @property {string} web.interaction.type
|
|
61
64
|
* @property {string|null} web.interaction.uri
|
|
@@ -101,4 +104,16 @@ governing permissions and limitations under the License.
|
|
|
101
104
|
* @property {(...args: any[]) => void} error
|
|
102
105
|
*/
|
|
103
106
|
|
|
107
|
+
/**
|
|
108
|
+
* @typedef {Object} PushServiceWorkerConfig
|
|
109
|
+
* @property {string} [ecid]
|
|
110
|
+
* @property {string} [browser]
|
|
111
|
+
* @property {string} [edgeDomain]
|
|
112
|
+
* @property {string} [edgeBasePath]
|
|
113
|
+
* @property {string} [datastreamId]
|
|
114
|
+
* @property {string} [datasetId]
|
|
115
|
+
* @property {string} [id]
|
|
116
|
+
* @property {number} [timestamp]
|
|
117
|
+
*/
|
|
118
|
+
|
|
104
119
|
export const Types = {};
|
|
@@ -50,6 +50,7 @@ const createEventListeners = ({ platform, sw }) => {
|
|
|
50
50
|
event,
|
|
51
51
|
sw,
|
|
52
52
|
logger: platform.logger,
|
|
53
|
+
readFromIndexedDb,
|
|
53
54
|
});
|
|
54
55
|
},
|
|
55
56
|
/**
|
|
@@ -67,7 +68,6 @@ const createEventListeners = ({ platform, sw }) => {
|
|
|
67
68
|
|
|
68
69
|
try {
|
|
69
70
|
await makeSendServiceWorkerTrackingData({
|
|
70
|
-
/* eslint-disable-next-line no-underscore-dangle */
|
|
71
71
|
xdm: data._xdm.mixins,
|
|
72
72
|
actionLabel: "Dismiss",
|
|
73
73
|
});
|