@adobe/alloy 2.30.1-beta.21 → 2.30.1-beta.23
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/Advertising/createComponent.js +7 -3
- package/libEs5/components/Advertising/handlers/sendAdConversion.js +11 -6
- package/libEs5/components/Advertising/index.js +2 -1
- package/libEs5/components/BrandConcierge/configValidators.js +25 -0
- package/libEs5/components/BrandConcierge/createSendConversationEvent.js +6 -4
- package/libEs5/components/BrandConcierge/createStreamParser.js +49 -14
- package/libEs5/components/BrandConcierge/createTimeoutWrapper.js +47 -20
- package/libEs5/components/BrandConcierge/index.js +3 -5
- package/libEs5/components/BrandConcierge/validateMessage.js +5 -2
- package/libEs5/components/Context/injectOneTimeAnalyticsReferrer.js +4 -1
- package/libEs5/components/Personalization/createFetchDataHandler.js +6 -1
- package/libEs5/components/Personalization/dom-actions/remapHeadOffers.js +5 -0
- package/libEs5/components/StreamingMedia/createMediaEventManager.js +1 -1
- package/libEs5/constants/libraryVersion.js +1 -1
- package/libEs5/core/createEvent.js +4 -0
- package/libEs5/core/edgeNetwork/injectSendEdgeNetworkRequest.js +23 -0
- package/libEs5/utils/clamp.js +25 -0
- package/libEs5/utils/filterObject.js +1 -1
- package/libEs5/utils/prepareConfigOverridesForEdge.js +4 -2
- package/libEs5/utils/request/createDataCollectionRequestPayload.js +3 -0
- package/libEs5/utils/request/createRequestParams.js +1 -0
- package/libEs5/utils/request/createRequestPayload.js +11 -1
- package/libEs5/utils/request/types.js +1 -0
- package/libEs6/components/Advertising/createComponent.js +7 -3
- package/libEs6/components/Advertising/handlers/sendAdConversion.js +11 -6
- package/libEs6/components/Advertising/index.js +2 -1
- package/libEs6/components/BrandConcierge/configValidators.js +22 -0
- package/libEs6/components/BrandConcierge/createSendConversationEvent.js +6 -4
- package/libEs6/components/BrandConcierge/createStreamParser.js +49 -14
- package/libEs6/components/BrandConcierge/createTimeoutWrapper.js +47 -20
- package/libEs6/components/BrandConcierge/index.js +3 -5
- package/libEs6/components/BrandConcierge/validateMessage.js +6 -3
- package/libEs6/components/Context/injectOneTimeAnalyticsReferrer.js +3 -1
- package/libEs6/components/Personalization/createFetchDataHandler.js +6 -1
- package/libEs6/components/Personalization/dom-actions/remapHeadOffers.js +6 -1
- package/libEs6/components/StreamingMedia/createMediaEventManager.js +1 -1
- package/libEs6/constants/libraryVersion.js +1 -1
- package/libEs6/core/createEvent.js +4 -0
- package/libEs6/core/edgeNetwork/injectSendEdgeNetworkRequest.js +23 -0
- package/libEs6/utils/clamp.js +22 -0
- package/libEs6/utils/filterObject.js +1 -1
- package/libEs6/utils/prepareConfigOverridesForEdge.js +4 -2
- package/libEs6/utils/request/createDataCollectionRequestPayload.js +3 -0
- package/libEs6/utils/request/createRequestParams.js +1 -0
- package/libEs6/utils/request/createRequestPayload.js +11 -1
- package/libEs6/utils/request/types.js +1 -0
- package/package.json +1 -1
- package/types/components/Advertising/createComponent.d.ts +3 -2
- package/types/components/Advertising/createComponent.d.ts.map +1 -1
- package/types/components/Advertising/handlers/sendAdConversion.d.ts +2 -1
- package/types/components/Advertising/handlers/sendAdConversion.d.ts.map +1 -1
- package/types/components/Advertising/index.d.ts +1 -1
- package/types/components/Advertising/index.d.ts.map +1 -1
- package/types/components/BrandConcierge/configValidators.d.ts +3 -0
- package/types/components/BrandConcierge/configValidators.d.ts.map +1 -0
- package/types/components/BrandConcierge/createSendConversationEvent.d.ts.map +1 -1
- package/types/components/BrandConcierge/createStreamParser.d.ts +5 -1
- package/types/components/BrandConcierge/createStreamParser.d.ts.map +1 -1
- package/types/components/BrandConcierge/createTimeoutWrapper.d.ts +4 -1
- package/types/components/BrandConcierge/createTimeoutWrapper.d.ts.map +1 -1
- package/types/components/BrandConcierge/index.d.ts +3 -2
- package/types/components/BrandConcierge/index.d.ts.map +1 -1
- package/types/components/BrandConcierge/validateMessage.d.ts.map +1 -1
- package/types/components/Context/injectOneTimeAnalyticsReferrer.d.ts.map +1 -1
- package/types/components/Personalization/createFetchDataHandler.d.ts.map +1 -1
- package/types/components/Personalization/dom-actions/remapHeadOffers.d.ts.map +1 -1
- package/types/core/createEvent.d.ts +1 -0
- package/types/core/createEvent.d.ts.map +1 -1
- package/types/core/edgeNetwork/injectSendEdgeNetworkRequest.d.ts.map +1 -1
- package/types/utils/clamp.d.ts +3 -0
- package/types/utils/clamp.d.ts.map +1 -0
- package/types/utils/prepareConfigOverridesForEdge.d.ts.map +1 -1
- package/types/utils/request/createDataCollectionRequestPayload.d.ts.map +1 -1
- package/types/utils/request/createRequestParams.d.ts.map +1 -1
- package/types/utils/request/createRequestPayload.d.ts.map +1 -1
- package/types/utils/request/types.d.ts +2 -0
- package/types/utils/request/types.d.ts.map +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2026 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
|
+
import { STREAM_START_TIMEOUT_MS } from "./constants.js";
|
|
13
|
+
import { number, objectOf, boolean } from "../../utils/validation/index.js";
|
|
14
|
+
export default objectOf({
|
|
15
|
+
conversation: objectOf({
|
|
16
|
+
stickyConversationSession: boolean().default(false),
|
|
17
|
+
streamTimeout: number().integer().minimum(STREAM_START_TIMEOUT_MS).default(STREAM_START_TIMEOUT_MS)
|
|
18
|
+
}).default({
|
|
19
|
+
stickyConversationSession: false,
|
|
20
|
+
streamTimeout: STREAM_START_TIMEOUT_MS
|
|
21
|
+
})
|
|
22
|
+
});
|
|
@@ -32,7 +32,8 @@ export default ({
|
|
|
32
32
|
edgeDomain,
|
|
33
33
|
edgeBasePath,
|
|
34
34
|
datastreamId,
|
|
35
|
-
onBeforeEventSend
|
|
35
|
+
onBeforeEventSend,
|
|
36
|
+
conversation
|
|
36
37
|
} = config;
|
|
37
38
|
return options => {
|
|
38
39
|
let streamingEnabled = false;
|
|
@@ -131,11 +132,12 @@ export default ({
|
|
|
131
132
|
logger.info("onStreamResponse callback called with", response.getPayloadsByType("brand-concierge:conversation"));
|
|
132
133
|
onStreamResponse(response.getPayloadsByType("brand-concierge:conversation"));
|
|
133
134
|
};
|
|
134
|
-
const
|
|
135
|
-
onStreamResponseCallback
|
|
135
|
+
const timeoutWrapper = createTimeoutWrapper({
|
|
136
|
+
onStreamResponseCallback,
|
|
137
|
+
streamTimeout: conversation.streamTimeout
|
|
136
138
|
});
|
|
137
139
|
const streamParser = createStreamParser();
|
|
138
|
-
streamParser(response.body,
|
|
140
|
+
streamParser(response.body, timeoutWrapper);
|
|
139
141
|
});
|
|
140
142
|
});
|
|
141
143
|
};
|
|
@@ -16,6 +16,20 @@ export default () => {
|
|
|
16
16
|
const LINE_ENDING_REGEX = /\r\n|\r|\n/;
|
|
17
17
|
// Events are separated by blank lines (double line endings)
|
|
18
18
|
const EVENT_SEPARATOR_REGEX = /\r\n\r\n|\n\n|\r\r/;
|
|
19
|
+
// Ping comment format: `: ping` (colon followed immediately by "ping")
|
|
20
|
+
const PING_COMMENT = ": ping";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Check if an event block is a ping comment.
|
|
24
|
+
* Ping comments are SSE comments in the format `:ping`
|
|
25
|
+
*
|
|
26
|
+
* @param {string} eventData - Raw event data
|
|
27
|
+
* @returns {boolean} - True if this is a ping comment
|
|
28
|
+
*/
|
|
29
|
+
const isPingComment = eventData => {
|
|
30
|
+
const trimmed = eventData.trim();
|
|
31
|
+
return trimmed.startsWith(PING_COMMENT);
|
|
32
|
+
};
|
|
19
33
|
|
|
20
34
|
/**
|
|
21
35
|
* Parse a single SSE event from raw event data.
|
|
@@ -54,9 +68,16 @@ export default () => {
|
|
|
54
68
|
* Uses modern async iteration (for await...of) for clean, performant stream processing.
|
|
55
69
|
*
|
|
56
70
|
* @param {ReadableStream} stream - The readable stream from fetch response
|
|
57
|
-
* @param {
|
|
71
|
+
* @param {Object} callbacks - Callback functions for stream events
|
|
72
|
+
* @param {Function} callbacks.onEvent - Callback function called for each parsed event
|
|
73
|
+
* @param {Function} callbacks.onPing - Callback function called for ping comments
|
|
74
|
+
* @param {Function} callbacks.onComplete - Callback function called when stream ends
|
|
58
75
|
*/
|
|
59
|
-
return async (stream,
|
|
76
|
+
return async (stream, {
|
|
77
|
+
onEvent,
|
|
78
|
+
onPing,
|
|
79
|
+
onComplete
|
|
80
|
+
}) => {
|
|
60
81
|
const decoder = new TextDecoder(ENCODING);
|
|
61
82
|
let buffer = "";
|
|
62
83
|
try {
|
|
@@ -66,27 +87,41 @@ export default () => {
|
|
|
66
87
|
});
|
|
67
88
|
const events = buffer.split(EVENT_SEPARATOR_REGEX);
|
|
68
89
|
buffer = events.pop() || "";
|
|
69
|
-
for (const
|
|
70
|
-
const trimmedEvent =
|
|
71
|
-
if (trimmedEvent) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
90
|
+
for (const event of events) {
|
|
91
|
+
const trimmedEvent = event.trim();
|
|
92
|
+
if (!trimmedEvent) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (isPingComment(trimmedEvent)) {
|
|
96
|
+
onPing();
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const parsedEvent = parseEventFromBuffer(trimmedEvent);
|
|
100
|
+
if (parsedEvent !== null) {
|
|
101
|
+
onEvent(parsedEvent);
|
|
76
102
|
}
|
|
77
103
|
}
|
|
78
104
|
}
|
|
79
105
|
const trimmedBuffer = buffer.trim();
|
|
80
|
-
if (trimmedBuffer) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
106
|
+
if (!trimmedBuffer) {
|
|
107
|
+
onComplete();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (isPingComment(trimmedBuffer)) {
|
|
111
|
+
onPing();
|
|
112
|
+
onComplete();
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const event = parseEventFromBuffer(trimmedBuffer);
|
|
116
|
+
if (event !== null) {
|
|
117
|
+
onEvent(event);
|
|
85
118
|
}
|
|
119
|
+
onComplete();
|
|
86
120
|
} catch (error) {
|
|
87
121
|
onEvent({
|
|
88
122
|
error
|
|
89
123
|
});
|
|
124
|
+
onComplete();
|
|
90
125
|
}
|
|
91
126
|
};
|
|
92
127
|
};
|
|
@@ -9,41 +9,68 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA
|
|
|
9
9
|
OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
10
|
governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
|
-
import { STREAM_START_TIMEOUT_MS } from "./constants.js";
|
|
13
12
|
|
|
14
13
|
/**
|
|
15
|
-
* Creates a wrapper around a callback that implements a timeout
|
|
16
|
-
*
|
|
14
|
+
* Creates a wrapper around a callback that implements a rolling timeout.
|
|
15
|
+
* The timeout resets on every data event or ping. If no activity occurs
|
|
16
|
+
* within the timeout period, an error is passed to the callback.
|
|
17
17
|
* After timeout fires, all subsequent calls are ignored.
|
|
18
18
|
*
|
|
19
|
-
* @param {
|
|
20
|
-
* @
|
|
19
|
+
* @param {Object} options - Configuration options
|
|
20
|
+
* @param {Function} options.onStreamResponseCallback - The callback function to wrap
|
|
21
|
+
* @param {number} options.streamTimeout - Timeout duration in milliseconds
|
|
22
|
+
* @returns {Object} Object with onEvent, onPing, and onComplete handler functions
|
|
21
23
|
*/
|
|
22
24
|
export default ({
|
|
23
|
-
onStreamResponseCallback
|
|
25
|
+
onStreamResponseCallback,
|
|
26
|
+
streamTimeout
|
|
24
27
|
}) => {
|
|
25
|
-
const timeoutMs = STREAM_START_TIMEOUT_MS;
|
|
26
|
-
let firstCallMade = false;
|
|
27
28
|
let timedOut = false;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
let timeoutId;
|
|
30
|
+
const resetTimeout = () => {
|
|
31
|
+
clearTimeout(timeoutId);
|
|
32
|
+
timeoutId = setTimeout(() => {
|
|
31
33
|
timedOut = true;
|
|
32
34
|
onStreamResponseCallback({
|
|
33
35
|
error: {
|
|
34
36
|
message: "Stream timeout: No data received within 10 seconds"
|
|
35
37
|
}
|
|
36
38
|
});
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
}, streamTimeout);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Start initial timeout
|
|
43
|
+
resetTimeout();
|
|
44
|
+
return {
|
|
45
|
+
/**
|
|
46
|
+
* Handle data events from the stream parser.
|
|
47
|
+
* Resets the timeout and forwards the event to the callback.
|
|
48
|
+
*
|
|
49
|
+
* @param {Object} event - The parsed SSE event
|
|
50
|
+
*/
|
|
51
|
+
onEvent: event => {
|
|
52
|
+
if (timedOut) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
resetTimeout();
|
|
56
|
+
onStreamResponseCallback(event);
|
|
57
|
+
},
|
|
58
|
+
/**
|
|
59
|
+
* Handle ping events from the stream parser.
|
|
60
|
+
* Resets the timeout but does not forward anything to the callback.
|
|
61
|
+
*/
|
|
62
|
+
onPing: () => {
|
|
63
|
+
if (timedOut) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
resetTimeout();
|
|
67
|
+
},
|
|
68
|
+
/**
|
|
69
|
+
* Handle stream completion.
|
|
70
|
+
* Clears the timeout since the stream has ended successfully.
|
|
71
|
+
*/
|
|
72
|
+
onComplete: () => {
|
|
45
73
|
clearTimeout(timeoutId);
|
|
46
74
|
}
|
|
47
|
-
onStreamResponseCallback(event);
|
|
48
75
|
};
|
|
49
76
|
};
|
|
@@ -15,9 +15,9 @@ import createBuildEndpointUrl from "./createBuildEndpointUrl.js";
|
|
|
15
15
|
import queryString from "@adobe/reactor-query-string";
|
|
16
16
|
import { getNamespacedCookieName } from "../../utils/index.js";
|
|
17
17
|
import { BC_SESSION_COOKIE_NAME } from "./constants.js";
|
|
18
|
-
import { boolean, objectOf } from "../../utils/validation/index.js";
|
|
19
18
|
import createGetEcidFromCookie from "../../utils/createDecodeKndctrCookie.js";
|
|
20
19
|
import createSendConversationServiceRequest from "./createSendConversationServiceRequest.js";
|
|
20
|
+
import configValidators from "./configValidators.js";
|
|
21
21
|
const createConciergeComponent = ({
|
|
22
22
|
loggingCookieJar,
|
|
23
23
|
logger,
|
|
@@ -34,7 +34,7 @@ const createConciergeComponent = ({
|
|
|
34
34
|
const {
|
|
35
35
|
fetch
|
|
36
36
|
} = window;
|
|
37
|
-
if (!config.stickyConversationSession) {
|
|
37
|
+
if (!config.conversation.stickyConversationSession) {
|
|
38
38
|
loggingCookieJar.remove(getNamespacedCookieName(config.orgId, BC_SESSION_COOKIE_NAME), {
|
|
39
39
|
domain: apexDomain
|
|
40
40
|
});
|
|
@@ -94,7 +94,5 @@ const createConciergeComponent = ({
|
|
|
94
94
|
};
|
|
95
95
|
};
|
|
96
96
|
createConciergeComponent.namespace = "BrandConcierge";
|
|
97
|
-
createConciergeComponent.configValidators =
|
|
98
|
-
stickyConversationSession: boolean().default(false)
|
|
99
|
-
});
|
|
97
|
+
createConciergeComponent.configValidators = configValidators;
|
|
100
98
|
export default createConciergeComponent;
|
|
@@ -9,12 +9,14 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA
|
|
|
9
9
|
OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
10
|
governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
|
-
import { anyOf, arrayOf, objectOf, string } from "../../utils/validation/index.js";
|
|
12
|
+
import { anyOf, arrayOf, objectOf, string, callback } from "../../utils/validation/index.js";
|
|
13
|
+
import { noop } from "../../utils/index.js";
|
|
13
14
|
export default ({
|
|
14
15
|
options
|
|
15
16
|
}) => {
|
|
16
17
|
const brandConciergeEventValidator = anyOf([objectOf({
|
|
17
|
-
message: string().required()
|
|
18
|
+
message: string().required(),
|
|
19
|
+
onStreamResponse: callback().default(noop)
|
|
18
20
|
}), objectOf({
|
|
19
21
|
xdm: objectOf({
|
|
20
22
|
interactionId: string(),
|
|
@@ -31,7 +33,8 @@ export default ({
|
|
|
31
33
|
data: objectOf({
|
|
32
34
|
type: string().required(),
|
|
33
35
|
payload: objectOf({})
|
|
34
|
-
}).required()
|
|
36
|
+
}).required(),
|
|
37
|
+
onStreamResponse: callback().default(noop)
|
|
35
38
|
})]);
|
|
36
39
|
return brandConciergeEventValidator(options);
|
|
37
40
|
};
|
|
@@ -10,12 +10,14 @@ 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
|
+
// Because these events are originated by the SDK rather than user actions, don't change the referrer
|
|
14
|
+
const IGNORED_EVENT_TYPES = new Set(["decisioning.propositionFetch", "decisioning.propositionDisplay", "decisioning.propositionInteract"]);
|
|
13
15
|
export default window => {
|
|
14
16
|
let lastReferrerSent = null;
|
|
15
17
|
return event => {
|
|
16
18
|
const content = event.getContent();
|
|
17
19
|
const eventType = content.xdm?.eventType;
|
|
18
|
-
if (eventType
|
|
20
|
+
if (IGNORED_EVENT_TYPES.has(eventType)) {
|
|
19
21
|
return;
|
|
20
22
|
}
|
|
21
23
|
|
|
@@ -11,6 +11,7 @@ governing permissions and limitations under the License.
|
|
|
11
11
|
*/
|
|
12
12
|
import { groupBy, isNonEmptyArray } from "../../utils/index.js";
|
|
13
13
|
import PAGE_WIDE_SCOPE from "../../constants/pageWideScope.js";
|
|
14
|
+
import { REDIRECT_ITEM } from "../../constants/schema.js";
|
|
14
15
|
const DECISIONS_HANDLE = "personalization:decisions";
|
|
15
16
|
export default ({
|
|
16
17
|
logger,
|
|
@@ -103,7 +104,11 @@ export default ({
|
|
|
103
104
|
// Render could take a long time especially if one of the renders
|
|
104
105
|
// is waiting for html to appear on the page. We show the containers
|
|
105
106
|
// immediately, and whatever renders quickly will not have flicker.
|
|
106
|
-
|
|
107
|
+
// However, skip showing containers if there's only one page proposition with a single REDIRECT_ITEM
|
|
108
|
+
const shouldSkipShowContainers = pagePropositions.length === 1 && pagePropositions[0].getItems().every(p => p.getSchema() === REDIRECT_ITEM);
|
|
109
|
+
if (!shouldSkipShowContainers) {
|
|
110
|
+
showContainers();
|
|
111
|
+
}
|
|
107
112
|
} else {
|
|
108
113
|
({
|
|
109
114
|
returnedPropositions,
|
|
@@ -21,7 +21,7 @@ import { is } from "./scripts.js";
|
|
|
21
21
|
import { createFragment, selectNodesWithEq } from "./dom/index.js";
|
|
22
22
|
import isBlankString from "../../../utils/isBlankString.js";
|
|
23
23
|
import { HEAD } from "../../../constants/tagName.js";
|
|
24
|
-
import { DOM_ACTION_APPEND_HTML } from "./initDomActionsModules.js";
|
|
24
|
+
import { DOM_ACTION_APPEND_HTML, DOM_ACTION_CUSTOM_CODE } from "./initDomActionsModules.js";
|
|
25
25
|
const HEAD_TAGS_SELECTOR = "SCRIPT,LINK,STYLE";
|
|
26
26
|
const filterHeadContent = content => {
|
|
27
27
|
const container = createFragment(content);
|
|
@@ -36,6 +36,11 @@ export default action => {
|
|
|
36
36
|
content,
|
|
37
37
|
selector
|
|
38
38
|
} = result;
|
|
39
|
+
|
|
40
|
+
// Custom code actions have a "HEAD" selector, but are handled differently.
|
|
41
|
+
if (result.type === DOM_ACTION_CUSTOM_CODE) {
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
39
44
|
if (isBlankString(content)) {
|
|
40
45
|
return result;
|
|
41
46
|
}
|
|
@@ -24,6 +24,7 @@ const getXdmPropositions = xdm => {
|
|
|
24
24
|
};
|
|
25
25
|
export default () => {
|
|
26
26
|
const content = {};
|
|
27
|
+
const createdAt = Date.now();
|
|
27
28
|
let userXdm;
|
|
28
29
|
let userData;
|
|
29
30
|
let documentMayUnload = false;
|
|
@@ -138,6 +139,9 @@ export default () => {
|
|
|
138
139
|
getDocumentMayUnload() {
|
|
139
140
|
return documentMayUnload;
|
|
140
141
|
},
|
|
142
|
+
getCreatedAt() {
|
|
143
|
+
return createdAt;
|
|
144
|
+
},
|
|
141
145
|
isEmpty() {
|
|
142
146
|
return isEmptyObject(content) && (!userXdm || isEmptyObject(userXdm)) && (!userData || isEmptyObject(userData));
|
|
143
147
|
},
|
|
@@ -17,8 +17,25 @@ import { ID_THIRD_PARTY as ID_THIRD_PARTY_DOMAIN } from "../../constants/domain.
|
|
|
17
17
|
import apiVersion from "../../constants/apiVersion.js";
|
|
18
18
|
import { createCallbackAggregator, noop } from "../../utils/index.js";
|
|
19
19
|
import { isNetworkError } from "../../utils/networkErrors.js";
|
|
20
|
+
import clamp from "../../utils/clamp.js";
|
|
20
21
|
import mergeLifecycleResponses from "./mergeLifecycleResponses.js";
|
|
21
22
|
import handleRequestFailure from "./handleRequestFailure.js";
|
|
23
|
+
const MAX_QUEUE_TIME_MILLIS = 300000; // 5 minutes
|
|
24
|
+
|
|
25
|
+
const calculateQueueTimeMillis = payload => {
|
|
26
|
+
if (typeof payload.getEvents !== "function") {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
const events = payload.getEvents();
|
|
30
|
+
if (events.length === 0) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// In practice, there should only be one event in the payload, in the future if this changes we'll need to
|
|
35
|
+
// evaluate what timestamp to use (earliest, average, latest), or move the queueTime to the event meta
|
|
36
|
+
const earliestCreatedAt = Math.min(...events.map(event => event.getCreatedAt()));
|
|
37
|
+
return clamp(Date.now() - earliestCreatedAt, 0, MAX_QUEUE_TIME_MILLIS);
|
|
38
|
+
};
|
|
22
39
|
const isDemdexBlockedError = (error, request) => {
|
|
23
40
|
return request.getUseIdThirdPartyDomain() && isNetworkError(error);
|
|
24
41
|
};
|
|
@@ -94,6 +111,12 @@ export default ({
|
|
|
94
111
|
const endpointDomain = hasDemdexFailed || !request.getUseIdThirdPartyDomain() ? edgeDomain : ID_THIRD_PARTY_DOMAIN;
|
|
95
112
|
const url = buildEndpointUrl(endpointDomain, request);
|
|
96
113
|
const payload = request.getPayload();
|
|
114
|
+
const queueTimeMillis = calculateQueueTimeMillis(payload);
|
|
115
|
+
if (queueTimeMillis !== undefined) {
|
|
116
|
+
payload.mergeMeta({
|
|
117
|
+
queueTimeMillis
|
|
118
|
+
});
|
|
119
|
+
}
|
|
97
120
|
cookieTransfer.cookiesToPayload(payload, endpointDomain);
|
|
98
121
|
return sendNetworkRequest({
|
|
99
122
|
requestId: request.getId(),
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
/**
|
|
14
|
+
* Clamps a value between a minimum and maximum value.
|
|
15
|
+
* @param {number} value - The value to clamp.
|
|
16
|
+
* @param {number} min - The minimum value.
|
|
17
|
+
* @param {number} max - The maximum value.
|
|
18
|
+
* @returns {number} The clamped value.
|
|
19
|
+
*/
|
|
20
|
+
export default (value, min, max) => {
|
|
21
|
+
return Math.max(min, Math.min(value, max));
|
|
22
|
+
};
|
|
@@ -25,11 +25,13 @@ export default configuration => {
|
|
|
25
25
|
return null;
|
|
26
26
|
}
|
|
27
27
|
// remove entries that are empty strings or arrays
|
|
28
|
-
const configOverrides = filterObject(configuration, value => {
|
|
28
|
+
const configOverrides = filterObject(configuration, (value, key) => {
|
|
29
29
|
if (isNil(value)) {
|
|
30
30
|
return false;
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
// We want to remove all the { enabled: true } values, but leave any other boolean values.
|
|
33
|
+
// Experience Edge will not accept { enabled: true } values as true is the default for "enabled".
|
|
34
|
+
if (isBoolean(value) && (key !== "enabled" || value === false)) {
|
|
33
35
|
return true;
|
|
34
36
|
}
|
|
35
37
|
if (isNumber(value)) {
|
|
@@ -34,6 +34,9 @@ export default () => {
|
|
|
34
34
|
content.events = content.events || [];
|
|
35
35
|
content.events.push(event);
|
|
36
36
|
},
|
|
37
|
+
getEvents: () => {
|
|
38
|
+
return content.events || [];
|
|
39
|
+
},
|
|
37
40
|
getDocumentMayUnload: () => {
|
|
38
41
|
return (content.events || []).some(event => event.getDocumentMayUnload());
|
|
39
42
|
}
|
|
@@ -42,5 +42,6 @@ export default ({
|
|
|
42
42
|
if (localConfigOverridesWithoutDatastreamId && !isEmptyObject(localConfigOverridesWithoutDatastreamId)) {
|
|
43
43
|
payload.mergeConfigOverride(localConfigOverridesWithoutDatastreamId);
|
|
44
44
|
}
|
|
45
|
+
payload.finalizeConfigOverrides();
|
|
45
46
|
return requestParams;
|
|
46
47
|
};
|
|
@@ -88,7 +88,17 @@ export default options => {
|
|
|
88
88
|
mergeMeta: createMerger(content, "meta"),
|
|
89
89
|
mergeState: createMerger(content, "meta.state"),
|
|
90
90
|
mergeQuery: createMerger(content, "query"),
|
|
91
|
-
mergeConfigOverride: updates => mergeConfigOverrides(
|
|
91
|
+
mergeConfigOverride: updates => mergeConfigOverrides(updates),
|
|
92
|
+
finalizeConfigOverrides: () => {
|
|
93
|
+
if (content.meta?.configOverrides) {
|
|
94
|
+
const prepared = prepareConfigOverridesForEdge(content.meta.configOverrides);
|
|
95
|
+
if (prepared === null) {
|
|
96
|
+
delete content.meta.configOverrides;
|
|
97
|
+
} else {
|
|
98
|
+
content.meta.configOverrides = prepared;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
},
|
|
92
102
|
addIdentity,
|
|
93
103
|
hasIdentity,
|
|
94
104
|
toJSON() {
|
|
@@ -49,6 +49,7 @@ governing permissions and limitations under the License.
|
|
|
49
49
|
* @property {function(string, Identity): void} options.addIdentity
|
|
50
50
|
* @property {function(string): boolean} options.hasIdentity
|
|
51
51
|
* @property {function(object): void} addEvent
|
|
52
|
+
* @property {function(): Array} getEvents
|
|
52
53
|
* @property {function(): boolean} getDocumentMayUnload
|
|
53
54
|
* @property {function(): object} toJSON
|
|
54
55
|
*/
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
declare function _default({ logger, config, eventManager, cookieManager, adConversionHandler, getBrowser, }: {
|
|
1
|
+
declare function _default({ logger, config, eventManager, cookieManager, adConversionHandler, getBrowser, consent, }: {
|
|
2
2
|
logger: any;
|
|
3
3
|
config: any;
|
|
4
4
|
eventManager: any;
|
|
5
5
|
cookieManager: any;
|
|
6
6
|
adConversionHandler: any;
|
|
7
7
|
getBrowser: any;
|
|
8
|
+
consent: any;
|
|
8
9
|
}): {
|
|
9
10
|
lifecycle: {
|
|
10
|
-
onComponentsRegistered():
|
|
11
|
+
onComponentsRegistered(): void;
|
|
11
12
|
onBeforeEvent: ({ event, advertising }: {
|
|
12
13
|
event: any;
|
|
13
14
|
advertising?: {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createComponent.d.ts","sourceRoot":"","sources":["../../../packages/core/src/components/Advertising/createComponent.js"],"names":[],"mappings":"AAee
|
|
1
|
+
{"version":3,"file":"createComponent.d.ts","sourceRoot":"","sources":["../../../packages/core/src/components/Advertising/createComponent.js"],"names":[],"mappings":"AAee;;;;;;;;;;;;;;;;EAwCd"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
declare function _default({ eventManager, cookieManager, adConversionHandler, logger, componentConfig, getBrowser, }: {
|
|
1
|
+
declare function _default({ eventManager, cookieManager, adConversionHandler, logger, componentConfig, getBrowser, consent, }: {
|
|
2
2
|
eventManager: any;
|
|
3
3
|
cookieManager: any;
|
|
4
4
|
adConversionHandler: any;
|
|
5
5
|
logger: any;
|
|
6
6
|
componentConfig: any;
|
|
7
7
|
getBrowser: any;
|
|
8
|
+
consent: any;
|
|
8
9
|
}): () => Promise<any>;
|
|
9
10
|
export default _default;
|
|
10
11
|
//# sourceMappingURL=sendAdConversion.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sendAdConversion.d.ts","sourceRoot":"","sources":["../../../../packages/core/src/components/Advertising/handlers/sendAdConversion.js"],"names":[],"mappings":"AAqBe
|
|
1
|
+
{"version":3,"file":"sendAdConversion.d.ts","sourceRoot":"","sources":["../../../../packages/core/src/components/Advertising/handlers/sendAdConversion.js"],"names":[],"mappings":"AAqBe;;;;;;;;uBAgDd"}
|
|
@@ -8,7 +8,7 @@ declare function createAdvertising({ logger, config, eventManager, sendEdgeNetwo
|
|
|
8
8
|
getBrowser: any;
|
|
9
9
|
}): {
|
|
10
10
|
lifecycle: {
|
|
11
|
-
onComponentsRegistered():
|
|
11
|
+
onComponentsRegistered(): void;
|
|
12
12
|
onBeforeEvent: ({ event, advertising }: {
|
|
13
13
|
event: any;
|
|
14
14
|
advertising?: {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../packages/core/src/components/Advertising/index.js"],"names":[],"mappings":";AAqBA;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../packages/core/src/components/Advertising/index.js"],"names":[],"mappings":";AAqBA;;;;;;;;;;;;;;;EA8BC;;;;;6BAtC4B,uBAAuB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configValidators.d.ts","sourceRoot":"","sources":["../../../packages/core/src/components/BrandConcierge/configValidators.js"],"names":[],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSendConversationEvent.d.ts","sourceRoot":"","sources":["../../../packages/core/src/components/BrandConcierge/createSendConversationEvent.js"],"names":[],"mappings":"AAkBe;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"createSendConversationEvent.d.ts","sourceRoot":"","sources":["../../../packages/core/src/components/BrandConcierge/createSendConversationEvent.js"],"names":[],"mappings":"AAkBe;;;;;;;;;;;;KAqBL,YAAO,SAgHhB"}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
declare function _default(): (stream: ReadableStream, onEvent
|
|
1
|
+
declare function _default(): (stream: ReadableStream, { onEvent, onPing, onComplete }: {
|
|
2
|
+
onEvent: Function;
|
|
3
|
+
onPing: Function;
|
|
4
|
+
onComplete: Function;
|
|
5
|
+
}) => Promise<void>;
|
|
2
6
|
export default _default;
|
|
3
7
|
//# sourceMappingURL=createStreamParser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createStreamParser.d.ts","sourceRoot":"","sources":["../../../packages/core/src/components/BrandConcierge/createStreamParser.js"],"names":[],"mappings":"AAWe,
|
|
1
|
+
{"version":3,"file":"createStreamParser.d.ts","sourceRoot":"","sources":["../../../packages/core/src/components/BrandConcierge/createStreamParser.js"],"names":[],"mappings":"AAWe,8BAwEC,QANH,cAMS,EAAE,iCAJnB;IAA4B,OAAO;IACP,MAAM;IACN,UAAU;CAEY,mBAuDtD"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
declare function _default({ onStreamResponseCallback }:
|
|
1
|
+
declare function _default({ onStreamResponseCallback, streamTimeout }: {
|
|
2
|
+
onStreamResponseCallback: Function;
|
|
3
|
+
streamTimeout: number;
|
|
4
|
+
}): any;
|
|
2
5
|
export default _default;
|
|
3
6
|
//# sourceMappingURL=createTimeoutWrapper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createTimeoutWrapper.d.ts","sourceRoot":"","sources":["../../../packages/core/src/components/BrandConcierge/createTimeoutWrapper.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"createTimeoutWrapper.d.ts","sourceRoot":"","sources":["../../../packages/core/src/components/BrandConcierge/createTimeoutWrapper.js"],"names":[],"mappings":"AAuBe,uEAJZ;IAA0B,wBAAwB;IAC1B,aAAa,EAA7B,MAAM;CACd,OAuDF"}
|