@adobe/alloy 2.24.0 → 2.25.0-beta.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.
Files changed (23) hide show
  1. package/README.md +2 -2
  2. package/libEs5/components/ActivityCollector/configValidators.js +8 -4
  3. package/libEs5/components/ActivityCollector/index.js +2 -0
  4. package/libEs5/components/ActivityCollector/validateClickCollectionConfig.js +43 -0
  5. package/libEs5/components/Personalization/dom-actions/dom/createFragment.js +1 -1
  6. package/libEs5/components/Personalization/handlers/createProcessPropositions.js +4 -3
  7. package/libEs5/constants/libraryVersion.js +1 -1
  8. package/libEs5/core/edgeNetwork/injectSendEdgeNetworkRequest.js +39 -15
  9. package/libEs5/core/injectExecuteCommand.js +14 -1
  10. package/libEs5/{components/Personalization/createPreprocessors.js → utils/networkErrors.js} +13 -10
  11. package/libEs6/components/ActivityCollector/configValidators.js +8 -3
  12. package/libEs6/components/ActivityCollector/index.js +2 -0
  13. package/libEs6/components/ActivityCollector/validateClickCollectionConfig.js +40 -0
  14. package/libEs6/components/Personalization/dom-actions/dom/createFragment.js +1 -1
  15. package/libEs6/components/Personalization/dom-actions/dom/util.js +1 -1
  16. package/libEs6/components/Personalization/handlers/createProcessPropositions.js +4 -3
  17. package/libEs6/constants/libraryVersion.js +1 -1
  18. package/libEs6/core/edgeNetwork/injectSendEdgeNetworkRequest.js +38 -15
  19. package/libEs6/core/injectExecuteCommand.js +14 -1
  20. package/libEs6/{components/Personalization/createPreprocessors.js → utils/networkErrors.js} +11 -8
  21. package/package.json +22 -40
  22. package/libEs5/components/Personalization/createActionsProvider.js +0 -76
  23. package/libEs6/components/Personalization/createActionsProvider.js +0 -72
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![Alloy Main Branch | Konductor Prod](https://github.com/adobe/alloy/workflows/Pre-Deploy/badge.svg)](https://github.com/adobe/alloy/actions)
1
+ ![Alloy Main Branch | Konductor Prod](https://github.com/adobe/alloy/actions/workflows/prod.yml/badge.svg)
2
2
  ![alloy](https://img.shields.io/bundlephobia/min/@adobe/alloy?logo=Adobe&style=for-the-badge)
3
3
  ![alloy](https://img.shields.io/bundlephobia/minzip/@adobe/alloy?logo=Adobe&style=for-the-badge)
4
4
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  Alloy is the code name for the Adobe Experience Platform Web SDK. It allows for recording events into Adobe Experience Platform, syncing identities, personalizing content, and more.
8
8
 
9
- For documentation on how to use Alloy, please see the [user documentation](https://experienceleague.adobe.com/docs/experience-platform/edge/home.html).
9
+ For documentation on how to use Alloy, please see the [user documentation](https://experienceleague.adobe.com/en/docs/experience-platform/web-sdk/home).
10
10
 
11
11
 
12
12
  ## Contribution
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- exports.downloadLinkQualifier = exports.default = void 0;
3
+ exports.downloadLinkQualifier = exports.default = exports.DEFAULT_DOWNLOAD_QUALIFIER = void 0;
4
4
  var _index = require("../../utils/validation/index.js");
5
5
  /*
6
6
  Copyright 2019 Adobe. All rights reserved.
@@ -14,8 +14,9 @@ OF ANY KIND, either express or implied. See the License for the specific languag
14
14
  governing permissions and limitations under the License.
15
15
  */
16
16
 
17
- const downloadLinkQualifier = exports.downloadLinkQualifier = (0, _index.string)().regexp().default("\\.(exe|zip|wav|mp3|mov|mpg|avi|wmv|pdf|doc|docx|xls|xlsx|ppt|pptx)$");
18
- var _default = exports.default = (0, _index.objectOf)({
17
+ const DEFAULT_DOWNLOAD_QUALIFIER = exports.DEFAULT_DOWNLOAD_QUALIFIER = "\\.(exe|zip|wav|mp3|mov|mpg|avi|wmv|pdf|doc|docx|xls|xlsx|ppt|pptx)$";
18
+ const downloadLinkQualifier = exports.downloadLinkQualifier = (0, _index.string)().regexp().default(DEFAULT_DOWNLOAD_QUALIFIER);
19
+ const validators = (0, _index.objectOf)({
19
20
  clickCollectionEnabled: (0, _index.boolean)().default(true),
20
21
  clickCollection: (0, _index.objectOf)({
21
22
  internalLinkEnabled: (0, _index.boolean)().default(true),
@@ -34,4 +35,7 @@ var _default = exports.default = (0, _index.objectOf)({
34
35
  }),
35
36
  downloadLinkQualifier,
36
37
  onBeforeLinkClickSend: (0, _index.callback)().deprecated('The field "onBeforeLinkClickSend" has been deprecated. Use "clickCollection.filterClickDetails" instead.')
37
- });
38
+ });
39
+
40
+ // Export both the validators and the default qualifier
41
+ var _default = exports.default = validators;
@@ -8,6 +8,7 @@ var _createRecallAndInjectClickedElementProperties = require("./createRecallAndI
8
8
  var _createGetClickedElementProperties = require("./createGetClickedElementProperties.js");
9
9
  var _createClickActivityStorage = require("./createClickActivityStorage.js");
10
10
  var _createStorePageViewProperties = require("./createStorePageViewProperties.js");
11
+ var _validateClickCollectionConfig = require("./validateClickCollectionConfig.js");
11
12
  var _getLinkName = require("./getLinkName.js");
12
13
  var _getLinkRegion = require("./getLinkRegion.js");
13
14
  var _getAbsoluteUrlFromAnchorElement = require("./utils/dom/getAbsoluteUrlFromAnchorElement.js");
@@ -55,6 +56,7 @@ const createActivityCollector = ({
55
56
  handleError,
56
57
  logger
57
58
  }) => {
59
+ (0, _validateClickCollectionConfig.default)(config, logger);
58
60
  const clickCollection = config.clickCollection;
59
61
  if (!clickActivityStorage) {
60
62
  initClickActivityStorage(config);
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ exports.default = void 0;
4
+ var _configValidators = require("./configValidators.js");
5
+ /*
6
+ Copyright 2024 Adobe. All rights reserved.
7
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License. You may obtain a copy
9
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software distributed under
12
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
13
+ OF ANY KIND, either express or implied. See the License for the specific language
14
+ governing permissions and limitations under the License.
15
+ */
16
+ // src/components/ActivityCollector/validateClickCollectionConfig.js
17
+ /*
18
+ Copyright 2024 Adobe. All rights reserved.
19
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
20
+ you may not use this file except in compliance with the License. You may obtain a copy
21
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
22
+
23
+ Unless required by applicable law or agreed to in writing, software distributed under
24
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
25
+ OF ANY KIND, either express or implied. See the License for the specific language
26
+ governing permissions and limitations under the License.
27
+ */
28
+ var _default = (config, logger) => {
29
+ const {
30
+ clickCollectionEnabled,
31
+ onBeforeLinkClickSend,
32
+ downloadLinkQualifier: dlq
33
+ } = config;
34
+ if (clickCollectionEnabled === false) {
35
+ if (onBeforeLinkClickSend) {
36
+ logger.warn("The 'onBeforeLinkClickSend' configuration was provided but will be ignored because clickCollectionEnabled is false.");
37
+ }
38
+ if (dlq && dlq !== _configValidators.DEFAULT_DOWNLOAD_QUALIFIER) {
39
+ logger.warn("The 'downloadLinkQualifier' configuration was provided but will be ignored because clickCollectionEnabled is false.");
40
+ }
41
+ }
42
+ };
43
+ exports.default = _default;
@@ -14,7 +14,7 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA
14
14
  OF ANY KIND, either express or implied. See the License for the specific language
15
15
  governing permissions and limitations under the License.
16
16
  */
17
- var _default = content => {
17
+ var _default = (content = "undefined") => {
18
18
  return (0, _index.createNode)(_tagName.DIV, {}, {
19
19
  innerHTML: content
20
20
  });
@@ -42,8 +42,9 @@ var _default = ({
42
42
  return undefined;
43
43
  });
44
44
  };
45
- const renderItems = (renderers, meta) => Promise.all(renderers.map(renderer => renderer())).then(results => {
46
- const successes = results.filter(result => result);
45
+ const renderItems = async (renderers, meta) => {
46
+ const results = await Promise.allSettled(renderers.map(renderer => renderer()));
47
+ const successes = results.filter(result => result.status === "fulfilled").map(result => result.value);
47
48
  // as long as at least one renderer succeeds, we want to add the notification
48
49
  // to the display notifications
49
50
  if (meta && (0, _index.isNonEmptyArray)(successes)) {
@@ -53,7 +54,7 @@ var _default = ({
53
54
  };
54
55
  }
55
56
  return undefined;
56
- });
57
+ };
57
58
  const processItem = item => {
58
59
  const processor = schemaProcessors[item.getSchema()];
59
60
  if (!processor) {
@@ -14,4 +14,4 @@ governing permissions and limitations under the License.
14
14
  */
15
15
  // The __VERSION__ keyword will be replace at alloy build time with the package.json version.
16
16
  // see babel-plugin-version
17
- var _default = exports.default = "2.24.0";
17
+ var _default = exports.default = "2.25.0-beta.0";
@@ -4,6 +4,7 @@ exports.default = void 0;
4
4
  var _domain = require("../../constants/domain.js");
5
5
  var _apiVersion = require("../../constants/apiVersion.js");
6
6
  var _index = require("../../utils/index.js");
7
+ var _networkErrors = require("../../utils/networkErrors.js");
7
8
  var _mergeLifecycleResponses = require("./mergeLifecycleResponses.js");
8
9
  var _handleRequestFailure = require("./handleRequestFailure.js");
9
10
  /*
@@ -17,6 +18,10 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA
17
18
  OF ANY KIND, either express or implied. See the License for the specific language
18
19
  governing permissions and limitations under the License.
19
20
  */
21
+
22
+ const isDemdexBlockedError = (error, request) => {
23
+ return request.getUseIdThirdPartyDomain() && (0, _networkErrors.isNetworkError)(error);
24
+ };
20
25
  var _default = ({
21
26
  config,
22
27
  lifecycle,
@@ -32,6 +37,22 @@ var _default = ({
32
37
  edgeBasePath,
33
38
  datastreamId
34
39
  } = config;
40
+ let hasDemdexFailed = false;
41
+ const buildEndpointUrl = (endpointDomain, request) => {
42
+ const locationHint = getLocationHint();
43
+ const edgeBasePathWithLocationHint = locationHint ? edgeBasePath + "/" + locationHint + request.getEdgeSubPath() : "" + edgeBasePath + request.getEdgeSubPath();
44
+ const configId = request.getDatastreamIdOverride() || datastreamId;
45
+ if (configId !== datastreamId) {
46
+ request.getPayload().mergeMeta({
47
+ sdkConfig: {
48
+ datastream: {
49
+ original: datastreamId
50
+ }
51
+ }
52
+ });
53
+ }
54
+ return "https://" + endpointDomain + "/" + edgeBasePathWithLocationHint + "/" + _apiVersion.default + "/" + request.getAction() + "?configId=" + configId + "&requestId=" + request.getId() + getAssuranceValidationTokenParams();
55
+ };
35
56
 
36
57
  /**
37
58
  * Sends a network request that is aware of payload interfaces,
@@ -53,21 +74,9 @@ var _default = ({
53
74
  onResponse: onResponseCallbackAggregator.add,
54
75
  onRequestFailure: onRequestFailureCallbackAggregator.add
55
76
  }).then(() => {
56
- const endpointDomain = request.getUseIdThirdPartyDomain() ? _domain.ID_THIRD_PARTY : edgeDomain;
57
- const locationHint = getLocationHint();
58
- const edgeBasePathWithLocationHint = locationHint ? edgeBasePath + "/" + locationHint + request.getEdgeSubPath() : "" + edgeBasePath + request.getEdgeSubPath();
59
- const configId = request.getDatastreamIdOverride() || datastreamId;
77
+ const endpointDomain = hasDemdexFailed || !request.getUseIdThirdPartyDomain() ? edgeDomain : _domain.ID_THIRD_PARTY;
78
+ const url = buildEndpointUrl(endpointDomain, request);
60
79
  const payload = request.getPayload();
61
- if (configId !== datastreamId) {
62
- payload.mergeMeta({
63
- sdkConfig: {
64
- datastream: {
65
- original: datastreamId
66
- }
67
- }
68
- });
69
- }
70
- const url = "https://" + endpointDomain + "/" + edgeBasePathWithLocationHint + "/" + _apiVersion.default + "/" + request.getAction() + "?configId=" + configId + "&requestId=" + request.getId() + getAssuranceValidationTokenParams();
71
80
  cookieTransfer.cookiesToPayload(payload, endpointDomain);
72
81
  return sendNetworkRequest({
73
82
  requestId: request.getId(),
@@ -78,7 +87,22 @@ var _default = ({
78
87
  }).then(networkResponse => {
79
88
  processWarningsAndErrors(networkResponse);
80
89
  return networkResponse;
81
- }).catch((0, _handleRequestFailure.default)(onRequestFailureCallbackAggregator)).then(({
90
+ }).catch(error => {
91
+ if (isDemdexBlockedError(error, request)) {
92
+ hasDemdexFailed = true;
93
+ request.setUseIdThirdPartyDomain(false);
94
+ const url = buildEndpointUrl(edgeDomain, request);
95
+ const payload = request.getPayload();
96
+ cookieTransfer.cookiesToPayload(payload, edgeDomain);
97
+ return sendNetworkRequest({
98
+ requestId: request.getId(),
99
+ url,
100
+ payload,
101
+ useSendBeacon: request.getUseSendBeacon()
102
+ });
103
+ }
104
+ return (0, _handleRequestFailure.default)(onRequestFailureCallbackAggregator)(error);
105
+ }).then(({
82
106
  parsedBody,
83
107
  getHeader
84
108
  }) => {
@@ -3,6 +3,7 @@
3
3
  exports.default = void 0;
4
4
  var _index = require("../utils/index.js");
5
5
  var _coreCommands = require("../constants/coreCommands.js");
6
+ var _index2 = require("../utils/validation/index.js");
6
7
  /*
7
8
  Copyright 2019 Adobe. All rights reserved.
8
9
  This file is licensed to you under the Apache License, Version 2.0 (the "License");
@@ -39,7 +40,19 @@ var _default = ({
39
40
  throw new Error("The library must be configured first. Please do so by executing the configure command.");
40
41
  }
41
42
  if (commandName === _coreCommands.SET_DEBUG) {
42
- executor = () => setDebugCommand(options);
43
+ executor = () => {
44
+ const optionsValidator = (0, _index2.objectOf)({
45
+ enabled: (0, _index2.boolean)().required()
46
+ }).noUnknownFields();
47
+ const validatedOptions = validateCommandOptions({
48
+ command: {
49
+ commandName: _coreCommands.SET_DEBUG,
50
+ optionsValidator
51
+ },
52
+ options
53
+ });
54
+ setDebugCommand(validatedOptions);
55
+ };
43
56
  } else {
44
57
  executor = () => {
45
58
  return configurePromise.then(componentRegistry => {
@@ -1,11 +1,8 @@
1
1
  "use strict";
2
2
 
3
- exports.default = void 0;
4
- var _schema = require("../../constants/schema.js");
5
- var _remapHeadOffers = require("./dom-actions/remapHeadOffers.js");
6
- var _remapCustomCodeOffers = require("./dom-actions/remapCustomCodeOffers.js");
3
+ exports.isNetworkError = exports.TYPE_ERROR = exports.NETWORK_ERROR = void 0;
7
4
  /*
8
- Copyright 2023 Adobe. All rights reserved.
5
+ Copyright 2024 Adobe. All rights reserved.
9
6
  This file is licensed to you under the Apache License, Version 2.0 (the "License");
10
7
  you may not use this file except in compliance with the License. You may obtain a copy
11
8
  of the License at http://www.apache.org/licenses/LICENSE-2.0
@@ -15,9 +12,15 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA
15
12
  OF ANY KIND, either express or implied. See the License for the specific language
16
13
  governing permissions and limitations under the License.
17
14
  */
18
- var _default = () => {
19
- return {
20
- [_schema.DOM_ACTION]: [_remapHeadOffers.default, _remapCustomCodeOffers.default]
21
- };
15
+ const TYPE_ERROR = exports.TYPE_ERROR = "TypeError";
16
+ const NETWORK_ERROR = exports.NETWORK_ERROR = "NetworkError";
17
+
18
+ /**
19
+ * Checks if the error is a network-related error
20
+ * @param {Error} error The error to check
21
+ * @returns {boolean} True if the error is network-related
22
+ */
23
+ const isNetworkError = error => {
24
+ return error.name === TYPE_ERROR || error.name === NETWORK_ERROR || error.status === 0;
22
25
  };
23
- exports.default = _default;
26
+ exports.isNetworkError = isNetworkError;
@@ -11,8 +11,9 @@ governing permissions and limitations under the License.
11
11
  */
12
12
 
13
13
  import { boolean, callback, objectOf, string } from "../../utils/validation/index.js";
14
- export const downloadLinkQualifier = string().regexp().default("\\.(exe|zip|wav|mp3|mov|mpg|avi|wmv|pdf|doc|docx|xls|xlsx|ppt|pptx)$");
15
- export default objectOf({
14
+ const DEFAULT_DOWNLOAD_QUALIFIER = "\\.(exe|zip|wav|mp3|mov|mpg|avi|wmv|pdf|doc|docx|xls|xlsx|ppt|pptx)$";
15
+ export const downloadLinkQualifier = string().regexp().default(DEFAULT_DOWNLOAD_QUALIFIER);
16
+ const validators = objectOf({
16
17
  clickCollectionEnabled: boolean().default(true),
17
18
  clickCollection: objectOf({
18
19
  internalLinkEnabled: boolean().default(true),
@@ -31,4 +32,8 @@ export default objectOf({
31
32
  }),
32
33
  downloadLinkQualifier,
33
34
  onBeforeLinkClickSend: callback().deprecated('The field "onBeforeLinkClickSend" has been deprecated. Use "clickCollection.filterClickDetails" instead.')
34
- });
35
+ });
36
+
37
+ // Export both the validators and the default qualifier
38
+ export { DEFAULT_DOWNLOAD_QUALIFIER };
39
+ export default validators;
@@ -17,6 +17,7 @@ import createRecallAndInjectClickedElementProperties from "./createRecallAndInje
17
17
  import createGetClickedElementProperties from "./createGetClickedElementProperties.js";
18
18
  import createClickActivityStorage from "./createClickActivityStorage.js";
19
19
  import createStorePageViewProperties from "./createStorePageViewProperties.js";
20
+ import validateClickCollectionConfig from "./validateClickCollectionConfig.js";
20
21
  import getLinkName from "./getLinkName.js";
21
22
  import getLinkRegion from "./getLinkRegion.js";
22
23
  import getAbsoluteUrlFromAnchorElement from "./utils/dom/getAbsoluteUrlFromAnchorElement.js";
@@ -52,6 +53,7 @@ const createActivityCollector = ({
52
53
  handleError,
53
54
  logger
54
55
  }) => {
56
+ validateClickCollectionConfig(config, logger);
55
57
  const clickCollection = config.clickCollection;
56
58
  if (!clickActivityStorage) {
57
59
  initClickActivityStorage(config);
@@ -0,0 +1,40 @@
1
+ /*
2
+ Copyright 2024 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
+ // src/components/ActivityCollector/validateClickCollectionConfig.js
13
+ /*
14
+ Copyright 2024 Adobe. All rights reserved.
15
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
16
+ you may not use this file except in compliance with the License. You may obtain a copy
17
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
18
+
19
+ Unless required by applicable law or agreed to in writing, software distributed under
20
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
21
+ OF ANY KIND, either express or implied. See the License for the specific language
22
+ governing permissions and limitations under the License.
23
+ */
24
+
25
+ import { DEFAULT_DOWNLOAD_QUALIFIER } from "./configValidators.js";
26
+ export default (config, logger) => {
27
+ const {
28
+ clickCollectionEnabled,
29
+ onBeforeLinkClickSend,
30
+ downloadLinkQualifier: dlq
31
+ } = config;
32
+ if (clickCollectionEnabled === false) {
33
+ if (onBeforeLinkClickSend) {
34
+ logger.warn("The 'onBeforeLinkClickSend' configuration was provided but will be ignored because clickCollectionEnabled is false.");
35
+ }
36
+ if (dlq && dlq !== DEFAULT_DOWNLOAD_QUALIFIER) {
37
+ logger.warn("The 'downloadLinkQualifier' configuration was provided but will be ignored because clickCollectionEnabled is false.");
38
+ }
39
+ }
40
+ };
@@ -12,7 +12,7 @@ governing permissions and limitations under the License.
12
12
 
13
13
  import { createNode } from "../../../../utils/dom/index.js";
14
14
  import { DIV } from "../../../../constants/tagName.js";
15
- export default content => {
15
+ export default (content = "undefined") => {
16
16
  return createNode(DIV, {}, {
17
17
  innerHTML: content
18
18
  });
@@ -11,6 +11,6 @@ governing permissions and limitations under the License.
11
11
  */
12
12
 
13
13
  export const addPxIfMissing = value => {
14
- const hasPx = ("" + value).endsWith("px");
14
+ const hasPx = `${value}`.endsWith("px");
15
15
  return hasPx ? value : `${value}px`;
16
16
  };
@@ -40,8 +40,9 @@ export default ({
40
40
  return undefined;
41
41
  });
42
42
  };
43
- const renderItems = (renderers, meta) => Promise.all(renderers.map(renderer => renderer())).then(results => {
44
- const successes = results.filter(result => result);
43
+ const renderItems = async (renderers, meta) => {
44
+ const results = await Promise.allSettled(renderers.map(renderer => renderer()));
45
+ const successes = results.filter(result => result.status === "fulfilled").map(result => result.value);
45
46
  // as long as at least one renderer succeeds, we want to add the notification
46
47
  // to the display notifications
47
48
  if (meta && isNonEmptyArray(successes)) {
@@ -51,7 +52,7 @@ export default ({
51
52
  };
52
53
  }
53
54
  return undefined;
54
- });
55
+ };
55
56
  const processItem = item => {
56
57
  const processor = schemaProcessors[item.getSchema()];
57
58
  if (!processor) {
@@ -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.24.0";
16
+ export default "2.25.0-beta.0";
@@ -13,8 +13,12 @@ governing permissions and limitations under the License.
13
13
  import { ID_THIRD_PARTY as ID_THIRD_PARTY_DOMAIN } from "../../constants/domain.js";
14
14
  import apiVersion from "../../constants/apiVersion.js";
15
15
  import { createCallbackAggregator, noop } from "../../utils/index.js";
16
+ import { isNetworkError } from "../../utils/networkErrors.js";
16
17
  import mergeLifecycleResponses from "./mergeLifecycleResponses.js";
17
18
  import handleRequestFailure from "./handleRequestFailure.js";
19
+ const isDemdexBlockedError = (error, request) => {
20
+ return request.getUseIdThirdPartyDomain() && isNetworkError(error);
21
+ };
18
22
  export default ({
19
23
  config,
20
24
  lifecycle,
@@ -30,6 +34,22 @@ export default ({
30
34
  edgeBasePath,
31
35
  datastreamId
32
36
  } = config;
37
+ let hasDemdexFailed = false;
38
+ const buildEndpointUrl = (endpointDomain, request) => {
39
+ const locationHint = getLocationHint();
40
+ const edgeBasePathWithLocationHint = locationHint ? `${edgeBasePath}/${locationHint}${request.getEdgeSubPath()}` : `${edgeBasePath}${request.getEdgeSubPath()}`;
41
+ const configId = request.getDatastreamIdOverride() || datastreamId;
42
+ if (configId !== datastreamId) {
43
+ request.getPayload().mergeMeta({
44
+ sdkConfig: {
45
+ datastream: {
46
+ original: datastreamId
47
+ }
48
+ }
49
+ });
50
+ }
51
+ return `https://${endpointDomain}/${edgeBasePathWithLocationHint}/${apiVersion}/${request.getAction()}?configId=${configId}&requestId=${request.getId()}${getAssuranceValidationTokenParams()}`;
52
+ };
33
53
 
34
54
  /**
35
55
  * Sends a network request that is aware of payload interfaces,
@@ -51,21 +71,9 @@ export default ({
51
71
  onResponse: onResponseCallbackAggregator.add,
52
72
  onRequestFailure: onRequestFailureCallbackAggregator.add
53
73
  }).then(() => {
54
- const endpointDomain = request.getUseIdThirdPartyDomain() ? ID_THIRD_PARTY_DOMAIN : edgeDomain;
55
- const locationHint = getLocationHint();
56
- const edgeBasePathWithLocationHint = locationHint ? `${edgeBasePath}/${locationHint}${request.getEdgeSubPath()}` : `${edgeBasePath}${request.getEdgeSubPath()}`;
57
- const configId = request.getDatastreamIdOverride() || datastreamId;
74
+ const endpointDomain = hasDemdexFailed || !request.getUseIdThirdPartyDomain() ? edgeDomain : ID_THIRD_PARTY_DOMAIN;
75
+ const url = buildEndpointUrl(endpointDomain, request);
58
76
  const payload = request.getPayload();
59
- if (configId !== datastreamId) {
60
- payload.mergeMeta({
61
- sdkConfig: {
62
- datastream: {
63
- original: datastreamId
64
- }
65
- }
66
- });
67
- }
68
- const url = `https://${endpointDomain}/${edgeBasePathWithLocationHint}/${apiVersion}/${request.getAction()}?configId=${configId}&requestId=${request.getId()}${getAssuranceValidationTokenParams()}`;
69
77
  cookieTransfer.cookiesToPayload(payload, endpointDomain);
70
78
  return sendNetworkRequest({
71
79
  requestId: request.getId(),
@@ -76,7 +84,22 @@ export default ({
76
84
  }).then(networkResponse => {
77
85
  processWarningsAndErrors(networkResponse);
78
86
  return networkResponse;
79
- }).catch(handleRequestFailure(onRequestFailureCallbackAggregator)).then(({
87
+ }).catch(error => {
88
+ if (isDemdexBlockedError(error, request)) {
89
+ hasDemdexFailed = true;
90
+ request.setUseIdThirdPartyDomain(false);
91
+ const url = buildEndpointUrl(edgeDomain, request);
92
+ const payload = request.getPayload();
93
+ cookieTransfer.cookiesToPayload(payload, edgeDomain);
94
+ return sendNetworkRequest({
95
+ requestId: request.getId(),
96
+ url,
97
+ payload,
98
+ useSendBeacon: request.getUseSendBeacon()
99
+ });
100
+ }
101
+ return handleRequestFailure(onRequestFailureCallbackAggregator)(error);
102
+ }).then(({
80
103
  parsedBody,
81
104
  getHeader
82
105
  }) => {
@@ -12,6 +12,7 @@ governing permissions and limitations under the License.
12
12
 
13
13
  import { isFunction, isObject } from "../utils/index.js";
14
14
  import { CONFIGURE, SET_DEBUG } from "../constants/coreCommands.js";
15
+ import { objectOf, boolean } from "../utils/validation/index.js";
15
16
  export default ({
16
17
  logger,
17
18
  configureCommand,
@@ -37,7 +38,19 @@ export default ({
37
38
  throw new Error(`The library must be configured first. Please do so by executing the configure command.`);
38
39
  }
39
40
  if (commandName === SET_DEBUG) {
40
- executor = () => setDebugCommand(options);
41
+ executor = () => {
42
+ const optionsValidator = objectOf({
43
+ enabled: boolean().required()
44
+ }).noUnknownFields();
45
+ const validatedOptions = validateCommandOptions({
46
+ command: {
47
+ commandName: SET_DEBUG,
48
+ optionsValidator
49
+ },
50
+ options
51
+ });
52
+ setDebugCommand(validatedOptions);
53
+ };
41
54
  } else {
42
55
  executor = () => {
43
56
  return configurePromise.then(componentRegistry => {
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright 2023 Adobe. All rights reserved.
2
+ Copyright 2024 Adobe. All rights reserved.
3
3
  This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License. You may obtain a copy
5
5
  of the License at http://www.apache.org/licenses/LICENSE-2.0
@@ -9,11 +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 { DOM_ACTION } from "../../constants/schema.js";
13
- import remapHeadOffers from "./dom-actions/remapHeadOffers.js";
14
- import remapCustomCodeOffers from "./dom-actions/remapCustomCodeOffers.js";
15
- export default () => {
16
- return {
17
- [DOM_ACTION]: [remapHeadOffers, remapCustomCodeOffers]
18
- };
12
+ export const TYPE_ERROR = "TypeError";
13
+ export const NETWORK_ERROR = "NetworkError";
14
+
15
+ /**
16
+ * Checks if the error is a network-related error
17
+ * @param {Error} error The error to check
18
+ * @returns {boolean} True if the error is network-related
19
+ */
20
+ export const isNetworkError = error => {
21
+ return error.name === TYPE_ERROR || error.name === NETWORK_ERROR || error.status === 0;
19
22
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/alloy",
3
- "version": "2.24.0",
3
+ "version": "2.25.0-beta.0",
4
4
  "description": "Adobe Experience Platform Web SDK",
5
5
  "type": "module",
6
6
  "main": "libEs5/index.js",
@@ -21,20 +21,18 @@
21
21
  "clean": "rimraf dist distTest libEs5 libEs6",
22
22
  "lint": "eslint --cache --fix \"*.{js,cjs,mjs,jsx}\" \"{src,test,scripts}/**/*.{js,cjs,mjs,jsx}\"",
23
23
  "format": "prettier --write \"*.{html,js,cjs,mjs,jsx}\" \"{sandbox,src,test,scripts}/**/*.{html,js,cjs,mjs,jsx}\"",
24
- "test": "npm run test:unit && npm run test:scripts && npm run test:functional",
25
- "test:unit": "karma start karma.conf.cjs --single-run",
26
- "test:unit:debug": "karma start karma.conf.cjs --browsers=Chrome --single-run=false --debug",
27
- "test:unit:watch": "karma start",
28
- "test:unit:saucelabs:local": "karma start karma.saucelabs.conf.cjs --single-run",
29
- "test:unit:coverage": "karma start --single-run --reporters spec,coverage",
24
+ "test": "npm run test:unit && npm run test:scripts",
25
+ "test:unit": "vitest run",
26
+ "test:unit:debug": "vitest --no-file-parallelism --browser.headless=false",
27
+ "test:unit:watch": "vitest",
28
+ "test:unit:coverage": "vitest run --coverage",
30
29
  "test:functional": "EDGE_BASE_PATH=\"ee-pre-prd\" ALLOY_ENV=\"int\" testcafe chrome",
31
30
  "test:functional:custom": "node scripts/helpers/runFunctionalTests.js",
32
- "test:functional:saucelabs:dev": "NPM_PACKAGE_VERSION=$(npm pkg get version | tr -d '\"') EDGE_BASE_PATH=\"ee-pre-prd\" ALLOY_ENV=\"int\" saucectl run --config ./.sauce/dev.yml",
33
31
  "test:functional:watch": "EDGE_BASE_PATH=\"ee-pre-prd\" ALLOY_ENV=\"int\" ./scripts/watchFunctionalTests.js --browsers chrome",
34
32
  "test:functional:debug": "EDGE_BASE_PATH=\"ee-pre-prd\" ALLOY_ENV=\"int\" testcafe --inspect-brk chrome",
35
33
  "test:functional:build:int": "rollup -c --environment BASE_CODE_MIN,STANDALONE,NPM_PACKAGE_LOCAL",
36
34
  "test:functional:build:prod": "rollup -c --environment BASE_CODE_MIN,NPM_PACKAGE_PROD",
37
- "test:scripts": "jasmine --config=scripts/specs/jasmine.json",
35
+ "test:scripts": "vitest run --config=./scripts/specs/vitest.config.js",
38
36
  "sandbox:build": "rollup -c --environment SANDBOX && cd sandbox && npm run build",
39
37
  "dev": "concurrently --names build,sandbox \"rollup -c -w --environment SANDBOX\" \"cd sandbox && export REACT_APP_NONCE=321 && npm start\"",
40
38
  "dev:standalone": "npm run clean && rollup -c -w --environment STANDALONE",
@@ -43,7 +41,8 @@
43
41
  "prepare": "husky && cd sandbox && npm install",
44
42
  "prepack": "rimraf libEs5 libEs6 && babel src -d libEs5 --env-name npmEs5 && babel src -d libEs6 --env-name npmEs6",
45
43
  "checkthattestfilesexist": "./scripts/checkThatTestFilesExist.js",
46
- "add-license": "./scripts/add-license.js"
44
+ "add-license": "./scripts/add-license.js",
45
+ "postinstall": "npx playwright install chromium"
47
46
  },
48
47
  "lint-staged": {
49
48
  "./*.{cjs,mjs,js,jsx}": [
@@ -89,20 +88,21 @@
89
88
  "css.escape": "^1.5.1",
90
89
  "js-cookie": "3.0.5",
91
90
  "parse-uri": "^1.0.9",
92
- "rollup": "^4.24.2",
91
+ "rollup": "^4.24.4",
93
92
  "rollup-plugin-license": "^3.5.3",
94
- "uuid": "^11.0.1"
93
+ "uuid": "^11.0.2"
95
94
  },
96
95
  "devDependencies": {
97
96
  "@adobe/alloy": "^2.24.0-beta.2",
98
97
  "@babel/cli": "^7.25.9",
99
98
  "@babel/plugin-transform-runtime": "^7.25.9",
100
- "@eslint/js": "^9.13.0",
99
+ "@eslint/js": "^9.14.0",
101
100
  "@octokit/rest": "^21.0.2",
101
+ "@vitest/browser": "^2.1.8",
102
+ "@vitest/coverage-v8": "^2.1.8",
102
103
  "bundlesize": "^0.18.2",
103
- "chai": "^5.1.2",
104
104
  "chalk": "^5.3.0",
105
- "concurrently": "^9.0.1",
105
+ "concurrently": "^9.1.0",
106
106
  "date-fns": "^4.1.0",
107
107
  "dotenv": "^16.4.5",
108
108
  "eslint": "^8.57.0",
@@ -113,24 +113,12 @@
113
113
  "eslint-plugin-prettier": "^5.2.1",
114
114
  "eslint-plugin-testcafe": "^0.2.1",
115
115
  "glob": "^11.0.0",
116
- "globals": "^15.11.0",
116
+ "globals": "^15.12.0",
117
117
  "handlebars": "^4.7.8",
118
+ "happy-dom": "^15.11.1",
118
119
  "husky": "^9.1.6",
119
- "jasmine": "^5.4.0",
120
- "jasmine-core": "^5.4.0",
121
- "karma": "^6.4.4",
122
- "karma-chrome-launcher": "^3.2.0",
123
- "karma-coverage": "^2.2.1",
124
- "karma-firefox-launcher": "^2.1.3",
125
- "karma-jasmine": "^5.1.0",
126
- "karma-jasmine-html-reporter": "^2.1.0",
127
- "karma-jasmine-matchers": "^5.0.0",
128
- "karma-junit-reporter": "^2.0.1",
129
- "karma-rollup-preprocessor": "^7.0.8",
130
- "karma-safari-launcher": "^1.0.0",
131
- "karma-sauce-launcher": "^4.3.6",
132
- "karma-spec-reporter": "0.0.36",
133
120
  "lint-staged": "^15.2.10",
121
+ "playwright": "^1.49.1",
134
122
  "prettier": "^3.3.3",
135
123
  "read-cache": "^1.0.0",
136
124
  "recursive-readdir": "^2.2.3",
@@ -141,19 +129,13 @@
141
129
  "semver": "^7.6.3",
142
130
  "staged-git-files": "^1.3.0",
143
131
  "start-server-and-test": "^2.0.8",
144
- "testcafe": "^3.6.2",
145
- "testcafe-browser-provider-saucelabs": "^3.0.0",
132
+ "testcafe": "^3.7.0",
146
133
  "testcafe-reporter-junit": "^3.0.2",
147
- "testcafe-reporter-saucelabs": "^3.5.1",
148
134
  "url-exists-nodejs": "^0.2.4",
149
- "url-parse": "^1.5.10"
150
- },
151
- "overrides": {
152
- "karma-sauce-launcher": {
153
- "webdriverio": "^8.35.1"
154
- }
135
+ "url-parse": "^1.5.10",
136
+ "vitest": "^2.1.4"
155
137
  },
156
138
  "optionalDependencies": {
157
- "@rollup/rollup-linux-x64-gnu": "^4.24.2"
139
+ "@rollup/rollup-linux-x64-gnu": "^4.24.4"
158
140
  }
159
141
  }
@@ -1,76 +0,0 @@
1
- "use strict";
2
-
3
- exports.default = void 0;
4
- var _createPreprocessors = require("./createPreprocessors.js");
5
- /*
6
- Copyright 2023 Adobe. All rights reserved.
7
- This file is licensed to you under the Apache License, Version 2.0 (the "License");
8
- you may not use this file except in compliance with the License. You may obtain a copy
9
- of the License at http://www.apache.org/licenses/LICENSE-2.0
10
-
11
- Unless required by applicable law or agreed to in writing, software distributed under
12
- the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
13
- OF ANY KIND, either express or implied. See the License for the specific language
14
- governing permissions and limitations under the License.
15
- */
16
- var _default = ({
17
- modules,
18
- preprocessors = (0, _createPreprocessors.default)(),
19
- logger
20
- }) => {
21
- const logActionError = (action, error) => {
22
- if (logger.enabled) {
23
- const details = JSON.stringify(action);
24
- const {
25
- message,
26
- stack
27
- } = error;
28
- const errorMessage = "Failed to execute action " + details + ". " + message + " " + (stack ? "\n " + stack : "");
29
- logger.warn(errorMessage);
30
- }
31
- };
32
- const logActionCompleted = action => {
33
- if (logger.enabled) {
34
- const details = JSON.stringify(action);
35
- logger.info("Action " + details + " executed.");
36
- }
37
- };
38
- const getExecuteAction = (schema, type) => {
39
- if (!modules[schema] || !modules[schema][type]) {
40
- return () => Promise.reject(new Error("Action \"" + type + "\" not found for schema \"" + schema + "\""));
41
- }
42
- return modules[schema][type];
43
- };
44
- const applyPreprocessors = action => {
45
- const {
46
- schema
47
- } = action;
48
- const preprocessorsList = preprocessors[schema];
49
- if (!schema || !(preprocessorsList instanceof Array) || preprocessorsList.length === 0) {
50
- return action;
51
- }
52
- return preprocessorsList.reduce((processed, fn) => ({
53
- ...processed,
54
- ...fn(processed)
55
- }), action);
56
- };
57
- const executeAction = action => {
58
- const processedAction = applyPreprocessors(action);
59
- const {
60
- type,
61
- schema
62
- } = processedAction;
63
- const execute = getExecuteAction(schema, type);
64
- return execute(processedAction).then(result => {
65
- logActionCompleted(processedAction);
66
- return result;
67
- }).catch(error => {
68
- logActionError(processedAction, error);
69
- throw error;
70
- });
71
- };
72
- return {
73
- executeAction
74
- };
75
- };
76
- exports.default = _default;
@@ -1,72 +0,0 @@
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
- import createPreprocessors from "./createPreprocessors.js";
13
- export default ({
14
- modules,
15
- preprocessors = createPreprocessors(),
16
- logger
17
- }) => {
18
- const logActionError = (action, error) => {
19
- if (logger.enabled) {
20
- const details = JSON.stringify(action);
21
- const {
22
- message,
23
- stack
24
- } = error;
25
- const errorMessage = `Failed to execute action ${details}. ${message} ${stack ? `\n ${stack}` : ""}`;
26
- logger.warn(errorMessage);
27
- }
28
- };
29
- const logActionCompleted = action => {
30
- if (logger.enabled) {
31
- const details = JSON.stringify(action);
32
- logger.info(`Action ${details} executed.`);
33
- }
34
- };
35
- const getExecuteAction = (schema, type) => {
36
- if (!modules[schema] || !modules[schema][type]) {
37
- return () => Promise.reject(new Error(`Action "${type}" not found for schema "${schema}"`));
38
- }
39
- return modules[schema][type];
40
- };
41
- const applyPreprocessors = action => {
42
- const {
43
- schema
44
- } = action;
45
- const preprocessorsList = preprocessors[schema];
46
- if (!schema || !(preprocessorsList instanceof Array) || preprocessorsList.length === 0) {
47
- return action;
48
- }
49
- return preprocessorsList.reduce((processed, fn) => ({
50
- ...processed,
51
- ...fn(processed)
52
- }), action);
53
- };
54
- const executeAction = action => {
55
- const processedAction = applyPreprocessors(action);
56
- const {
57
- type,
58
- schema
59
- } = processedAction;
60
- const execute = getExecuteAction(schema, type);
61
- return execute(processedAction).then(result => {
62
- logActionCompleted(processedAction);
63
- return result;
64
- }).catch(error => {
65
- logActionError(processedAction, error);
66
- throw error;
67
- });
68
- };
69
- return {
70
- executeAction
71
- };
72
- };