@adobe/alloy 2.29.0-beta.0 → 2.29.0-beta.13

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 (161) hide show
  1. package/libEs5/components/ActivityCollector/utils/dom/findClickableElement.js +4 -0
  2. package/libEs5/components/Advertising/createComponent.js +1 -5
  3. package/libEs5/components/Advertising/handlers/clickThroughHandler.js +2 -1
  4. package/libEs5/components/Advertising/handlers/sendAdConversion.js +6 -8
  5. package/libEs5/components/Advertising/handlers/viewThroughHandler.js +4 -3
  6. package/libEs5/components/Consent/createConsentRequestPayload.js +14 -3
  7. package/libEs5/components/Consent/types.js +18 -0
  8. package/libEs5/components/Identity/createComponent.js +5 -4
  9. package/libEs5/components/Identity/index.js +4 -9
  10. package/libEs5/components/Personalization/dom-actions/action.js +7 -4
  11. package/libEs5/components/Personalization/dom-actions/initDomActionsModules.js +10 -10
  12. package/libEs5/components/PushNotifications/helpers/getPushSubscriptionDetails.js +112 -0
  13. package/libEs5/components/PushNotifications/index.js +96 -0
  14. package/libEs5/components/PushNotifications/request/createSendPushSubscriptionPayload.js +62 -0
  15. package/libEs5/components/PushNotifications/request/createSendPushSubscriptionRequest.js +35 -0
  16. package/libEs5/components/PushNotifications/request/makeSendPushSubscriptionRequest.js +88 -0
  17. package/libEs5/components/PushNotifications/types.js +14 -0
  18. package/libEs5/constants/libraryVersion.js +1 -1
  19. package/libEs5/core/componentCreators.js +8 -1
  20. package/libEs5/core/consent/createConsent.js +10 -0
  21. package/libEs5/core/consent/createConsentStateMachine.js +36 -0
  22. package/libEs5/core/consent/types.js +24 -0
  23. package/libEs5/core/edgeNetwork/injectSendEdgeNetworkRequest.js +20 -0
  24. package/libEs5/core/edgeNetwork/types.js +10 -0
  25. package/libEs5/core/identity/createIdentity.js +82 -0
  26. package/libEs5/core/identity/types.js +15 -0
  27. package/libEs5/core/index.js +8 -0
  28. package/libEs5/core/injectCreateResponse.js +9 -7
  29. package/libEs5/core/types.js +101 -11
  30. package/libEs5/utils/bytes.js +38 -0
  31. package/libEs5/{components/Identity → utils}/createDecodeKndctrCookie.js +12 -20
  32. package/libEs5/utils/createLoggingCookieJar.js +14 -1
  33. package/libEs5/utils/createMerger.js +5 -4
  34. package/libEs5/utils/index.js +13 -0
  35. package/libEs5/utils/injectStorage.js +19 -0
  36. package/libEs5/utils/request/createDataCollectionRequestPayload.js +16 -8
  37. package/libEs5/utils/request/createRequest.js +28 -1
  38. package/libEs5/utils/request/createRequestPayload.js +68 -4
  39. package/libEs5/utils/request/types.js +52 -0
  40. package/libEs5/utils/types.js +39 -0
  41. package/libEs6/components/ActivityCollector/utils/dom/findClickableElement.js +4 -0
  42. package/libEs6/components/Advertising/createComponent.js +1 -5
  43. package/libEs6/components/Advertising/handlers/clickThroughHandler.js +2 -1
  44. package/libEs6/components/Advertising/handlers/sendAdConversion.js +6 -8
  45. package/libEs6/components/Advertising/handlers/viewThroughHandler.js +4 -3
  46. package/libEs6/components/Consent/createConsentRequestPayload.js +16 -3
  47. package/libEs6/components/Consent/types.js +15 -0
  48. package/libEs6/components/Identity/createComponent.js +5 -4
  49. package/libEs6/components/Identity/index.js +4 -9
  50. package/libEs6/components/Personalization/dom-actions/action.js +7 -4
  51. package/libEs6/components/Personalization/dom-actions/initDomActionsModules.js +10 -10
  52. package/libEs6/components/PushNotifications/helpers/getPushSubscriptionDetails.js +110 -0
  53. package/libEs6/components/PushNotifications/index.js +93 -0
  54. package/libEs6/components/PushNotifications/request/createSendPushSubscriptionPayload.js +61 -0
  55. package/libEs6/components/PushNotifications/request/createSendPushSubscriptionRequest.js +34 -0
  56. package/libEs6/components/PushNotifications/request/makeSendPushSubscriptionRequest.js +84 -0
  57. package/libEs6/components/PushNotifications/types.js +11 -0
  58. package/libEs6/constants/libraryVersion.js +1 -1
  59. package/libEs6/core/componentCreators.js +2 -1
  60. package/libEs6/core/consent/createConsent.js +12 -0
  61. package/libEs6/core/consent/createConsentStateMachine.js +36 -0
  62. package/libEs6/core/consent/types.js +21 -0
  63. package/libEs6/core/edgeNetwork/injectSendEdgeNetworkRequest.js +20 -0
  64. package/libEs6/core/edgeNetwork/types.js +7 -0
  65. package/libEs6/core/identity/createIdentity.js +81 -0
  66. package/libEs6/core/identity/types.js +12 -0
  67. package/libEs6/core/index.js +8 -0
  68. package/libEs6/core/injectCreateResponse.js +11 -7
  69. package/libEs6/core/types.js +101 -11
  70. package/libEs6/utils/bytes.js +33 -0
  71. package/libEs6/{components/Identity → utils}/createDecodeKndctrCookie.js +11 -19
  72. package/libEs6/utils/createLoggingCookieJar.js +15 -1
  73. package/libEs6/utils/createMerger.js +5 -4
  74. package/libEs6/utils/index.js +1 -0
  75. package/libEs6/utils/injectStorage.js +20 -0
  76. package/libEs6/utils/request/createDataCollectionRequestPayload.js +19 -8
  77. package/libEs6/utils/request/createRequest.js +29 -1
  78. package/libEs6/utils/request/createRequestPayload.js +67 -4
  79. package/libEs6/utils/request/types.js +49 -0
  80. package/libEs6/utils/types.js +36 -0
  81. package/package.json +30 -30
  82. package/types/components/ActivityCollector/utils/dom/findClickableElement.d.ts.map +1 -1
  83. package/types/components/Advertising/createComponent.d.ts +1 -1
  84. package/types/components/Advertising/createComponent.d.ts.map +1 -1
  85. package/types/components/Advertising/handlers/sendAdConversion.d.ts.map +1 -1
  86. package/types/components/Advertising/handlers/viewThroughHandler.d.ts.map +1 -1
  87. package/types/components/Advertising/index.d.ts +1 -1
  88. package/types/components/Consent/createConsentRequest.d.ts +1 -11
  89. package/types/components/Consent/createConsentRequest.d.ts.map +1 -1
  90. package/types/components/Consent/createConsentRequestPayload.d.ts +2 -9
  91. package/types/components/Consent/createConsentRequestPayload.d.ts.map +1 -1
  92. package/types/components/Consent/types.d.ts +28 -0
  93. package/types/components/Consent/types.d.ts.map +1 -0
  94. package/types/components/Identity/createComponent.d.ts +2 -2
  95. package/types/components/Identity/createComponent.d.ts.map +1 -1
  96. package/types/components/Identity/getIdentity/createIdentityRequest.d.ts +1 -11
  97. package/types/components/Identity/getIdentity/createIdentityRequest.d.ts.map +1 -1
  98. package/types/components/Identity/getIdentity/createIdentityRequestPayload.d.ts +1 -9
  99. package/types/components/Identity/getIdentity/createIdentityRequestPayload.d.ts.map +1 -1
  100. package/types/components/Identity/index.d.ts +2 -1
  101. package/types/components/Identity/index.d.ts.map +1 -1
  102. package/types/components/Personalization/dom-actions/action.d.ts +1 -1
  103. package/types/components/Personalization/dom-actions/action.d.ts.map +1 -1
  104. package/types/components/PushNotifications/helpers/getPushSubscriptionDetails.d.ts +30 -0
  105. package/types/components/PushNotifications/helpers/getPushSubscriptionDetails.d.ts.map +1 -0
  106. package/types/components/PushNotifications/index.d.ts +43 -0
  107. package/types/components/PushNotifications/index.d.ts.map +1 -0
  108. package/types/components/PushNotifications/request/createSendPushSubscriptionPayload.d.ts +10 -0
  109. package/types/components/PushNotifications/request/createSendPushSubscriptionPayload.d.ts.map +1 -0
  110. package/types/components/PushNotifications/request/createSendPushSubscriptionRequest.d.ts +7 -0
  111. package/types/components/PushNotifications/request/createSendPushSubscriptionRequest.d.ts.map +1 -0
  112. package/types/components/PushNotifications/request/makeSendPushSubscriptionRequest.d.ts +20 -0
  113. package/types/components/PushNotifications/request/makeSendPushSubscriptionRequest.d.ts.map +1 -0
  114. package/types/components/PushNotifications/types.d.ts +23 -0
  115. package/types/components/PushNotifications/types.d.ts.map +1 -0
  116. package/types/components/StreamingMedia/createMediaRequest.d.ts +1 -11
  117. package/types/components/StreamingMedia/createMediaRequest.d.ts.map +1 -1
  118. package/types/core/componentCreators.d.ts +1 -0
  119. package/types/core/consent/createConsent.d.ts +4 -10
  120. package/types/core/consent/createConsent.d.ts.map +1 -1
  121. package/types/core/consent/createConsentStateMachine.d.ts +4 -12
  122. package/types/core/consent/createConsentStateMachine.d.ts.map +1 -1
  123. package/types/core/consent/types.d.ts +42 -0
  124. package/types/core/consent/types.d.ts.map +1 -0
  125. package/types/core/edgeNetwork/injectSendEdgeNetworkRequest.d.ts +15 -13
  126. package/types/core/edgeNetwork/injectSendEdgeNetworkRequest.d.ts.map +1 -1
  127. package/types/core/edgeNetwork/types.d.ts +12 -0
  128. package/types/core/edgeNetwork/types.d.ts.map +1 -0
  129. package/types/core/identity/createIdentity.d.ts +12 -0
  130. package/types/core/identity/createIdentity.d.ts.map +1 -0
  131. package/types/core/identity/types.d.ts +23 -0
  132. package/types/core/identity/types.d.ts.map +1 -0
  133. package/types/core/index.d.ts.map +1 -1
  134. package/types/core/injectCreateResponse.d.ts +3 -27
  135. package/types/core/injectCreateResponse.d.ts.map +1 -1
  136. package/types/core/types.d.ts +209 -22
  137. package/types/core/types.d.ts.map +1 -1
  138. package/types/utils/bytes.d.ts +3 -0
  139. package/types/utils/bytes.d.ts.map +1 -0
  140. package/types/utils/createDecodeKndctrCookie.d.ts.map +1 -0
  141. package/types/utils/createLoggingCookieJar.d.ts +5 -3
  142. package/types/utils/createLoggingCookieJar.d.ts.map +1 -1
  143. package/types/utils/createMerger.d.ts +1 -1
  144. package/types/utils/createMerger.d.ts.map +1 -1
  145. package/types/utils/index.d.ts +1 -0
  146. package/types/utils/injectStorage.d.ts +2 -40
  147. package/types/utils/injectStorage.d.ts.map +1 -1
  148. package/types/utils/request/createDataCollectionRequest.d.ts +1 -11
  149. package/types/utils/request/createDataCollectionRequest.d.ts.map +1 -1
  150. package/types/utils/request/createDataCollectionRequestPayload.d.ts +2 -9
  151. package/types/utils/request/createDataCollectionRequestPayload.d.ts.map +1 -1
  152. package/types/utils/request/createRequest.d.ts +13 -11
  153. package/types/utils/request/createRequest.d.ts.map +1 -1
  154. package/types/utils/request/createRequestPayload.d.ts +7 -9
  155. package/types/utils/request/createRequestPayload.d.ts.map +1 -1
  156. package/types/utils/request/types.d.ts +91 -0
  157. package/types/utils/request/types.d.ts.map +1 -0
  158. package/types/utils/types.d.ts +91 -0
  159. package/types/utils/types.d.ts.map +1 -0
  160. package/types/components/Identity/createDecodeKndctrCookie.d.ts.map +0 -1
  161. /package/types/{components/Identity → utils}/createDecodeKndctrCookie.d.ts +0 -0
