@adobe/alloy 2.35.1-beta.0 → 2.35.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.
@@ -1,10 +1,11 @@
1
- declare function _default({ eventManager, config, logger, sendConversationServiceRequest, buildEndpointUrl, cookieTransfer, createResponse, decodeKndctrCookie, lifecycle, consent, session, getPageLocation, }: {
1
+ declare function _default({ eventManager, config, logger, sendConversationServiceRequest, buildEndpointUrl, cookieTransfer, alwaysTransferCookies, createResponse, decodeKndctrCookie, lifecycle, consent, session, getPageLocation, }: {
2
2
  eventManager: any;
3
3
  config: any;
4
4
  logger: any;
5
5
  sendConversationServiceRequest: any;
6
6
  buildEndpointUrl: any;
7
7
  cookieTransfer: any;
8
+ alwaysTransferCookies?: never[] | undefined;
8
9
  createResponse: any;
9
10
  decodeKndctrCookie: any;
10
11
  lifecycle: any;
@@ -1,5 +1,5 @@
1
1
  export default createConciergeComponent;
2
- declare function createConciergeComponent({ loggingCookieJar, logger, eventManager, consent, instanceName, sendEdgeNetworkRequest, config, lifecycle, cookieTransfer, createResponse, platformServices, }: {
2
+ declare function createConciergeComponent({ loggingCookieJar, logger, eventManager, consent, instanceName, sendEdgeNetworkRequest, config, lifecycle, cookieTransfer, createResponse, platformServices, createSendConversationEvent: createSendConversationEventFactory, }: {
3
3
  loggingCookieJar: any;
4
4
  logger: any;
5
5
  eventManager: any;
@@ -11,6 +11,21 @@ declare function createConciergeComponent({ loggingCookieJar, logger, eventManag
11
11
  cookieTransfer: any;
12
12
  createResponse: any;
13
13
  platformServices: any;
14
+ createSendConversationEvent?: (({ eventManager, config, logger, sendConversationServiceRequest, buildEndpointUrl, cookieTransfer, alwaysTransferCookies, createResponse, decodeKndctrCookie, lifecycle, consent, session, getPageLocation, }: {
15
+ eventManager: any;
16
+ config: any;
17
+ logger: any;
18
+ sendConversationServiceRequest: any;
19
+ buildEndpointUrl: any;
20
+ cookieTransfer: any;
21
+ alwaysTransferCookies?: never[] | undefined;
22
+ createResponse: any;
23
+ decodeKndctrCookie: any;
24
+ lifecycle: any;
25
+ consent: any;
26
+ session: any;
27
+ getPageLocation: any;
28
+ }) => (options: any) => any) | undefined;
14
29
  }): {
15
30
  lifecycle: {
16
31
  onBeforeEvent({ event }: {
@@ -1,3 +1,4 @@
1
1
  export const MBOX_EDGE_CLUSTER: "mboxEdgeCluster";
2
2
  export const AT_QA_MODE: "at_qa_mode";
3
3
  export const MBOX: "mbox";
4
+ export const MUNCHKIN: "_mkto_trk";
@@ -9,7 +9,7 @@ declare function _default({ cookieJar, shouldTransferCookie, apexDomain, datePro
9
9
  * access first-party cookies, therefore we transfer cookies into
10
10
  * the request body so they can be read by the server.
11
11
  */
12
- cookiesToPayload(payload: any, endpointDomain: any): void;
12
+ cookiesToPayload(payload: any, endpointDomain: any, extraCookieNames?: any[]): void;
13
13
  /**
14
14
  * When receiving from a third-party endpoint, the endpoint won't be able to
15
15
  * write first-party cookies, therefore we write first-party cookies
@@ -1,4 +1,5 @@
1
1
  export { default as createCoreConfigs } from "./core/config/createCoreConfigs.js";
2
+ export { default as consent } from "./components/Consent/index.js";
2
3
  export function createCustomInstance(options?: {
3
4
  name?: string | undefined;
4
5
  monitors?: import("./core/types.js").AlloyMonitor[] | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/alloy",
3
- "version": "2.35.1-beta.0",
3
+ "version": "2.35.1",
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.3-beta.0"
72
+ "@adobe/alloy-core": "^1.2.3"
73
73
  },
74
74
  "devDependencies": {
75
75
  "glob": "^13.0.6",
@@ -14,6 +14,55 @@ import { SCRIPT } from "@adobe/alloy-core/constants/tagName.js";
14
14
  import { SRC } from "@adobe/alloy-core/constants/elementAttribute.js";
15
15
  import { getAttribute, getNonce } from "./dom/index.js";
16
16
 
17
+ const TYPE = "type";
18
+ const MODULE = "module";
19
+ const NONCE = "nonce";
20
+ const NOMODULE = "nomodule";
21
+
22
+ // Per the HTML spec, a <script> only ever executes if its type is absent/
23
+ // empty, "module", or one of these recognized JavaScript MIME type essences
24
+ // (https://mimesniff.spec.whatwg.org/#javascript-mime-type). Any other type
25
+ // (e.g. "importmap", "application/json", a templating library's custom type)
26
+ // makes the element a data block: the browser never executes it, regardless
27
+ // of whether it's parsed from HTML, inserted via innerHTML, or appended with
28
+ // appendChild. Such elements are left untouched by this module — extracting
29
+ // and re-inserting them would be pointless at best, and at worst (if `type`
30
+ // were dropped along the way) would turn inert data into code that runs.
31
+ const JAVASCRIPT_MIME_TYPES = new Set([
32
+ "application/ecmascript",
33
+ "application/javascript",
34
+ "application/x-ecmascript",
35
+ "application/x-javascript",
36
+ "text/ecmascript",
37
+ "text/javascript",
38
+ "text/javascript1.0",
39
+ "text/javascript1.1",
40
+ "text/javascript1.2",
41
+ "text/javascript1.3",
42
+ "text/javascript1.4",
43
+ "text/javascript1.5",
44
+ "text/jscript",
45
+ "text/livescript",
46
+ "text/x-ecmascript",
47
+ "text/x-javascript",
48
+ ]);
49
+
50
+ // Attributes that affect how the script executes/fetches (as opposed to
51
+ // identity/presentation attributes like id, class, and data-*, which are
52
+ // intentionally not copied — see loadScript below). `src` is handled
53
+ // separately since it needs different treatment for inline vs. remote
54
+ // scripts, and `nonce` is copied here as a fallback but then overridden
55
+ // below with the page's current CSP nonce when one is found.
56
+ const COPIED_ATTRIBUTES = [
57
+ TYPE,
58
+ NONCE,
59
+ "crossorigin",
60
+ "integrity",
61
+ "referrerpolicy",
62
+ "fetchpriority",
63
+ "nomodule",
64
+ ];
65
+
17
66
  const getPromise = (url, script) => {
18
67
  return new Promise((resolve, reject) => {
19
68
  script.onload = () => {
@@ -24,24 +73,45 @@ const getPromise = (url, script) => {
24
73
  };
25
74
  });
26
75
  };
76
+
77
+ // Re-creates a script in <head> so the browser executes it (scripts inserted via
78
+ // innerHTML never run). Handles both remote scripts (with a src) and inline
79
+ // module scripts: an inline `type="module"` executes asynchronously and belongs
80
+ // with the head-loaded scripts rather than the synchronously-run inline path.
27
81
  const loadScript = (source) => {
28
82
  const url = getAttribute(source, SRC);
29
83
  const script = document.createElement("script");
30
- // Preserve all author-supplied attributes (class, type, data-*, etc.) so
31
- // consumers relying on them keep working.
32
- const { attributes } = source;
33
- for (let i = 0; i < attributes.length; i += 1) {
34
- const { name, value } = attributes[i];
35
- script.setAttribute(name, value);
36
- }
37
- // Override invariants last so they can't be clobbered by the source element.
84
+ // Only carry the attributes required to execute the script correctly:
85
+ // `src` (below) and COPIED_ATTRIBUTES. Author attributes such as `id`,
86
+ // `class`, and `data-*` are intentionally NOT copied: the original offer
87
+ // <script> is left in the page (inert), so copying its id/class onto this
88
+ // executed element would create duplicate matches for
89
+ // document.getElementById / querySelector.
90
+ COPIED_ATTRIBUTES.forEach((name) => {
91
+ const value = getAttribute(source, name);
92
+ if (value !== null) {
93
+ script.setAttribute(name, value);
94
+ }
95
+ });
96
+ // The page's current CSP nonce takes priority over whatever nonce (if any)
97
+ // was written into the source markup, since that's the one the browser
98
+ // will actually check against the CSP header for this page load.
38
99
  const nonce = getNonce();
39
100
  if (nonce) {
40
- script.setAttribute("nonce", nonce);
101
+ script.setAttribute(NONCE, nonce);
41
102
  }
103
+
104
+ if (!url) {
105
+ // Inline module script: carry the code across and let it execute in <head>.
106
+ // Inline scripts emit no load event, so completion cannot be tracked; we
107
+ // resolve immediately and rely on the browser's deferred module execution.
108
+ script.textContent = source.textContent;
109
+ document.head.appendChild(script);
110
+ return Promise.resolve(script);
111
+ }
112
+
113
+ script.src = url;
42
114
  script.async = true;
43
- // Assign load handlers after copying attributes so a copied inline
44
- // onload/onerror attribute can't break load-completion tracking.
45
115
  const promise = getPromise(url, script);
46
116
  document.head.appendChild(script);
47
117
  return promise;
@@ -50,11 +120,59 @@ const loadScript = (source) => {
50
120
  export const is = (element, tagName) =>
51
121
  !!element && element.tagName === tagName;
52
122
 
53
- const isInlineScript = (element) =>
54
- is(element, SCRIPT) && !getAttribute(element, SRC);
123
+ // Normalizes away casing/whitespace/parameters (e.g. "TEXT/JAVASCRIPT ;
124
+ // charset=utf-8") so it can be compared against MODULE/JAVASCRIPT_MIME_TYPES.
125
+ const getNormalizedType = (element) => {
126
+ const type = getAttribute(element, TYPE);
127
+ return type ? type.split(";")[0].trim().toLowerCase() : "";
128
+ };
55
129
 
56
- const isRemoteScript = (element) =>
57
- is(element, SCRIPT) && getAttribute(element, SRC);
130
+ const isModule = (element) => getNormalizedType(element) === MODULE;
131
+
132
+ // An empty src (`<script src="">`) is treated as "no src" — it points nowhere,
133
+ // so the script is handled on the inline path rather than fetched.
134
+ const hasSrc = (element) => !!getAttribute(element, SRC);
135
+
136
+ // A <script> the browser would actually execute: a classic script (type is
137
+ // absent/empty or a recognized JavaScript MIME type) or an ES module. Any other
138
+ // type is a data block (e.g. "importmap", "application/json", a templating
139
+ // library's custom type) that never runs — see JAVASCRIPT_MIME_TYPES above.
140
+ // Only executable scripts are extracted and re-inserted; the rest are left
141
+ // untouched, since forcing them to run was never the intent.
142
+ const isExecutableScript = (element) => {
143
+ if (!is(element, SCRIPT)) {
144
+ return false;
145
+ }
146
+ const type = getNormalizedType(element);
147
+ return type === "" || type === MODULE || JAVASCRIPT_MIME_TYPES.has(type);
148
+ };
149
+
150
+ // How a given <script> must be re-created for the browser to run it:
151
+ // HEAD_SCRIPT – re-created in <head>: any remote script (with a src), plus
152
+ // inline ES modules. An inline `type="module"` executes
153
+ // asynchronously, so it belongs with the head scripts rather
154
+ // than the synchronous inline path.
155
+ // INLINE_SCRIPT – classic inline script: re-created and run synchronously in
156
+ // the offer container.
157
+ const HEAD_SCRIPT = "head";
158
+ const INLINE_SCRIPT = "inline";
159
+
160
+ // Classifies a <script>, or returns null when there's nothing to run: either a
161
+ // data block the browser would never execute (left untouched), or an inline
162
+ // script with no code. `src`-less inline scripts need code to be worth running;
163
+ // a remote script's code lives at its `src`, so it always qualifies.
164
+ const classifyScript = (element) => {
165
+ if (!isExecutableScript(element)) {
166
+ return null;
167
+ }
168
+ if (hasSrc(element)) {
169
+ return HEAD_SCRIPT;
170
+ }
171
+ if (!element.textContent) {
172
+ return null;
173
+ }
174
+ return isModule(element) ? HEAD_SCRIPT : INLINE_SCRIPT;
175
+ };
58
176
 
59
177
  export const getInlineScripts = (fragment) => {
60
178
  const scripts = selectNodes(SCRIPT, fragment);
@@ -68,17 +186,24 @@ export const getInlineScripts = (fragment) => {
68
186
  for (let i = 0; i < length; i += 1) {
69
187
  const element = scripts[i];
70
188
 
71
- if (!isInlineScript(element)) {
189
+ if (classifyScript(element) !== INLINE_SCRIPT) {
72
190
  continue;
73
191
  }
74
192
 
75
193
  const { textContent } = element;
76
194
 
77
- if (!textContent) {
78
- continue;
79
- }
80
-
81
- result.push(createNode(SCRIPT, attributes, { textContent }));
195
+ // `nomodule` is preserved even though this element is force-executed via
196
+ // appendChild: without it, a classic script the author intended as a
197
+ // legacy fallback (skipped in module-supporting browsers) would run
198
+ // where it otherwise wouldn't have.
199
+ const nomodule = getAttribute(element, NOMODULE);
200
+ result.push(
201
+ createNode(
202
+ SCRIPT,
203
+ { ...attributes, ...(nomodule !== null && { nomodule }) },
204
+ { textContent },
205
+ ),
206
+ );
82
207
  }
83
208
 
84
209
  return result;
@@ -92,8 +217,7 @@ export const getRemoteScripts = (fragment) => {
92
217
  for (let i = 0; i < length; i += 1) {
93
218
  const element = scripts[i];
94
219
 
95
- // isRemoteScript already requires a non-empty src attribute.
96
- if (!isRemoteScript(element)) {
220
+ if (classifyScript(element) !== HEAD_SCRIPT) {
97
221
  continue;
98
222
  }
99
223