@@ -0,0 +1,110 @@
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 { PushSubscription } from '../types.js' */
14
+
15
+ import { base64ToBytes, bytesToBase64 } from "../../../utils/index.js";
16
+
17
+ /**
18
+ * Gets push subscription details for the current browser.
19
+ *
20
+ * @async
21
+ * @function
22
+ *
23
+ * @param {object} options
24
+ * @param {string} options.vapidPublicKey - The VAPID public key in base64 format used for push notification authentication.
25
+ * @param {Window} options.window
26
+ *
27
+ * @returns {Promise<PushSubscription>} A promise that resolves to an object containing the push subscription details.
28
+
29
+ * @throws {Error} Throws an error if service workers are not supported in the browser.
30
+ * @throws {Error} Throws an error if user didn't approve push notifications for the domain.
31
+ * @throws {Error} Throws an error if push notifications are not supported in the browser.
32
+ * @throws {Error} Throws an error if no VAPID public key was provided.
33
+ *
34
+ * @example
35
+ * // Get subscription details with VAPID key
36
+ * const vapidKey = "BEl62iUYgUivxIkv69yViEuiBIa40HI5hmjHbKPlXO...";
37
+ * const subscription = await getPushSubscriptionDetails(vapidKey);
38
+ * console.log(subscription.endpoint); // "https://fcm.googleapis.com/fcm/send/..."
39
+ */
40
+ const getPushSubscriptionDetails = async ({
41
+ vapidPublicKey,
42
+ window
43
+ }) => {
44
+ if (!("serviceWorker" in window.navigator)) {
45
+ throw new Error("Service workers are not supported in this browser.");
46
+ }
47
+ if (!("PushManager" in window) || !("Notification" in window)) {
48
+ throw new Error("Push notifications are not supported in this browser.");
49
+ }
50
+
51
+ /** @type {object} */
52
+ const notification = window.Notification;
53
+ if (notification.permission !== "granted") {
54
+ throw new Error("The user has not given permission to send push notifications.");
55
+ }
56
+ const serviceWorkerRegistration =
57
+ // eslint-disable-next-line compat/compat
58
+ await window.navigator.serviceWorker.getRegistration();
59
+ if (!serviceWorkerRegistration) {
60
+ throw new Error("No service worker registration was found.");
61
+ }
62
+
63
+ // Even `applicationServerKey` is not required in the spec, some browsers like Chrome are requiring it.
64
+ if (!vapidPublicKey) {
65
+ throw new Error("No VAPID public key was provided.");
66
+ }
67
+ const subscriptionOptions = {
68
+ userVisibleOnly: true,
69
+ applicationServerKey: base64ToBytes(vapidPublicKey)
70
+ };
71
+
72
+ // Push subscription handling strategy:
73
+ //
74
+ // 1. We always call subscribe() to either get the current subscription or create a new one.
75
+ // - If called with the same VAPID key as an existing subscription, it returns that subscription
76
+ // - If called with a different VAPID key when a subscription exists, it throws an error
77
+ //
78
+ // 2. Error handling approach:
79
+ // - Browser error messages vary and don't clearly indicate VAPID key conflicts
80
+ // - When subscribe() fails, we assume it's likely due to a VAPID key mismatch
81
+ // - We attempt recovery by unsubscribing the existing subscription and retrying
82
+ // - If the retry also fails, we re-throw the original error
83
+ //
84
+ // This strategy ensures we can handle both new subscriptions and VAPID key changes
85
+ // while gracefully falling back to error reporting when recovery isn't possible.
86
+ try {
87
+ const subscription = await serviceWorkerRegistration.pushManager.subscribe(subscriptionOptions);
88
+ return {
89
+ endpoint: subscription.endpoint,
90
+ keys: {
91
+ p256dh: bytesToBase64(new Uint8Array(subscription.getKey("p256dh"))),
92
+ auth: bytesToBase64(new Uint8Array(subscription.getKey("auth")))
93
+ }
94
+ };
95
+ } catch (e) {
96
+ const subscription = await serviceWorkerRegistration.pushManager.getSubscription();
97
+ if (!subscription) {
98
+ throw e;
99
+ }
100
+ const unsubscribeResult = await subscription.unsubscribe();
101
+ if (!unsubscribeResult) {
102
+ throw e;
103
+ }
104
+ return getPushSubscriptionDetails({
105
+ vapidPublicKey,
106
+ window
107
+ });
108
+ }
109
+ };
110
+ export default getPushSubscriptionDetails;
@@ -0,0 +1,93 @@
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 { StorageCreator } from '../../utils/types.js' */
14
+ /** @import { EventManager, Logger } from '../../core/types.js' */
15
+ /** @import { IdentityManager } from '../../core/identity/types.js' */
16
+ /** @import { ConsentManager } from '../../core/consent/types.js' */
17
+ /** @import { EdgeRequestExecutor } from '../../core/edgeNetwork/types.js' */
18
+
19
+ import { objectOf, string } from "../../utils/validation/index.js";
20
+ import { sanitizeOrgIdForCookieName } from "../../utils/index.js";
21
+ import makeSendPushSubscriptionRequest from "./request/makeSendPushSubscriptionRequest.js";
22
+ const isComponentConfigured = ({
23
+ orgId,
24
+ pushNotifications: {
25
+ vapidPublicKey
26
+ } = {
27
+ vapidPublicKey: undefined
28
+ }
29
+ }) => orgId && vapidPublicKey;
30
+
31
+ /**
32
+ * @function
33
+ *
34
+ * @param {Object} options
35
+ * @param {{ orgId: string, pushNotifications: { vapidPublicKey: string }}} options.config
36
+ * @param {StorageCreator} options.createNamespacedStorage
37
+ * @param {EventManager} options.eventManager
38
+ * @param {Logger} options.logger
39
+ * @param {ConsentManager} options.consent
40
+ * @param {IdentityManager} options.identity
41
+ * @param {EdgeRequestExecutor} options.sendEdgeNetworkRequest
42
+ * @returns {{ commands: { sendPushSubscription: object } }}
43
+ */
44
+ const createPushNotifications = ({
45
+ createNamespacedStorage,
46
+ eventManager,
47
+ config,
48
+ logger,
49
+ consent,
50
+ identity,
51
+ sendEdgeNetworkRequest
52
+ }) => {
53
+ return {
54
+ commands: {
55
+ sendPushSubscription: {
56
+ run: async () => {
57
+ if (!isComponentConfigured(config)) {
58
+ throw new Error("Push notifications module is not configured. No VAPID public key was provided.");
59
+ }
60
+ const {
61
+ orgId,
62
+ pushNotifications: {
63
+ vapidPublicKey
64
+ } = {
65
+ vapidPublicKey: undefined
66
+ }
67
+ } = config || {};
68
+ const storage = createNamespacedStorage(`${sanitizeOrgIdForCookieName(orgId)}.pushNotifications.`);
69
+ return makeSendPushSubscriptionRequest({
70
+ config: {
71
+ vapidPublicKey
72
+ },
73
+ storage: storage.persistent,
74
+ logger,
75
+ sendEdgeNetworkRequest,
76
+ consent,
77
+ eventManager,
78
+ identity,
79
+ window
80
+ });
81
+ },
82
+ optionsValidator: objectOf({}).noUnknownFields()
83
+ }
84
+ }
85
+ };
86
+ };
87
+ createPushNotifications.namespace = "Push Notifications";
88
+ createPushNotifications.configValidators = objectOf({
89
+ pushNotifications: objectOf({
90
+ vapidPublicKey: string().required()
91
+ }).noUnknownFields()
92
+ });
93
+ export default createPushNotifications;
@@ -0,0 +1,61 @@
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 { EventManager } from "../../../core/types.js" */
14
+ /** @import { DataCollectionRequestPayload } from "../../../utils/request/types.js" */
15
+
16
+ import createDataCollectionRequestPayload from "../../../utils/request/createDataCollectionRequestPayload.js";
17
+
18
+ /**
19
+ * Creates a data collection request payload for sending push subscription details to Adobe Experience Platform.
20
+ *
21
+ * This function constructs an event containing push notification subscription information,
22
+ * including the subscription details, platform information, and identity data. The event
23
+ * is then packaged into a data collection request payload for transmission to the edge network.
24
+ *
25
+ * @async
26
+ * @function
27
+ *
28
+ * @param {Object} options
29
+ * @param {string} options.ecid
30
+ * @param {EventManager} options.eventManager
31
+ * @param {string} options.serializedPushSubscriptionDetails
32
+ * @param {Window} options.window
33
+ *
34
+ * @returns {Promise<DataCollectionRequestPayload>}
35
+ */
36
+ export default async ({
37
+ ecid,
38
+ eventManager,
39
+ serializedPushSubscriptionDetails,
40
+ window
41
+ }) => {
42
+ const event = eventManager.createEvent();
43
+ event.setUserData({
44
+ pushNotificationDetails: [{
45
+ appID: window.location.host,
46
+ token: serializedPushSubscriptionDetails,
47
+ platform: "web",
48
+ denylisted: false,
49
+ identity: {
50
+ namespace: {
51
+ code: "ECID"
52
+ },
53
+ id: ecid
54
+ }
55
+ }]
56
+ });
57
+ event.finalize();
58
+ const payload = createDataCollectionRequestPayload();
59
+ payload.addEvent(event);
60
+ return payload;
61
+ };
@@ -0,0 +1,34 @@
1
+ /*
2
+ Copyright 2023 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 { DataCollectionRequestPayload, Request } from '../../../utils/request/types.js' */
14
+
15
+ import { createRequest } from "../../../utils/request/index.js";
16
+
17
+ /**
18
+ * @function
19
+ *
20
+ * @param {{ payload: DataCollectionRequestPayload }} options
21
+ *
22
+ * @returns {Request}
23
+ */
24
+ export default ({
25
+ payload
26
+ }) => createRequest({
27
+ payload,
28
+ getAction() {
29
+ return "interact";
30
+ },
31
+ getUseSendBeacon() {
32
+ return false;
33
+ }
34
+ });
@@ -0,0 +1,84 @@
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 { Storage } from '../../../utils/types.js' */
14
+ /** @import { EventManager, Logger } from '../../../core/types.js' */
15
+ /** @import { IdentityManager } from '../../../core/identity/types.js' */
16
+ /** @import { ConsentManager } from '../../../core/consent/types.js' */
17
+ /** @import { EdgeRequestExecutor } from '../../../core/edgeNetwork/types.js' */
18
+
19
+ import { sortObjectKeysRecursively } from "../../../utils/index.js";
20
+ import getPushSubscriptionDetails from "../helpers/getPushSubscriptionDetails.js";
21
+ import createSendPushSubscriptionRequest from "./createSendPushSubscriptionRequest.js";
22
+ import createSendPushSubscriptionPayload from "./createSendPushSubscriptionPayload.js";
23
+ const SUBSCRIPTION_DETAILS = "subscriptionDetails";
24
+
25
+ /**
26
+ * Retrieves and returns push subscription details with sorted object keys.
27
+ *
28
+ * This function gets the push subscription details using the provided VAPID public key
29
+ * and returns the details with all object keys sorted recursively for consistent output.
30
+ *
31
+ * @async
32
+ * @function
33
+ *
34
+ * @param {Object} options
35
+ * @param {{vapidPublicKey: string}} options.config
36
+ * @param {Storage} options.storage
37
+ * @param {Logger} options.logger
38
+ * @param {EventManager} options.eventManager
39
+ * @param {IdentityManager} options.identity
40
+ * @param {EdgeRequestExecutor} options.sendEdgeNetworkRequest
41
+ * @param {ConsentManager} options.consent
42
+ * @param {Window} options.window
43
+ *
44
+ * @returns {Promise<void>}
45
+ */
46
+ export default async ({
47
+ config: {
48
+ vapidPublicKey
49
+ },
50
+ storage,
51
+ logger,
52
+ sendEdgeNetworkRequest,
53
+ consent,
54
+ eventManager,
55
+ identity,
56
+ window
57
+ }) => {
58
+ await identity.awaitIdentity();
59
+ const ecid = identity.getEcidFromCookie();
60
+ const pushSubscriptionDetails = await getPushSubscriptionDetails({
61
+ vapidPublicKey,
62
+ window
63
+ });
64
+ const serializedPushSubscriptionDetails = JSON.stringify(sortObjectKeysRecursively(pushSubscriptionDetails));
65
+ const cacheValue = `${ecid}${serializedPushSubscriptionDetails}`;
66
+ if (cacheValue === storage.getItem(SUBSCRIPTION_DETAILS)) {
67
+ logger.info("Subscription details have not changed. Not sending to the server.");
68
+ return;
69
+ }
70
+ storage.setItem(SUBSCRIPTION_DETAILS, cacheValue);
71
+ const payload = await createSendPushSubscriptionPayload({
72
+ eventManager,
73
+ ecid,
74
+ serializedPushSubscriptionDetails,
75
+ window
76
+ });
77
+ const request = createSendPushSubscriptionRequest({
78
+ payload
79
+ });
80
+ await consent.awaitConsent();
81
+ await sendEdgeNetworkRequest({
82
+ request
83
+ });
84
+ };
@@ -0,0 +1,11 @@
1
+ /** @import { Identity } from '../../utils/request/types.js' */
2
+
3
+ /**
4
+ * @typedef {Object} PushSubscription
5
+ * @property {string} endpoint - The push service endpoint URL
6
+ * @property {Object} keys - The subscription keys object
7
+ * @property {string|null} keys.p256dh - The P-256 ECDH public key as an ArrayBuffer, or null if not available
8
+ * @property {string|null} keys.auth - The authentication secret as an ArrayBuffer, or null if not available
9
+ */
10
+
11
+ export const Types = {};
@@ -13,4 +13,4 @@ governing permissions and limitations under the License.
13
13
  // The __VERSION__ keyword will be replace at alloy build time with the package.json version.
14
14
  // see babel-plugin-version
15
15
 
16
- export default "2.29.0-beta.0";
16
+ export default "2.29.0-beta.13";
@@ -22,4 +22,5 @@ export { default as mediaAnalyticsBridge } from "../components/MediaAnalyticsBri
22
22
  export { default as personalization } from "../components/Personalization/index.js";
23
23
  export { default as rulesEngine } from "../components/RulesEngine/index.js";
24
24
  export { default as streamingMedia } from "../components/StreamingMedia/index.js";
25
- export { default as advertising } from "../components/Advertising/index.js";
25
+ export { default as advertising } from "../components/Advertising/index.js";
26
+ export { default as pushNotifications } from "../components/PushNotifications/index.js";
@@ -10,9 +10,21 @@ 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 { ConsentManager } from './types.js' */
14
+
13
15
  import { IN, OUT, PENDING } from "../../constants/consentStatus.js";
14
16
  import { GENERAL } from "../../constants/consentPurpose.js";
15
17
  import { CONSENT_SOURCE_DEFAULT, CONSENT_SOURCE_INITIAL, CONSENT_SOURCE_NEW } from "./createConsentStateMachine.js";
18
+
19
+ /**
20
+ * @function
21
+ *
22
+ * @param {Object} options
23
+ * @param {ConsentStateMachine} options.generalConsentState
24
+ * @param {Logger} options.logger
25
+ *
26
+ * @returns {ConsentManager}
27
+ */
16
28
  export default ({
17
29
  generalConsentState,
18
30
  logger
@@ -10,18 +10,54 @@ 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 { Logger } from '../../core/types.js' */
14
+ /** @import { ConsentStateMachineUtils, ConsentStateMachine } from './types.js' */
15
+
13
16
  import { defer } from "../../utils/index.js";
14
17
  export const DECLINED_CONSENT = "The user declined consent.";
15
18
  export const DECLINED_CONSENT_ERROR_CODE = "declinedConsent";
16
19
  export const CONSENT_SOURCE_DEFAULT = "default";
17
20
  export const CONSENT_SOURCE_INITIAL = "initial";
18
21
  export const CONSENT_SOURCE_NEW = "new";
22
+
23
+ /**
24
+ * @private
25
+ * @param {string} errorMessage
26
+ * @returns {Error}
27
+ */
19
28
  const createDeclinedConsentError = errorMessage => {
20
29
  const error = new Error(errorMessage);
21
30
  error.code = DECLINED_CONSENT_ERROR_CODE;
22
31
  error.message = errorMessage;
23
32
  return error;
24
33
  };
34
+
35
+ /**
36
+ * Creates a consent state machine that manages user consent preferences and
37
+ * coordinates deferred operations that require consent.
38
+ *
39
+ * The state machine supports the following states:
40
+ * - "in": User has provided consent (with default or explicit consent)
41
+ * - "out": User has declined consent (with default or explicit decline)
42
+ * - "pending": Consent decision is awaiting user input
43
+ *
44
+ * @param {object} options
45
+ * @param {Logger} options.logger
46
+ *
47
+ * @returns {ConsentStateMachine}
48
+ *
49
+ * @example
50
+ * const consentStateMachine = createConsentStateMachine({ logger });
51
+ *
52
+ * // Set consent state
53
+ * consentStateMachine.in('new');
54
+ *
55
+ * // Wait for consent
56
+ * await consentStateMachine.awaitConsent();
57
+ *
58
+ * // Check current state
59
+ * const { state, wasSet } = consentStateMachine.current();
60
+ */
25
61
  export default ({
26
62
  logger
27
63
  }) => {
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @typedef {Object} ConsentStateMachine
3
+ * @property {function(string): void} in
4
+ * @property {function(string): void} out
5
+ * @property {function(string): void} pending
6
+ * @property {function(boolean=): Promise<void>} awaitConsent
7
+ * @property {function(): Promise<void>} withConsent
8
+ * @property {function(): {state: string, wasSet: boolean}} current
9
+ */
10
+
11
+ /**
12
+ * @typedef {Object} ConsentManager
13
+ * @property {function(Object, Object): void} initializeConsent
14
+ * @property {function(Object): void} setConsent
15
+ * @property {function(): void} suspend
16
+ * @property {function(): Promise<void>} awaitConsent
17
+ * @property {function(): Promise<void>} withConsent
18
+ * @property {function(): {state: string, wasSet: boolean}} current
19
+ */
20
+
21
+ export const Types = {};
@@ -10,6 +10,9 @@ 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 { EdgeRequestExecutor } from './types.js' */
14
+ /** @import { ResponseCreator } from '../types.js' */
15
+
13
16
  import { ID_THIRD_PARTY as ID_THIRD_PARTY_DOMAIN } from "../../constants/domain.js";
14
17
  import apiVersion from "../../constants/apiVersion.js";
15
18
  import { createCallbackAggregator, noop } from "../../utils/index.js";
@@ -19,6 +22,23 @@ import handleRequestFailure from "./handleRequestFailure.js";
19
22
  const isDemdexBlockedError = (error, request) => {
20
23
  return request.getUseIdThirdPartyDomain() && isNetworkError(error);
21
24
  };
25
+
26
+ /**
27
+ * @function
28
+ *
29
+ * @param {object} options
30
+ * @param {{edgeDomain: string, edgeBasePath: string, datastreamId: string}} options.config
31
+ * @param {object} options.lifecycle
32
+ * @param {object} options.cookieTransfer
33
+ * @param {function(object): Promise<Object>} options.sendNetworkRequest
34
+ * @param {ResponseCreator} options.createResponse
35
+ * @param {function(object): void} options.processWarningsAndErrors
36
+ * @param {function(): string|undefined} options.getLocationHint
37
+ * @param {function(): string} options.getAssuranceValidationTokenParams
38
+
39
+ *
40
+ * @returns {EdgeRequestExecutor} A function that sends edge network requests with lifecycle management
41
+ */
22
42
  export default ({
23
43
  config,
24
44
  lifecycle,
@@ -0,0 +1,7 @@
1
+ /** @import { Request } from '../../utils/request/types.js' */
2
+
3
+ /**
4
+ * @typedef {function({request: Request, runOnResponseCallbacks?: function(): void, runOnRequestFailureCallbacks?: function(): void}): Promise<Object>} EdgeRequestExecutor
5
+ */
6
+
7
+ export const Types = {};
@@ -0,0 +1,81 @@
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 { IdentityManager } from './types.js' */
14
+ /** @import { Logger } from '../types.js' */
15
+ /** @import { CookieJar } from '../../utils/types.js' */
16
+
17
+ import createDecodeKndctrCookie from "../../utils/createDecodeKndctrCookie.js";
18
+
19
+ /**
20
+ * Creates an identity management service for handling ECID (Experience Cloud ID) resolution and tracking.
21
+ *
22
+ * This factory function creates an identity manager service that manages the state of identity resolution,
23
+ * provides methods to check for existing identity cookies, and handles the asynchronous nature
24
+ * of identity acquisition in Adobe Experience Platform Web SDK.
25
+ *
26
+ * @function
27
+ *
28
+ * @param {Object} options
29
+ * @param {Logger} options.logger
30
+ * @param {CookieJar} options.loggingCookieJar
31
+ * @param {{orgId: string}} options.config
32
+ *
33
+ * @returns {IdentityManager}
34
+ *
35
+ * @example
36
+ * // Create an identity service
37
+ * const identityManager = createIdentity({
38
+ * logger: myLogger,
39
+ * loggingCookieJar: myCookieJar,
40
+ * config: { orgId: 'myOrgId@AdobeOrg' }
41
+ * });
42
+ *
43
+ * // Initialize and check for existing identity
44
+ * identityManager.initialize();
45
+ *
46
+ * // Wait for identity to be available
47
+ * await identityManager.awaitIdentity();
48
+ *
49
+ * // Get ECID from cookie
50
+ * const ecid = identityManager.getEcidFromCookie();
51
+ */
52
+ export default ({
53
+ logger,
54
+ loggingCookieJar,
55
+ config
56
+ }) => {
57
+ let awaitIdentityResolve = null;
58
+ const awaitIdentityPromise = new Promise(resolve => {
59
+ awaitIdentityResolve = resolve;
60
+ });
61
+ const decodeKndctrCookie = createDecodeKndctrCookie({
62
+ orgId: config.orgId,
63
+ cookieJar: loggingCookieJar,
64
+ logger
65
+ });
66
+ return {
67
+ initialize() {
68
+ const ecidFromCookie = decodeKndctrCookie();
69
+ if (ecidFromCookie) {
70
+ this.setIdentityAcquired();
71
+ }
72
+ },
73
+ setIdentityAcquired() {
74
+ awaitIdentityResolve();
75
+ },
76
+ awaitIdentity() {
77
+ return awaitIdentityPromise;
78
+ },
79
+ getEcidFromCookie: () => decodeKndctrCookie()
80
+ };
81
+ };
@@ -0,0 +1,12 @@
1
+ /** @import { Logger } from '../../core/types.js' */
2
+ /** @import { CookieJar } from '../../utils/types.js' */
3
+
4
+ /**
5
+ * @typedef {Object} IdentityManager
6
+ * @property {Function} initialize
7
+ * @property {Function} setIdentityAcquired - Marks identity as acquired and resolves any pending identity promises
8
+ * @property {Function} awaitIdentity - Returns a promise that resolves when identity is acquired
9
+ * @property {Function} getEcidFromCookie
10
+ */
11
+
12
+ export const Types = {};
@@ -17,6 +17,7 @@ import createLifecycle from "./createLifecycle.js";
17
17
  import createComponentRegistry from "./createComponentRegistry.js";
18
18
  import injectSendNetworkRequest from "./network/injectSendNetworkRequest.js";
19
19
  import injectExtractEdgeInfo from "./edgeNetwork/injectExtractEdgeInfo.js";
20
+ import createIdentity from "./identity/createIdentity.js";
20
21
  import createConsent from "./consent/createConsent.js";
21
22
  import createConsentStateMachine from "./consent/createConsentStateMachine.js";
22
23
  import createEvent from "./createEvent.js";
@@ -156,6 +157,12 @@ export const createExecuteCommand = ({
156
157
  generalConsentState,
157
158
  logger
158
159
  });
160
+ const identity = createIdentity({
161
+ config,
162
+ logger,
163
+ loggingCookieJar
164
+ });
165
+ identity.initialize();
159
166
  const eventManager = createEventManager({
160
167
  config,
161
168
  logger,
@@ -177,6 +184,7 @@ export const createExecuteCommand = ({
177
184
  config,
178
185
  componentRegistry,
179
186
  consent,
187
+ identity,
180
188
  eventManager,
181
189
  fireReferrerHideableImage,
182
190
  logger: componentLogger,