personalize-connect-sdk 1.2.0 → 1.2.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.
- package/dist/index.d.mts +20 -9
- package/dist/index.d.ts +20 -9
- package/dist/index.js +236 -43
- package/dist/index.mjs +234 -43
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -63,6 +63,8 @@ interface PersonalizeConnectProviderProps {
|
|
|
63
63
|
resolveDatasource?: (datasourceId: string) => Promise<ComponentFields>;
|
|
64
64
|
/** Override editing mode detection. When true the HOC renders a visual indicator. */
|
|
65
65
|
isEditing?: boolean;
|
|
66
|
+
/** Enable debug logging to the browser console. */
|
|
67
|
+
debug?: boolean;
|
|
66
68
|
children: ReactNode;
|
|
67
69
|
}
|
|
68
70
|
/** Resolved datasource fields passed as component props */
|
|
@@ -88,7 +90,7 @@ interface PersonalizeContextValue {
|
|
|
88
90
|
siteName: string;
|
|
89
91
|
}
|
|
90
92
|
|
|
91
|
-
declare function PersonalizeProvider({ children, sitecoreEdgeContextId, sitecoreEdgeUrl, siteName, clientKey, pointOfSale, edgeUrl, apiKey, channel, language, currencyCode, timeout, resolveDatasource, isEditing: isEditingProp, }: PersonalizeConnectProviderProps): react_jsx_runtime.JSX.Element;
|
|
93
|
+
declare function PersonalizeProvider({ children, sitecoreEdgeContextId, sitecoreEdgeUrl, siteName, clientKey, pointOfSale, edgeUrl, apiKey, channel, language, currencyCode, timeout, resolveDatasource, isEditing: isEditingProp, debug, }: PersonalizeConnectProviderProps): react_jsx_runtime.JSX.Element;
|
|
92
94
|
declare function usePersonalizeContext(): PersonalizeContextValue | null;
|
|
93
95
|
|
|
94
96
|
/**
|
|
@@ -131,13 +133,13 @@ declare function resolveContent(options: ResolveContentOptions): Promise<Resolve
|
|
|
131
133
|
|
|
132
134
|
type GetConfigFromProps<P> = (props: P) => PersonalizeConnectConfig | undefined;
|
|
133
135
|
/**
|
|
134
|
-
* HOC that wraps any JSS
|
|
136
|
+
* HOC that wraps any JSS component.
|
|
135
137
|
* If the rendering has a personalizeConnect config, it renders with defaultKey first,
|
|
136
138
|
* then asynchronously fetches the personalized content and re-renders.
|
|
137
139
|
* If no config, passes through unchanged.
|
|
138
140
|
*
|
|
139
|
-
* In
|
|
140
|
-
*
|
|
141
|
+
* In Page Builder, renders a visual indicator (border + badge) on
|
|
142
|
+
* components that have personalization configured.
|
|
141
143
|
*/
|
|
142
144
|
declare function withPersonalizeConnect<P extends object>(WrappedComponent: ComponentType<P>, getConfig?: GetConfigFromProps<P>): ComponentType<P>;
|
|
143
145
|
|
|
@@ -171,17 +173,26 @@ declare function createEdgeResolver(edgeUrl: string, apiKey: string, language?:
|
|
|
171
173
|
declare function createEdgeProxyResolver(edgeBaseUrl: string, contextId: string, language?: string): (datasourceId: string) => Promise<ComponentFields>;
|
|
172
174
|
|
|
173
175
|
/**
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
+
* XM Cloud Pages (Page Builder) editing mode detection.
|
|
177
|
+
* Uses the same Sitecore context shape that JSS for XMC writes to __NEXT_DATA__.
|
|
176
178
|
*/
|
|
177
179
|
/**
|
|
178
|
-
* Detects whether the page is
|
|
179
|
-
*
|
|
180
|
+
* Detects whether the page is rendered inside XM Cloud Pages (Page Builder).
|
|
181
|
+
* Checks the JSS Sitecore context for pageEditing / pageState, and whether
|
|
182
|
+
* the rendering host is loaded in an iframe (Pages always iframes the site).
|
|
183
|
+
* Result is cached after the first call.
|
|
180
184
|
*/
|
|
181
185
|
declare function isEditingMode(): boolean;
|
|
182
186
|
/** Reset the cached result (useful for testing). */
|
|
183
187
|
declare function resetEditingDetectionCache(): void;
|
|
184
188
|
|
|
189
|
+
/**
|
|
190
|
+
* SDK debug logger. All output is prefixed with [PersonalizeConnect].
|
|
191
|
+
* Enable by passing debug={true} on PersonalizeProvider.
|
|
192
|
+
*/
|
|
193
|
+
declare function setDebug(on: boolean): void;
|
|
194
|
+
declare function isDebugEnabled(): boolean;
|
|
195
|
+
|
|
185
196
|
/**
|
|
186
197
|
* Manages the Sitecore CDP browser ID.
|
|
187
198
|
*
|
|
@@ -205,4 +216,4 @@ declare function getEdgeBrowserId(edgeUrl: string, contextId: string, siteName:
|
|
|
205
216
|
/** Reset the cached init promise (for testing). */
|
|
206
217
|
declare function resetEdgeInitCache(): void;
|
|
207
218
|
|
|
208
|
-
export { type CallFlowsRequest, type CallPersonalizeOptions, type ComponentFields, type EdgeInitResponse, type GetConfigFromProps, type PersonalizeConnectConfig, type PersonalizeConnectProviderProps, type PersonalizeConnectResponse, type PersonalizeContextValue, PersonalizeProvider, type ResolveContentOptions, type ResolvedContent, type UsePersonalizeExperienceResult, callPersonalize, createEdgeProxyResolver, createEdgeResolver, getBrowserId, getEdgeBrowserId, isEditingMode, resetEdgeInitCache, resetEditingDetectionCache, resolveContent, usePersonalizeContext, usePersonalizeExperience, withPersonalizeConnect };
|
|
219
|
+
export { type CallFlowsRequest, type CallPersonalizeOptions, type ComponentFields, type EdgeInitResponse, type GetConfigFromProps, type PersonalizeConnectConfig, type PersonalizeConnectProviderProps, type PersonalizeConnectResponse, type PersonalizeContextValue, PersonalizeProvider, type ResolveContentOptions, type ResolvedContent, type UsePersonalizeExperienceResult, callPersonalize, createEdgeProxyResolver, createEdgeResolver, getBrowserId, getEdgeBrowserId, isDebugEnabled, isEditingMode, resetEdgeInitCache, resetEditingDetectionCache, resolveContent, setDebug, usePersonalizeContext, usePersonalizeExperience, withPersonalizeConnect };
|
package/dist/index.d.ts
CHANGED
|
@@ -63,6 +63,8 @@ interface PersonalizeConnectProviderProps {
|
|
|
63
63
|
resolveDatasource?: (datasourceId: string) => Promise<ComponentFields>;
|
|
64
64
|
/** Override editing mode detection. When true the HOC renders a visual indicator. */
|
|
65
65
|
isEditing?: boolean;
|
|
66
|
+
/** Enable debug logging to the browser console. */
|
|
67
|
+
debug?: boolean;
|
|
66
68
|
children: ReactNode;
|
|
67
69
|
}
|
|
68
70
|
/** Resolved datasource fields passed as component props */
|
|
@@ -88,7 +90,7 @@ interface PersonalizeContextValue {
|
|
|
88
90
|
siteName: string;
|
|
89
91
|
}
|
|
90
92
|
|
|
91
|
-
declare function PersonalizeProvider({ children, sitecoreEdgeContextId, sitecoreEdgeUrl, siteName, clientKey, pointOfSale, edgeUrl, apiKey, channel, language, currencyCode, timeout, resolveDatasource, isEditing: isEditingProp, }: PersonalizeConnectProviderProps): react_jsx_runtime.JSX.Element;
|
|
93
|
+
declare function PersonalizeProvider({ children, sitecoreEdgeContextId, sitecoreEdgeUrl, siteName, clientKey, pointOfSale, edgeUrl, apiKey, channel, language, currencyCode, timeout, resolveDatasource, isEditing: isEditingProp, debug, }: PersonalizeConnectProviderProps): react_jsx_runtime.JSX.Element;
|
|
92
94
|
declare function usePersonalizeContext(): PersonalizeContextValue | null;
|
|
93
95
|
|
|
94
96
|
/**
|
|
@@ -131,13 +133,13 @@ declare function resolveContent(options: ResolveContentOptions): Promise<Resolve
|
|
|
131
133
|
|
|
132
134
|
type GetConfigFromProps<P> = (props: P) => PersonalizeConnectConfig | undefined;
|
|
133
135
|
/**
|
|
134
|
-
* HOC that wraps any JSS
|
|
136
|
+
* HOC that wraps any JSS component.
|
|
135
137
|
* If the rendering has a personalizeConnect config, it renders with defaultKey first,
|
|
136
138
|
* then asynchronously fetches the personalized content and re-renders.
|
|
137
139
|
* If no config, passes through unchanged.
|
|
138
140
|
*
|
|
139
|
-
* In
|
|
140
|
-
*
|
|
141
|
+
* In Page Builder, renders a visual indicator (border + badge) on
|
|
142
|
+
* components that have personalization configured.
|
|
141
143
|
*/
|
|
142
144
|
declare function withPersonalizeConnect<P extends object>(WrappedComponent: ComponentType<P>, getConfig?: GetConfigFromProps<P>): ComponentType<P>;
|
|
143
145
|
|
|
@@ -171,17 +173,26 @@ declare function createEdgeResolver(edgeUrl: string, apiKey: string, language?:
|
|
|
171
173
|
declare function createEdgeProxyResolver(edgeBaseUrl: string, contextId: string, language?: string): (datasourceId: string) => Promise<ComponentFields>;
|
|
172
174
|
|
|
173
175
|
/**
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
+
* XM Cloud Pages (Page Builder) editing mode detection.
|
|
177
|
+
* Uses the same Sitecore context shape that JSS for XMC writes to __NEXT_DATA__.
|
|
176
178
|
*/
|
|
177
179
|
/**
|
|
178
|
-
* Detects whether the page is
|
|
179
|
-
*
|
|
180
|
+
* Detects whether the page is rendered inside XM Cloud Pages (Page Builder).
|
|
181
|
+
* Checks the JSS Sitecore context for pageEditing / pageState, and whether
|
|
182
|
+
* the rendering host is loaded in an iframe (Pages always iframes the site).
|
|
183
|
+
* Result is cached after the first call.
|
|
180
184
|
*/
|
|
181
185
|
declare function isEditingMode(): boolean;
|
|
182
186
|
/** Reset the cached result (useful for testing). */
|
|
183
187
|
declare function resetEditingDetectionCache(): void;
|
|
184
188
|
|
|
189
|
+
/**
|
|
190
|
+
* SDK debug logger. All output is prefixed with [PersonalizeConnect].
|
|
191
|
+
* Enable by passing debug={true} on PersonalizeProvider.
|
|
192
|
+
*/
|
|
193
|
+
declare function setDebug(on: boolean): void;
|
|
194
|
+
declare function isDebugEnabled(): boolean;
|
|
195
|
+
|
|
185
196
|
/**
|
|
186
197
|
* Manages the Sitecore CDP browser ID.
|
|
187
198
|
*
|
|
@@ -205,4 +216,4 @@ declare function getEdgeBrowserId(edgeUrl: string, contextId: string, siteName:
|
|
|
205
216
|
/** Reset the cached init promise (for testing). */
|
|
206
217
|
declare function resetEdgeInitCache(): void;
|
|
207
218
|
|
|
208
|
-
export { type CallFlowsRequest, type CallPersonalizeOptions, type ComponentFields, type EdgeInitResponse, type GetConfigFromProps, type PersonalizeConnectConfig, type PersonalizeConnectProviderProps, type PersonalizeConnectResponse, type PersonalizeContextValue, PersonalizeProvider, type ResolveContentOptions, type ResolvedContent, type UsePersonalizeExperienceResult, callPersonalize, createEdgeProxyResolver, createEdgeResolver, getBrowserId, getEdgeBrowserId, isEditingMode, resetEdgeInitCache, resetEditingDetectionCache, resolveContent, usePersonalizeContext, usePersonalizeExperience, withPersonalizeConnect };
|
|
219
|
+
export { type CallFlowsRequest, type CallPersonalizeOptions, type ComponentFields, type EdgeInitResponse, type GetConfigFromProps, type PersonalizeConnectConfig, type PersonalizeConnectProviderProps, type PersonalizeConnectResponse, type PersonalizeContextValue, PersonalizeProvider, type ResolveContentOptions, type ResolvedContent, type UsePersonalizeExperienceResult, callPersonalize, createEdgeProxyResolver, createEdgeResolver, getBrowserId, getEdgeBrowserId, isDebugEnabled, isEditingMode, resetEdgeInitCache, resetEditingDetectionCache, resolveContent, setDebug, usePersonalizeContext, usePersonalizeExperience, withPersonalizeConnect };
|
package/dist/index.js
CHANGED
|
@@ -26,10 +26,12 @@ __export(index_exports, {
|
|
|
26
26
|
createEdgeResolver: () => createEdgeResolver,
|
|
27
27
|
getBrowserId: () => getBrowserId,
|
|
28
28
|
getEdgeBrowserId: () => getEdgeBrowserId,
|
|
29
|
+
isDebugEnabled: () => isDebugEnabled,
|
|
29
30
|
isEditingMode: () => isEditingMode,
|
|
30
31
|
resetEdgeInitCache: () => resetEdgeInitCache,
|
|
31
32
|
resetEditingDetectionCache: () => resetEditingDetectionCache,
|
|
32
33
|
resolveContent: () => resolveContent,
|
|
34
|
+
setDebug: () => setDebug,
|
|
33
35
|
usePersonalizeContext: () => usePersonalizeContext,
|
|
34
36
|
usePersonalizeExperience: () => usePersonalizeExperience,
|
|
35
37
|
withPersonalizeConnect: () => withPersonalizeConnect
|
|
@@ -39,6 +41,31 @@ module.exports = __toCommonJS(index_exports);
|
|
|
39
41
|
// src/PersonalizeProvider.tsx
|
|
40
42
|
var import_react = require("react");
|
|
41
43
|
|
|
44
|
+
// src/logger.ts
|
|
45
|
+
var PREFIX = "[PersonalizeConnect]";
|
|
46
|
+
var enabled = false;
|
|
47
|
+
function setDebug(on) {
|
|
48
|
+
enabled = on;
|
|
49
|
+
}
|
|
50
|
+
function isDebugEnabled() {
|
|
51
|
+
return enabled;
|
|
52
|
+
}
|
|
53
|
+
function log(...args) {
|
|
54
|
+
if (enabled) console.log(PREFIX, ...args);
|
|
55
|
+
}
|
|
56
|
+
function warn(...args) {
|
|
57
|
+
if (enabled) console.warn(PREFIX, ...args);
|
|
58
|
+
}
|
|
59
|
+
function error(...args) {
|
|
60
|
+
if (enabled) console.error(PREFIX, ...args);
|
|
61
|
+
}
|
|
62
|
+
function group(label) {
|
|
63
|
+
if (enabled) console.groupCollapsed(`${PREFIX} ${label}`);
|
|
64
|
+
}
|
|
65
|
+
function groupEnd() {
|
|
66
|
+
if (enabled) console.groupEnd();
|
|
67
|
+
}
|
|
68
|
+
|
|
42
69
|
// src/browserId.ts
|
|
43
70
|
var LEGACY_COOKIE_PREFIX = "bid_";
|
|
44
71
|
var CONTEXT_COOKIE_PREFIX = "sc_";
|
|
@@ -71,6 +98,9 @@ function getBrowserId(clientKey) {
|
|
|
71
98
|
if (!bid || typeof bid !== "string" || bid.length < 10) {
|
|
72
99
|
bid = generateBrowserId();
|
|
73
100
|
setCookie(cookieName, bid);
|
|
101
|
+
log("BrowserId (legacy): generated new", bid, `cookie=${cookieName}`);
|
|
102
|
+
} else {
|
|
103
|
+
log("BrowserId (legacy): from cookie", bid, `cookie=${cookieName}`);
|
|
74
104
|
}
|
|
75
105
|
return bid;
|
|
76
106
|
}
|
|
@@ -78,15 +108,21 @@ var edgeInitPromise = null;
|
|
|
78
108
|
async function getEdgeBrowserId(edgeUrl, contextId, siteName) {
|
|
79
109
|
const cookieName = CONTEXT_COOKIE_PREFIX + contextId + CONTEXT_COOKIE_SUFFIX;
|
|
80
110
|
const cached = getCookie(cookieName);
|
|
81
|
-
if (cached && cached.length >= 10)
|
|
111
|
+
if (cached && cached.length >= 10) {
|
|
112
|
+
log("BrowserId (edge): from cookie", cached, `cookie=${cookieName}`);
|
|
113
|
+
return cached;
|
|
114
|
+
}
|
|
115
|
+
log("BrowserId (edge): cookie miss, calling /v1/init", { edgeUrl, contextId, siteName });
|
|
82
116
|
if (!edgeInitPromise) {
|
|
83
117
|
edgeInitPromise = fetchEdgeInit(edgeUrl, contextId, siteName);
|
|
84
118
|
}
|
|
85
119
|
try {
|
|
86
120
|
const result = await edgeInitPromise;
|
|
121
|
+
log("BrowserId (edge): init returned", result);
|
|
87
122
|
setCookie(cookieName, result.browserId);
|
|
88
123
|
return result.browserId;
|
|
89
|
-
} catch {
|
|
124
|
+
} catch (e) {
|
|
125
|
+
warn("BrowserId (edge): init failed, generating fallback", e);
|
|
90
126
|
const fallback = generateBrowserId();
|
|
91
127
|
setCookie(cookieName, fallback);
|
|
92
128
|
return fallback;
|
|
@@ -97,12 +133,17 @@ async function getEdgeBrowserId(edgeUrl, contextId, siteName) {
|
|
|
97
133
|
async function fetchEdgeInit(edgeUrl, contextId, siteName) {
|
|
98
134
|
const base = edgeUrl.replace(/\/$/, "");
|
|
99
135
|
const url = `${base}/v1/init?sitecoreContextId=${encodeURIComponent(contextId)}&siteName=${encodeURIComponent(siteName)}`;
|
|
136
|
+
log("BrowserId (edge): GET", url);
|
|
100
137
|
const res = await fetch(url, { method: "GET" });
|
|
138
|
+
log("BrowserId (edge): init response status:", res.status);
|
|
101
139
|
if (!res.ok) {
|
|
140
|
+
const text = await res.text().catch(() => "");
|
|
141
|
+
error("BrowserId (edge): init non-OK:", res.status, text);
|
|
102
142
|
throw new Error(`Edge init failed: ${res.status}`);
|
|
103
143
|
}
|
|
104
144
|
const data = await res.json();
|
|
105
145
|
if (!data.browserId || typeof data.browserId !== "string") {
|
|
146
|
+
error("BrowserId (edge): init response missing browserId", data);
|
|
106
147
|
throw new Error("Edge init response missing browserId");
|
|
107
148
|
}
|
|
108
149
|
return data;
|
|
@@ -132,6 +173,7 @@ function mapFields(fields) {
|
|
|
132
173
|
return result;
|
|
133
174
|
}
|
|
134
175
|
async function queryEdge(url, headers, datasourceId, language) {
|
|
176
|
+
log("Edge GraphQL request:", { url, datasourceId, language });
|
|
135
177
|
const res = await fetch(url, {
|
|
136
178
|
method: "POST",
|
|
137
179
|
headers: { "Content-Type": "application/json", ...headers },
|
|
@@ -140,16 +182,26 @@ async function queryEdge(url, headers, datasourceId, language) {
|
|
|
140
182
|
variables: { itemId: datasourceId, language }
|
|
141
183
|
})
|
|
142
184
|
});
|
|
185
|
+
log("Edge GraphQL response status:", res.status);
|
|
143
186
|
if (!res.ok) {
|
|
187
|
+
const text = await res.text().catch(() => "");
|
|
188
|
+
error("Edge GraphQL non-OK response:", res.status, text);
|
|
144
189
|
throw new Error(`Experience Edge request failed: ${res.status}`);
|
|
145
190
|
}
|
|
146
191
|
const json = await res.json();
|
|
147
192
|
if (json.errors?.length) {
|
|
148
|
-
|
|
193
|
+
const msg = json.errors.map((e) => e.message ?? String(e)).join("; ");
|
|
194
|
+
error("Edge GraphQL errors:", msg);
|
|
195
|
+
throw new Error(msg);
|
|
149
196
|
}
|
|
150
197
|
const fields = json.data?.item?.fields;
|
|
151
|
-
if (!fields || !Array.isArray(fields))
|
|
152
|
-
|
|
198
|
+
if (!fields || !Array.isArray(fields)) {
|
|
199
|
+
warn("Edge GraphQL: item not found or has no fields for", datasourceId);
|
|
200
|
+
return {};
|
|
201
|
+
}
|
|
202
|
+
const mapped = mapFields(fields);
|
|
203
|
+
log("Edge GraphQL resolved fields:", { datasourceId, fieldCount: Object.keys(mapped).length, fieldNames: Object.keys(mapped) });
|
|
204
|
+
return mapped;
|
|
153
205
|
}
|
|
154
206
|
function createEdgeResolver(edgeUrl, apiKey, language = "en") {
|
|
155
207
|
return (datasourceId) => queryEdge(edgeUrl, { sc_apikey: apiKey }, datasourceId, language);
|
|
@@ -162,23 +214,46 @@ function createEdgeProxyResolver(edgeBaseUrl, contextId, language = "en") {
|
|
|
162
214
|
|
|
163
215
|
// src/editingDetection.ts
|
|
164
216
|
var cachedResult = null;
|
|
217
|
+
function getSitecoreContext() {
|
|
218
|
+
if (typeof window === "undefined") return void 0;
|
|
219
|
+
try {
|
|
220
|
+
const nd = window.__NEXT_DATA__;
|
|
221
|
+
return nd?.props?.pageProps?.layoutData?.sitecore?.context;
|
|
222
|
+
} catch {
|
|
223
|
+
return void 0;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
165
226
|
function isEditingMode() {
|
|
166
|
-
if (typeof window === "undefined")
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const scMode = params.get("sc_mode");
|
|
170
|
-
if (scMode && scMode !== "normal") {
|
|
171
|
-
cachedResult = true;
|
|
172
|
-
return true;
|
|
227
|
+
if (typeof window === "undefined") {
|
|
228
|
+
log("Editing detection: SSR \u2014 returning false");
|
|
229
|
+
return false;
|
|
173
230
|
}
|
|
174
|
-
if (
|
|
231
|
+
if (cachedResult !== null) {
|
|
232
|
+
log("Editing detection: returning cached result", cachedResult);
|
|
233
|
+
return cachedResult;
|
|
234
|
+
}
|
|
235
|
+
log("Editing detection: running checks...");
|
|
236
|
+
const sc = getSitecoreContext();
|
|
237
|
+
log("Editing detection: __NEXT_DATA__ sitecore context:", sc ?? "(not found)");
|
|
238
|
+
if (sc?.pageEditing === true || sc?.pageState && sc.pageState !== "normal") {
|
|
239
|
+
log("Editing detection: MATCH \u2014 JSS context pageEditing/pageState", { pageEditing: sc.pageEditing, pageState: sc.pageState });
|
|
175
240
|
cachedResult = true;
|
|
176
241
|
return true;
|
|
177
242
|
}
|
|
178
|
-
|
|
243
|
+
try {
|
|
244
|
+
const inIframe = window.self !== window.top;
|
|
245
|
+
log("Editing detection: iframe check \u2014 window.self !== window.top:", inIframe);
|
|
246
|
+
if (inIframe) {
|
|
247
|
+
log("Editing detection: MATCH \u2014 running inside iframe (Page Builder)");
|
|
248
|
+
cachedResult = true;
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
} catch {
|
|
252
|
+
log("Editing detection: MATCH \u2014 cross-origin iframe access threw (Page Builder)");
|
|
179
253
|
cachedResult = true;
|
|
180
254
|
return true;
|
|
181
255
|
}
|
|
256
|
+
log("Editing detection: no match \u2014 not in editing mode");
|
|
182
257
|
cachedResult = false;
|
|
183
258
|
return false;
|
|
184
259
|
}
|
|
@@ -197,43 +272,87 @@ var DEFAULT_EDGE_URL = "https://edge-platform.sitecorecloud.io";
|
|
|
197
272
|
var noopResolver = async () => ({});
|
|
198
273
|
function PersonalizeProvider({
|
|
199
274
|
children,
|
|
200
|
-
// Context ID mode
|
|
201
275
|
sitecoreEdgeContextId,
|
|
202
276
|
sitecoreEdgeUrl = DEFAULT_EDGE_URL,
|
|
203
277
|
siteName = "",
|
|
204
|
-
// Legacy mode
|
|
205
278
|
clientKey = "",
|
|
206
279
|
pointOfSale = "",
|
|
207
280
|
edgeUrl,
|
|
208
281
|
apiKey,
|
|
209
|
-
// Common
|
|
210
282
|
channel = DEFAULT_CHANNEL,
|
|
211
283
|
language = DEFAULT_LANGUAGE,
|
|
212
284
|
currencyCode = DEFAULT_CURRENCY,
|
|
213
285
|
timeout = DEFAULT_TIMEOUT,
|
|
214
286
|
resolveDatasource,
|
|
215
|
-
isEditing: isEditingProp
|
|
287
|
+
isEditing: isEditingProp,
|
|
288
|
+
debug = false
|
|
216
289
|
}) {
|
|
217
290
|
const useEdgeProxy = Boolean(sitecoreEdgeContextId);
|
|
218
291
|
const [browserId, setBrowserId] = (0, import_react.useState)("");
|
|
219
292
|
const [detectedEditing, setDetectedEditing] = (0, import_react.useState)(false);
|
|
293
|
+
(0, import_react.useEffect)(() => {
|
|
294
|
+
setDebug(debug);
|
|
295
|
+
}, [debug]);
|
|
296
|
+
(0, import_react.useEffect)(() => {
|
|
297
|
+
setDebug(debug);
|
|
298
|
+
log("Provider mounting", {
|
|
299
|
+
mode: useEdgeProxy ? "Context ID" : "Legacy",
|
|
300
|
+
sitecoreEdgeContextId: sitecoreEdgeContextId ?? "(none)",
|
|
301
|
+
sitecoreEdgeUrl,
|
|
302
|
+
siteName: siteName || "(none)",
|
|
303
|
+
clientKey: clientKey ? `${clientKey.slice(0, 8)}...` : "(none)",
|
|
304
|
+
pointOfSale: pointOfSale || "(none)",
|
|
305
|
+
edgeUrl: edgeUrl ?? "(none)",
|
|
306
|
+
apiKey: apiKey ? `${apiKey.slice(0, 8)}...` : "(none)",
|
|
307
|
+
language,
|
|
308
|
+
channel,
|
|
309
|
+
hasCustomResolver: Boolean(resolveDatasource),
|
|
310
|
+
isEditingProp: isEditingProp ?? "auto-detect"
|
|
311
|
+
});
|
|
312
|
+
}, []);
|
|
220
313
|
(0, import_react.useEffect)(() => {
|
|
221
314
|
if (useEdgeProxy) {
|
|
222
|
-
|
|
315
|
+
log("BrowserId: fetching via Edge init", { sitecoreEdgeUrl, sitecoreEdgeContextId, siteName });
|
|
316
|
+
getEdgeBrowserId(sitecoreEdgeUrl, sitecoreEdgeContextId, siteName).then((bid) => {
|
|
317
|
+
log("BrowserId: resolved via Edge init", bid);
|
|
318
|
+
setBrowserId(bid);
|
|
319
|
+
}).catch((err) => {
|
|
320
|
+
warn("BrowserId: Edge init failed, will use fallback", err);
|
|
321
|
+
});
|
|
223
322
|
} else if (clientKey) {
|
|
224
|
-
|
|
323
|
+
const bid = getBrowserId(clientKey);
|
|
324
|
+
log("BrowserId: resolved via local cookie", bid);
|
|
325
|
+
setBrowserId(bid);
|
|
326
|
+
} else {
|
|
327
|
+
warn("BrowserId: no clientKey and no sitecoreEdgeContextId \u2014 browserId will be empty");
|
|
225
328
|
}
|
|
226
329
|
}, [useEdgeProxy, sitecoreEdgeContextId, sitecoreEdgeUrl, siteName, clientKey]);
|
|
227
330
|
(0, import_react.useEffect)(() => {
|
|
228
331
|
if (isEditingProp === void 0) {
|
|
229
|
-
|
|
332
|
+
const detected = isEditingMode();
|
|
333
|
+
log("Editing mode auto-detected:", detected);
|
|
334
|
+
setDetectedEditing(detected);
|
|
335
|
+
} else {
|
|
336
|
+
log("Editing mode overridden via prop:", isEditingProp);
|
|
230
337
|
}
|
|
231
338
|
}, [isEditingProp]);
|
|
232
339
|
const effectiveEditing = isEditingProp ?? detectedEditing;
|
|
233
|
-
const effectiveResolver = (0, import_react.useCallback)(
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
340
|
+
const effectiveResolver = (0, import_react.useCallback)(() => {
|
|
341
|
+
if (resolveDatasource) {
|
|
342
|
+
log("Resolver: using custom resolveDatasource callback");
|
|
343
|
+
return resolveDatasource;
|
|
344
|
+
}
|
|
345
|
+
if (useEdgeProxy) {
|
|
346
|
+
log("Resolver: using Edge proxy GraphQL", { sitecoreEdgeUrl, sitecoreEdgeContextId });
|
|
347
|
+
return createEdgeProxyResolver(sitecoreEdgeUrl, sitecoreEdgeContextId, language);
|
|
348
|
+
}
|
|
349
|
+
if (edgeUrl && apiKey) {
|
|
350
|
+
log("Resolver: using direct Edge GraphQL", { edgeUrl });
|
|
351
|
+
return createEdgeResolver(edgeUrl, apiKey, language);
|
|
352
|
+
}
|
|
353
|
+
warn("Resolver: no resolver configured \u2014 resolveDatasource will return {}. Provide sitecoreEdgeContextId, edgeUrl+apiKey, or a custom resolveDatasource.");
|
|
354
|
+
return noopResolver;
|
|
355
|
+
}, [resolveDatasource, useEdgeProxy, sitecoreEdgeUrl, sitecoreEdgeContextId, edgeUrl, apiKey, language])();
|
|
237
356
|
const effectiveBrowserId = browserId || (!useEdgeProxy && clientKey && typeof window !== "undefined" ? getBrowserId(clientKey) : "");
|
|
238
357
|
const value = (0, import_react.useMemo)(
|
|
239
358
|
() => ({
|
|
@@ -277,10 +396,23 @@ function usePersonalizeContext() {
|
|
|
277
396
|
var DEFAULT_API_BASE = "https://api.boxever.com";
|
|
278
397
|
async function callPersonalize(options) {
|
|
279
398
|
const { config, context, apiBase = DEFAULT_API_BASE, componentRef, pageRoute } = options;
|
|
399
|
+
group(`callPersonalize [${config.friendlyId}]`);
|
|
400
|
+
log("Config:", { friendlyId: config.friendlyId, defaultKey: config.defaultKey, contentMapKeys: Object.keys(config.contentMap) });
|
|
401
|
+
log("BrowserId:", context.browserId || "(empty \u2014 call will likely fail)");
|
|
402
|
+
if (!context.browserId) {
|
|
403
|
+
warn("BrowserId is empty \u2014 personalize call may fail or return default");
|
|
404
|
+
}
|
|
405
|
+
let result;
|
|
280
406
|
if (context.useEdgeProxy) {
|
|
281
|
-
|
|
407
|
+
log("Route: Edge proxy");
|
|
408
|
+
result = await callViaEdgeProxy(config, context, componentRef, pageRoute);
|
|
409
|
+
} else {
|
|
410
|
+
log("Route: Legacy /v2/callFlows", { apiBase });
|
|
411
|
+
result = await callViaLegacy(config, context, apiBase, componentRef, pageRoute);
|
|
282
412
|
}
|
|
283
|
-
|
|
413
|
+
log("Result contentKey:", result ?? "(null \u2014 will use defaultKey)");
|
|
414
|
+
groupEnd();
|
|
415
|
+
return result;
|
|
284
416
|
}
|
|
285
417
|
async function callViaEdgeProxy(config, context, componentRef, pageRoute) {
|
|
286
418
|
const base = context.edgeProxyUrl.replace(/\/$/, "");
|
|
@@ -298,6 +430,8 @@ async function callViaEdgeProxy(config, context, componentRef, pageRoute) {
|
|
|
298
430
|
if (pageRoute) params.pageRoute = pageRoute;
|
|
299
431
|
body.params = params;
|
|
300
432
|
}
|
|
433
|
+
log("Edge proxy POST", url);
|
|
434
|
+
log("Request body:", body);
|
|
301
435
|
const controller = new AbortController();
|
|
302
436
|
const timeoutId = setTimeout(() => controller.abort(), context.timeout);
|
|
303
437
|
try {
|
|
@@ -308,10 +442,18 @@ async function callViaEdgeProxy(config, context, componentRef, pageRoute) {
|
|
|
308
442
|
signal: controller.signal
|
|
309
443
|
});
|
|
310
444
|
clearTimeout(timeoutId);
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
445
|
+
log("Edge proxy response status:", res.status);
|
|
446
|
+
if (!res.ok) {
|
|
447
|
+
const text = await res.text().catch(() => "");
|
|
448
|
+
warn("Edge proxy non-OK response:", res.status, text);
|
|
449
|
+
return null;
|
|
450
|
+
}
|
|
451
|
+
const data = await res.json();
|
|
452
|
+
log("Edge proxy response body:", data);
|
|
453
|
+
return extractContentKey(data);
|
|
454
|
+
} catch (e) {
|
|
314
455
|
clearTimeout(timeoutId);
|
|
456
|
+
error("Edge proxy fetch error:", e);
|
|
315
457
|
return null;
|
|
316
458
|
}
|
|
317
459
|
}
|
|
@@ -330,20 +472,31 @@ async function callViaLegacy(config, context, apiBase, componentRef, pageRoute)
|
|
|
330
472
|
if (componentRef) body.params.componentRef = componentRef;
|
|
331
473
|
if (pageRoute) body.params.pageRoute = pageRoute;
|
|
332
474
|
}
|
|
475
|
+
const url = `${apiBase.replace(/\/$/, "")}/v2/callFlows`;
|
|
476
|
+
log("Legacy POST", url);
|
|
477
|
+
log("Request body:", body);
|
|
333
478
|
const controller = new AbortController();
|
|
334
479
|
const timeoutId = setTimeout(() => controller.abort(), context.timeout);
|
|
335
480
|
try {
|
|
336
|
-
const res = await fetch(
|
|
481
|
+
const res = await fetch(url, {
|
|
337
482
|
method: "POST",
|
|
338
483
|
headers: { "Content-Type": "application/json" },
|
|
339
484
|
body: JSON.stringify(body),
|
|
340
485
|
signal: controller.signal
|
|
341
486
|
});
|
|
342
487
|
clearTimeout(timeoutId);
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
488
|
+
log("Legacy response status:", res.status);
|
|
489
|
+
if (!res.ok) {
|
|
490
|
+
const text = await res.text().catch(() => "");
|
|
491
|
+
warn("Legacy non-OK response:", res.status, text);
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
const data = await res.json();
|
|
495
|
+
log("Legacy response body:", data);
|
|
496
|
+
return extractContentKey(data);
|
|
497
|
+
} catch (e) {
|
|
346
498
|
clearTimeout(timeoutId);
|
|
499
|
+
error("Legacy fetch error:", e);
|
|
347
500
|
return null;
|
|
348
501
|
}
|
|
349
502
|
}
|
|
@@ -357,14 +510,29 @@ function extractContentKey(data) {
|
|
|
357
510
|
// src/contentResolver.ts
|
|
358
511
|
async function resolveContent(options) {
|
|
359
512
|
const { contentKey, config, resolveDatasource } = options;
|
|
360
|
-
const
|
|
513
|
+
const keyInMap = contentKey && contentKey in config.contentMap;
|
|
514
|
+
const effectiveKey = keyInMap ? contentKey : config.defaultKey;
|
|
515
|
+
if (!keyInMap) {
|
|
516
|
+
warn(
|
|
517
|
+
`Content key "${contentKey}" not found in contentMap [${Object.keys(config.contentMap).join(", ")}], falling back to defaultKey "${config.defaultKey}"`
|
|
518
|
+
);
|
|
519
|
+
}
|
|
361
520
|
const datasourceId = config.contentMap[effectiveKey];
|
|
362
|
-
|
|
521
|
+
log("Resolving datasource:", { effectiveKey, datasourceId });
|
|
522
|
+
if (!datasourceId || typeof datasourceId !== "string") {
|
|
523
|
+
warn(`No datasource ID for key "${effectiveKey}" \u2014 contentMap may be misconfigured`);
|
|
524
|
+
return null;
|
|
525
|
+
}
|
|
363
526
|
try {
|
|
364
527
|
const fields = await resolveDatasource(datasourceId);
|
|
365
|
-
if (!fields || typeof fields !== "object")
|
|
528
|
+
if (!fields || typeof fields !== "object") {
|
|
529
|
+
warn("resolveDatasource returned empty/invalid fields for", datasourceId);
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
532
|
+
log("Datasource resolved:", { datasourceId, fieldNames: Object.keys(fields) });
|
|
366
533
|
return { datasourceId, fields };
|
|
367
|
-
} catch {
|
|
534
|
+
} catch (e) {
|
|
535
|
+
error("resolveDatasource threw for", datasourceId, e);
|
|
368
536
|
return null;
|
|
369
537
|
}
|
|
370
538
|
}
|
|
@@ -397,24 +565,46 @@ var INDICATOR_BADGE = {
|
|
|
397
565
|
pointerEvents: "none"
|
|
398
566
|
};
|
|
399
567
|
function withPersonalizeConnect(WrappedComponent, getConfig = DEFAULT_GET_CONFIG) {
|
|
568
|
+
const componentName = WrappedComponent.displayName ?? WrappedComponent.name ?? "Component";
|
|
400
569
|
function PersonalizeConnectWrapper(props) {
|
|
401
570
|
const context = usePersonalizeContext();
|
|
402
571
|
const config = getConfig(props);
|
|
403
572
|
const [resolvedFields, setResolvedFields] = (0, import_react2.useState)(null);
|
|
404
573
|
const mountedRef = (0, import_react2.useRef)(true);
|
|
574
|
+
if (!config) {
|
|
575
|
+
log(`[${componentName}] No personalizeConnect config on rendering \u2014 passthrough`);
|
|
576
|
+
} else {
|
|
577
|
+
log(`[${componentName}] Config found:`, { friendlyId: config.friendlyId, defaultKey: config.defaultKey, keys: Object.keys(config.contentMap) });
|
|
578
|
+
}
|
|
579
|
+
if (!context) {
|
|
580
|
+
warn(`[${componentName}] PersonalizeContext is null \u2014 is PersonalizeProvider mounted?`);
|
|
581
|
+
}
|
|
405
582
|
const runPersonalization = (0, import_react2.useCallback)(async () => {
|
|
406
583
|
if (!config || !context) return;
|
|
584
|
+
group(`[${componentName}] personalization flow`);
|
|
585
|
+
log("Calling Personalize for experience:", config.friendlyId);
|
|
407
586
|
const contentKey = await callPersonalize({ config, context });
|
|
408
|
-
if (!mountedRef.current)
|
|
587
|
+
if (!mountedRef.current) {
|
|
588
|
+
groupEnd();
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
log("Resolving content for contentKey:", contentKey ?? "(null)");
|
|
409
592
|
const resolved = await resolveContent({
|
|
410
593
|
contentKey,
|
|
411
594
|
config,
|
|
412
595
|
resolveDatasource: context.resolveDatasource
|
|
413
596
|
});
|
|
414
|
-
if (!mountedRef.current)
|
|
597
|
+
if (!mountedRef.current) {
|
|
598
|
+
groupEnd();
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
415
601
|
if (resolved) {
|
|
602
|
+
log(`[${componentName}] Fields resolved \u2014 swapping props.fields`, { datasourceId: resolved.datasourceId, fieldNames: Object.keys(resolved.fields) });
|
|
416
603
|
setResolvedFields(resolved.fields);
|
|
604
|
+
} else {
|
|
605
|
+
warn(`[${componentName}] Content resolution returned null \u2014 component keeps original fields`);
|
|
417
606
|
}
|
|
607
|
+
groupEnd();
|
|
418
608
|
}, [config, context]);
|
|
419
609
|
(0, import_react2.useEffect)(() => {
|
|
420
610
|
mountedRef.current = true;
|
|
@@ -431,6 +621,7 @@ function withPersonalizeConnect(WrappedComponent, getConfig = DEFAULT_GET_CONFIG
|
|
|
431
621
|
const mergedProps = resolvedFields ? { ...props, fields: resolvedFields } : props;
|
|
432
622
|
const component = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(WrappedComponent, { ...mergedProps });
|
|
433
623
|
if (context.isEditing) {
|
|
624
|
+
log(`[${componentName}] Editing mode \u2014 rendering indicator badge`);
|
|
434
625
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: INDICATOR_BORDER, "data-personalize-connect": config.friendlyId, children: [
|
|
435
626
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: INDICATOR_BADGE, title: `Personalize: ${config.friendlyId}`, children: "\u26A1 Personalized" }),
|
|
436
627
|
component
|
|
@@ -438,7 +629,7 @@ function withPersonalizeConnect(WrappedComponent, getConfig = DEFAULT_GET_CONFIG
|
|
|
438
629
|
}
|
|
439
630
|
return component;
|
|
440
631
|
}
|
|
441
|
-
PersonalizeConnectWrapper.displayName = `WithPersonalizeConnect(${
|
|
632
|
+
PersonalizeConnectWrapper.displayName = `WithPersonalizeConnect(${componentName})`;
|
|
442
633
|
return PersonalizeConnectWrapper;
|
|
443
634
|
}
|
|
444
635
|
|
|
@@ -449,7 +640,7 @@ function usePersonalizeExperience(config) {
|
|
|
449
640
|
const [contentKey, setContentKey] = (0, import_react3.useState)(null);
|
|
450
641
|
const [resolvedFields, setResolvedFields] = (0, import_react3.useState)(null);
|
|
451
642
|
const [isLoading, setIsLoading] = (0, import_react3.useState)(true);
|
|
452
|
-
const [
|
|
643
|
+
const [error2, setError] = (0, import_react3.useState)(null);
|
|
453
644
|
const mountedRef = (0, import_react3.useRef)(true);
|
|
454
645
|
const runPersonalization = (0, import_react3.useCallback)(async () => {
|
|
455
646
|
if (!config || !context) {
|
|
@@ -490,7 +681,7 @@ function usePersonalizeExperience(config) {
|
|
|
490
681
|
contentKey,
|
|
491
682
|
resolvedFields,
|
|
492
683
|
isLoading,
|
|
493
|
-
error
|
|
684
|
+
error: error2
|
|
494
685
|
};
|
|
495
686
|
}
|
|
496
687
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -501,10 +692,12 @@ function usePersonalizeExperience(config) {
|
|
|
501
692
|
createEdgeResolver,
|
|
502
693
|
getBrowserId,
|
|
503
694
|
getEdgeBrowserId,
|
|
695
|
+
isDebugEnabled,
|
|
504
696
|
isEditingMode,
|
|
505
697
|
resetEdgeInitCache,
|
|
506
698
|
resetEditingDetectionCache,
|
|
507
699
|
resolveContent,
|
|
700
|
+
setDebug,
|
|
508
701
|
usePersonalizeContext,
|
|
509
702
|
usePersonalizeExperience,
|
|
510
703
|
withPersonalizeConnect
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
// src/PersonalizeProvider.tsx
|
|
2
2
|
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
|
|
3
3
|
|
|
4
|
+
// src/logger.ts
|
|
5
|
+
var PREFIX = "[PersonalizeConnect]";
|
|
6
|
+
var enabled = false;
|
|
7
|
+
function setDebug(on) {
|
|
8
|
+
enabled = on;
|
|
9
|
+
}
|
|
10
|
+
function isDebugEnabled() {
|
|
11
|
+
return enabled;
|
|
12
|
+
}
|
|
13
|
+
function log(...args) {
|
|
14
|
+
if (enabled) console.log(PREFIX, ...args);
|
|
15
|
+
}
|
|
16
|
+
function warn(...args) {
|
|
17
|
+
if (enabled) console.warn(PREFIX, ...args);
|
|
18
|
+
}
|
|
19
|
+
function error(...args) {
|
|
20
|
+
if (enabled) console.error(PREFIX, ...args);
|
|
21
|
+
}
|
|
22
|
+
function group(label) {
|
|
23
|
+
if (enabled) console.groupCollapsed(`${PREFIX} ${label}`);
|
|
24
|
+
}
|
|
25
|
+
function groupEnd() {
|
|
26
|
+
if (enabled) console.groupEnd();
|
|
27
|
+
}
|
|
28
|
+
|
|
4
29
|
// src/browserId.ts
|
|
5
30
|
var LEGACY_COOKIE_PREFIX = "bid_";
|
|
6
31
|
var CONTEXT_COOKIE_PREFIX = "sc_";
|
|
@@ -33,6 +58,9 @@ function getBrowserId(clientKey) {
|
|
|
33
58
|
if (!bid || typeof bid !== "string" || bid.length < 10) {
|
|
34
59
|
bid = generateBrowserId();
|
|
35
60
|
setCookie(cookieName, bid);
|
|
61
|
+
log("BrowserId (legacy): generated new", bid, `cookie=${cookieName}`);
|
|
62
|
+
} else {
|
|
63
|
+
log("BrowserId (legacy): from cookie", bid, `cookie=${cookieName}`);
|
|
36
64
|
}
|
|
37
65
|
return bid;
|
|
38
66
|
}
|
|
@@ -40,15 +68,21 @@ var edgeInitPromise = null;
|
|
|
40
68
|
async function getEdgeBrowserId(edgeUrl, contextId, siteName) {
|
|
41
69
|
const cookieName = CONTEXT_COOKIE_PREFIX + contextId + CONTEXT_COOKIE_SUFFIX;
|
|
42
70
|
const cached = getCookie(cookieName);
|
|
43
|
-
if (cached && cached.length >= 10)
|
|
71
|
+
if (cached && cached.length >= 10) {
|
|
72
|
+
log("BrowserId (edge): from cookie", cached, `cookie=${cookieName}`);
|
|
73
|
+
return cached;
|
|
74
|
+
}
|
|
75
|
+
log("BrowserId (edge): cookie miss, calling /v1/init", { edgeUrl, contextId, siteName });
|
|
44
76
|
if (!edgeInitPromise) {
|
|
45
77
|
edgeInitPromise = fetchEdgeInit(edgeUrl, contextId, siteName);
|
|
46
78
|
}
|
|
47
79
|
try {
|
|
48
80
|
const result = await edgeInitPromise;
|
|
81
|
+
log("BrowserId (edge): init returned", result);
|
|
49
82
|
setCookie(cookieName, result.browserId);
|
|
50
83
|
return result.browserId;
|
|
51
|
-
} catch {
|
|
84
|
+
} catch (e) {
|
|
85
|
+
warn("BrowserId (edge): init failed, generating fallback", e);
|
|
52
86
|
const fallback = generateBrowserId();
|
|
53
87
|
setCookie(cookieName, fallback);
|
|
54
88
|
return fallback;
|
|
@@ -59,12 +93,17 @@ async function getEdgeBrowserId(edgeUrl, contextId, siteName) {
|
|
|
59
93
|
async function fetchEdgeInit(edgeUrl, contextId, siteName) {
|
|
60
94
|
const base = edgeUrl.replace(/\/$/, "");
|
|
61
95
|
const url = `${base}/v1/init?sitecoreContextId=${encodeURIComponent(contextId)}&siteName=${encodeURIComponent(siteName)}`;
|
|
96
|
+
log("BrowserId (edge): GET", url);
|
|
62
97
|
const res = await fetch(url, { method: "GET" });
|
|
98
|
+
log("BrowserId (edge): init response status:", res.status);
|
|
63
99
|
if (!res.ok) {
|
|
100
|
+
const text = await res.text().catch(() => "");
|
|
101
|
+
error("BrowserId (edge): init non-OK:", res.status, text);
|
|
64
102
|
throw new Error(`Edge init failed: ${res.status}`);
|
|
65
103
|
}
|
|
66
104
|
const data = await res.json();
|
|
67
105
|
if (!data.browserId || typeof data.browserId !== "string") {
|
|
106
|
+
error("BrowserId (edge): init response missing browserId", data);
|
|
68
107
|
throw new Error("Edge init response missing browserId");
|
|
69
108
|
}
|
|
70
109
|
return data;
|
|
@@ -94,6 +133,7 @@ function mapFields(fields) {
|
|
|
94
133
|
return result;
|
|
95
134
|
}
|
|
96
135
|
async function queryEdge(url, headers, datasourceId, language) {
|
|
136
|
+
log("Edge GraphQL request:", { url, datasourceId, language });
|
|
97
137
|
const res = await fetch(url, {
|
|
98
138
|
method: "POST",
|
|
99
139
|
headers: { "Content-Type": "application/json", ...headers },
|
|
@@ -102,16 +142,26 @@ async function queryEdge(url, headers, datasourceId, language) {
|
|
|
102
142
|
variables: { itemId: datasourceId, language }
|
|
103
143
|
})
|
|
104
144
|
});
|
|
145
|
+
log("Edge GraphQL response status:", res.status);
|
|
105
146
|
if (!res.ok) {
|
|
147
|
+
const text = await res.text().catch(() => "");
|
|
148
|
+
error("Edge GraphQL non-OK response:", res.status, text);
|
|
106
149
|
throw new Error(`Experience Edge request failed: ${res.status}`);
|
|
107
150
|
}
|
|
108
151
|
const json = await res.json();
|
|
109
152
|
if (json.errors?.length) {
|
|
110
|
-
|
|
153
|
+
const msg = json.errors.map((e) => e.message ?? String(e)).join("; ");
|
|
154
|
+
error("Edge GraphQL errors:", msg);
|
|
155
|
+
throw new Error(msg);
|
|
111
156
|
}
|
|
112
157
|
const fields = json.data?.item?.fields;
|
|
113
|
-
if (!fields || !Array.isArray(fields))
|
|
114
|
-
|
|
158
|
+
if (!fields || !Array.isArray(fields)) {
|
|
159
|
+
warn("Edge GraphQL: item not found or has no fields for", datasourceId);
|
|
160
|
+
return {};
|
|
161
|
+
}
|
|
162
|
+
const mapped = mapFields(fields);
|
|
163
|
+
log("Edge GraphQL resolved fields:", { datasourceId, fieldCount: Object.keys(mapped).length, fieldNames: Object.keys(mapped) });
|
|
164
|
+
return mapped;
|
|
115
165
|
}
|
|
116
166
|
function createEdgeResolver(edgeUrl, apiKey, language = "en") {
|
|
117
167
|
return (datasourceId) => queryEdge(edgeUrl, { sc_apikey: apiKey }, datasourceId, language);
|
|
@@ -124,23 +174,46 @@ function createEdgeProxyResolver(edgeBaseUrl, contextId, language = "en") {
|
|
|
124
174
|
|
|
125
175
|
// src/editingDetection.ts
|
|
126
176
|
var cachedResult = null;
|
|
177
|
+
function getSitecoreContext() {
|
|
178
|
+
if (typeof window === "undefined") return void 0;
|
|
179
|
+
try {
|
|
180
|
+
const nd = window.__NEXT_DATA__;
|
|
181
|
+
return nd?.props?.pageProps?.layoutData?.sitecore?.context;
|
|
182
|
+
} catch {
|
|
183
|
+
return void 0;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
127
186
|
function isEditingMode() {
|
|
128
|
-
if (typeof window === "undefined")
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const scMode = params.get("sc_mode");
|
|
132
|
-
if (scMode && scMode !== "normal") {
|
|
133
|
-
cachedResult = true;
|
|
134
|
-
return true;
|
|
187
|
+
if (typeof window === "undefined") {
|
|
188
|
+
log("Editing detection: SSR \u2014 returning false");
|
|
189
|
+
return false;
|
|
135
190
|
}
|
|
136
|
-
if (
|
|
191
|
+
if (cachedResult !== null) {
|
|
192
|
+
log("Editing detection: returning cached result", cachedResult);
|
|
193
|
+
return cachedResult;
|
|
194
|
+
}
|
|
195
|
+
log("Editing detection: running checks...");
|
|
196
|
+
const sc = getSitecoreContext();
|
|
197
|
+
log("Editing detection: __NEXT_DATA__ sitecore context:", sc ?? "(not found)");
|
|
198
|
+
if (sc?.pageEditing === true || sc?.pageState && sc.pageState !== "normal") {
|
|
199
|
+
log("Editing detection: MATCH \u2014 JSS context pageEditing/pageState", { pageEditing: sc.pageEditing, pageState: sc.pageState });
|
|
137
200
|
cachedResult = true;
|
|
138
201
|
return true;
|
|
139
202
|
}
|
|
140
|
-
|
|
203
|
+
try {
|
|
204
|
+
const inIframe = window.self !== window.top;
|
|
205
|
+
log("Editing detection: iframe check \u2014 window.self !== window.top:", inIframe);
|
|
206
|
+
if (inIframe) {
|
|
207
|
+
log("Editing detection: MATCH \u2014 running inside iframe (Page Builder)");
|
|
208
|
+
cachedResult = true;
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
} catch {
|
|
212
|
+
log("Editing detection: MATCH \u2014 cross-origin iframe access threw (Page Builder)");
|
|
141
213
|
cachedResult = true;
|
|
142
214
|
return true;
|
|
143
215
|
}
|
|
216
|
+
log("Editing detection: no match \u2014 not in editing mode");
|
|
144
217
|
cachedResult = false;
|
|
145
218
|
return false;
|
|
146
219
|
}
|
|
@@ -159,43 +232,87 @@ var DEFAULT_EDGE_URL = "https://edge-platform.sitecorecloud.io";
|
|
|
159
232
|
var noopResolver = async () => ({});
|
|
160
233
|
function PersonalizeProvider({
|
|
161
234
|
children,
|
|
162
|
-
// Context ID mode
|
|
163
235
|
sitecoreEdgeContextId,
|
|
164
236
|
sitecoreEdgeUrl = DEFAULT_EDGE_URL,
|
|
165
237
|
siteName = "",
|
|
166
|
-
// Legacy mode
|
|
167
238
|
clientKey = "",
|
|
168
239
|
pointOfSale = "",
|
|
169
240
|
edgeUrl,
|
|
170
241
|
apiKey,
|
|
171
|
-
// Common
|
|
172
242
|
channel = DEFAULT_CHANNEL,
|
|
173
243
|
language = DEFAULT_LANGUAGE,
|
|
174
244
|
currencyCode = DEFAULT_CURRENCY,
|
|
175
245
|
timeout = DEFAULT_TIMEOUT,
|
|
176
246
|
resolveDatasource,
|
|
177
|
-
isEditing: isEditingProp
|
|
247
|
+
isEditing: isEditingProp,
|
|
248
|
+
debug = false
|
|
178
249
|
}) {
|
|
179
250
|
const useEdgeProxy = Boolean(sitecoreEdgeContextId);
|
|
180
251
|
const [browserId, setBrowserId] = useState("");
|
|
181
252
|
const [detectedEditing, setDetectedEditing] = useState(false);
|
|
253
|
+
useEffect(() => {
|
|
254
|
+
setDebug(debug);
|
|
255
|
+
}, [debug]);
|
|
256
|
+
useEffect(() => {
|
|
257
|
+
setDebug(debug);
|
|
258
|
+
log("Provider mounting", {
|
|
259
|
+
mode: useEdgeProxy ? "Context ID" : "Legacy",
|
|
260
|
+
sitecoreEdgeContextId: sitecoreEdgeContextId ?? "(none)",
|
|
261
|
+
sitecoreEdgeUrl,
|
|
262
|
+
siteName: siteName || "(none)",
|
|
263
|
+
clientKey: clientKey ? `${clientKey.slice(0, 8)}...` : "(none)",
|
|
264
|
+
pointOfSale: pointOfSale || "(none)",
|
|
265
|
+
edgeUrl: edgeUrl ?? "(none)",
|
|
266
|
+
apiKey: apiKey ? `${apiKey.slice(0, 8)}...` : "(none)",
|
|
267
|
+
language,
|
|
268
|
+
channel,
|
|
269
|
+
hasCustomResolver: Boolean(resolveDatasource),
|
|
270
|
+
isEditingProp: isEditingProp ?? "auto-detect"
|
|
271
|
+
});
|
|
272
|
+
}, []);
|
|
182
273
|
useEffect(() => {
|
|
183
274
|
if (useEdgeProxy) {
|
|
184
|
-
|
|
275
|
+
log("BrowserId: fetching via Edge init", { sitecoreEdgeUrl, sitecoreEdgeContextId, siteName });
|
|
276
|
+
getEdgeBrowserId(sitecoreEdgeUrl, sitecoreEdgeContextId, siteName).then((bid) => {
|
|
277
|
+
log("BrowserId: resolved via Edge init", bid);
|
|
278
|
+
setBrowserId(bid);
|
|
279
|
+
}).catch((err) => {
|
|
280
|
+
warn("BrowserId: Edge init failed, will use fallback", err);
|
|
281
|
+
});
|
|
185
282
|
} else if (clientKey) {
|
|
186
|
-
|
|
283
|
+
const bid = getBrowserId(clientKey);
|
|
284
|
+
log("BrowserId: resolved via local cookie", bid);
|
|
285
|
+
setBrowserId(bid);
|
|
286
|
+
} else {
|
|
287
|
+
warn("BrowserId: no clientKey and no sitecoreEdgeContextId \u2014 browserId will be empty");
|
|
187
288
|
}
|
|
188
289
|
}, [useEdgeProxy, sitecoreEdgeContextId, sitecoreEdgeUrl, siteName, clientKey]);
|
|
189
290
|
useEffect(() => {
|
|
190
291
|
if (isEditingProp === void 0) {
|
|
191
|
-
|
|
292
|
+
const detected = isEditingMode();
|
|
293
|
+
log("Editing mode auto-detected:", detected);
|
|
294
|
+
setDetectedEditing(detected);
|
|
295
|
+
} else {
|
|
296
|
+
log("Editing mode overridden via prop:", isEditingProp);
|
|
192
297
|
}
|
|
193
298
|
}, [isEditingProp]);
|
|
194
299
|
const effectiveEditing = isEditingProp ?? detectedEditing;
|
|
195
|
-
const effectiveResolver = useCallback(
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
300
|
+
const effectiveResolver = useCallback(() => {
|
|
301
|
+
if (resolveDatasource) {
|
|
302
|
+
log("Resolver: using custom resolveDatasource callback");
|
|
303
|
+
return resolveDatasource;
|
|
304
|
+
}
|
|
305
|
+
if (useEdgeProxy) {
|
|
306
|
+
log("Resolver: using Edge proxy GraphQL", { sitecoreEdgeUrl, sitecoreEdgeContextId });
|
|
307
|
+
return createEdgeProxyResolver(sitecoreEdgeUrl, sitecoreEdgeContextId, language);
|
|
308
|
+
}
|
|
309
|
+
if (edgeUrl && apiKey) {
|
|
310
|
+
log("Resolver: using direct Edge GraphQL", { edgeUrl });
|
|
311
|
+
return createEdgeResolver(edgeUrl, apiKey, language);
|
|
312
|
+
}
|
|
313
|
+
warn("Resolver: no resolver configured \u2014 resolveDatasource will return {}. Provide sitecoreEdgeContextId, edgeUrl+apiKey, or a custom resolveDatasource.");
|
|
314
|
+
return noopResolver;
|
|
315
|
+
}, [resolveDatasource, useEdgeProxy, sitecoreEdgeUrl, sitecoreEdgeContextId, edgeUrl, apiKey, language])();
|
|
199
316
|
const effectiveBrowserId = browserId || (!useEdgeProxy && clientKey && typeof window !== "undefined" ? getBrowserId(clientKey) : "");
|
|
200
317
|
const value = useMemo(
|
|
201
318
|
() => ({
|
|
@@ -239,10 +356,23 @@ function usePersonalizeContext() {
|
|
|
239
356
|
var DEFAULT_API_BASE = "https://api.boxever.com";
|
|
240
357
|
async function callPersonalize(options) {
|
|
241
358
|
const { config, context, apiBase = DEFAULT_API_BASE, componentRef, pageRoute } = options;
|
|
359
|
+
group(`callPersonalize [${config.friendlyId}]`);
|
|
360
|
+
log("Config:", { friendlyId: config.friendlyId, defaultKey: config.defaultKey, contentMapKeys: Object.keys(config.contentMap) });
|
|
361
|
+
log("BrowserId:", context.browserId || "(empty \u2014 call will likely fail)");
|
|
362
|
+
if (!context.browserId) {
|
|
363
|
+
warn("BrowserId is empty \u2014 personalize call may fail or return default");
|
|
364
|
+
}
|
|
365
|
+
let result;
|
|
242
366
|
if (context.useEdgeProxy) {
|
|
243
|
-
|
|
367
|
+
log("Route: Edge proxy");
|
|
368
|
+
result = await callViaEdgeProxy(config, context, componentRef, pageRoute);
|
|
369
|
+
} else {
|
|
370
|
+
log("Route: Legacy /v2/callFlows", { apiBase });
|
|
371
|
+
result = await callViaLegacy(config, context, apiBase, componentRef, pageRoute);
|
|
244
372
|
}
|
|
245
|
-
|
|
373
|
+
log("Result contentKey:", result ?? "(null \u2014 will use defaultKey)");
|
|
374
|
+
groupEnd();
|
|
375
|
+
return result;
|
|
246
376
|
}
|
|
247
377
|
async function callViaEdgeProxy(config, context, componentRef, pageRoute) {
|
|
248
378
|
const base = context.edgeProxyUrl.replace(/\/$/, "");
|
|
@@ -260,6 +390,8 @@ async function callViaEdgeProxy(config, context, componentRef, pageRoute) {
|
|
|
260
390
|
if (pageRoute) params.pageRoute = pageRoute;
|
|
261
391
|
body.params = params;
|
|
262
392
|
}
|
|
393
|
+
log("Edge proxy POST", url);
|
|
394
|
+
log("Request body:", body);
|
|
263
395
|
const controller = new AbortController();
|
|
264
396
|
const timeoutId = setTimeout(() => controller.abort(), context.timeout);
|
|
265
397
|
try {
|
|
@@ -270,10 +402,18 @@ async function callViaEdgeProxy(config, context, componentRef, pageRoute) {
|
|
|
270
402
|
signal: controller.signal
|
|
271
403
|
});
|
|
272
404
|
clearTimeout(timeoutId);
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
405
|
+
log("Edge proxy response status:", res.status);
|
|
406
|
+
if (!res.ok) {
|
|
407
|
+
const text = await res.text().catch(() => "");
|
|
408
|
+
warn("Edge proxy non-OK response:", res.status, text);
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
const data = await res.json();
|
|
412
|
+
log("Edge proxy response body:", data);
|
|
413
|
+
return extractContentKey(data);
|
|
414
|
+
} catch (e) {
|
|
276
415
|
clearTimeout(timeoutId);
|
|
416
|
+
error("Edge proxy fetch error:", e);
|
|
277
417
|
return null;
|
|
278
418
|
}
|
|
279
419
|
}
|
|
@@ -292,20 +432,31 @@ async function callViaLegacy(config, context, apiBase, componentRef, pageRoute)
|
|
|
292
432
|
if (componentRef) body.params.componentRef = componentRef;
|
|
293
433
|
if (pageRoute) body.params.pageRoute = pageRoute;
|
|
294
434
|
}
|
|
435
|
+
const url = `${apiBase.replace(/\/$/, "")}/v2/callFlows`;
|
|
436
|
+
log("Legacy POST", url);
|
|
437
|
+
log("Request body:", body);
|
|
295
438
|
const controller = new AbortController();
|
|
296
439
|
const timeoutId = setTimeout(() => controller.abort(), context.timeout);
|
|
297
440
|
try {
|
|
298
|
-
const res = await fetch(
|
|
441
|
+
const res = await fetch(url, {
|
|
299
442
|
method: "POST",
|
|
300
443
|
headers: { "Content-Type": "application/json" },
|
|
301
444
|
body: JSON.stringify(body),
|
|
302
445
|
signal: controller.signal
|
|
303
446
|
});
|
|
304
447
|
clearTimeout(timeoutId);
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
448
|
+
log("Legacy response status:", res.status);
|
|
449
|
+
if (!res.ok) {
|
|
450
|
+
const text = await res.text().catch(() => "");
|
|
451
|
+
warn("Legacy non-OK response:", res.status, text);
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
const data = await res.json();
|
|
455
|
+
log("Legacy response body:", data);
|
|
456
|
+
return extractContentKey(data);
|
|
457
|
+
} catch (e) {
|
|
308
458
|
clearTimeout(timeoutId);
|
|
459
|
+
error("Legacy fetch error:", e);
|
|
309
460
|
return null;
|
|
310
461
|
}
|
|
311
462
|
}
|
|
@@ -319,14 +470,29 @@ function extractContentKey(data) {
|
|
|
319
470
|
// src/contentResolver.ts
|
|
320
471
|
async function resolveContent(options) {
|
|
321
472
|
const { contentKey, config, resolveDatasource } = options;
|
|
322
|
-
const
|
|
473
|
+
const keyInMap = contentKey && contentKey in config.contentMap;
|
|
474
|
+
const effectiveKey = keyInMap ? contentKey : config.defaultKey;
|
|
475
|
+
if (!keyInMap) {
|
|
476
|
+
warn(
|
|
477
|
+
`Content key "${contentKey}" not found in contentMap [${Object.keys(config.contentMap).join(", ")}], falling back to defaultKey "${config.defaultKey}"`
|
|
478
|
+
);
|
|
479
|
+
}
|
|
323
480
|
const datasourceId = config.contentMap[effectiveKey];
|
|
324
|
-
|
|
481
|
+
log("Resolving datasource:", { effectiveKey, datasourceId });
|
|
482
|
+
if (!datasourceId || typeof datasourceId !== "string") {
|
|
483
|
+
warn(`No datasource ID for key "${effectiveKey}" \u2014 contentMap may be misconfigured`);
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
325
486
|
try {
|
|
326
487
|
const fields = await resolveDatasource(datasourceId);
|
|
327
|
-
if (!fields || typeof fields !== "object")
|
|
488
|
+
if (!fields || typeof fields !== "object") {
|
|
489
|
+
warn("resolveDatasource returned empty/invalid fields for", datasourceId);
|
|
490
|
+
return null;
|
|
491
|
+
}
|
|
492
|
+
log("Datasource resolved:", { datasourceId, fieldNames: Object.keys(fields) });
|
|
328
493
|
return { datasourceId, fields };
|
|
329
|
-
} catch {
|
|
494
|
+
} catch (e) {
|
|
495
|
+
error("resolveDatasource threw for", datasourceId, e);
|
|
330
496
|
return null;
|
|
331
497
|
}
|
|
332
498
|
}
|
|
@@ -359,24 +525,46 @@ var INDICATOR_BADGE = {
|
|
|
359
525
|
pointerEvents: "none"
|
|
360
526
|
};
|
|
361
527
|
function withPersonalizeConnect(WrappedComponent, getConfig = DEFAULT_GET_CONFIG) {
|
|
528
|
+
const componentName = WrappedComponent.displayName ?? WrappedComponent.name ?? "Component";
|
|
362
529
|
function PersonalizeConnectWrapper(props) {
|
|
363
530
|
const context = usePersonalizeContext();
|
|
364
531
|
const config = getConfig(props);
|
|
365
532
|
const [resolvedFields, setResolvedFields] = useState2(null);
|
|
366
533
|
const mountedRef = useRef(true);
|
|
534
|
+
if (!config) {
|
|
535
|
+
log(`[${componentName}] No personalizeConnect config on rendering \u2014 passthrough`);
|
|
536
|
+
} else {
|
|
537
|
+
log(`[${componentName}] Config found:`, { friendlyId: config.friendlyId, defaultKey: config.defaultKey, keys: Object.keys(config.contentMap) });
|
|
538
|
+
}
|
|
539
|
+
if (!context) {
|
|
540
|
+
warn(`[${componentName}] PersonalizeContext is null \u2014 is PersonalizeProvider mounted?`);
|
|
541
|
+
}
|
|
367
542
|
const runPersonalization = useCallback2(async () => {
|
|
368
543
|
if (!config || !context) return;
|
|
544
|
+
group(`[${componentName}] personalization flow`);
|
|
545
|
+
log("Calling Personalize for experience:", config.friendlyId);
|
|
369
546
|
const contentKey = await callPersonalize({ config, context });
|
|
370
|
-
if (!mountedRef.current)
|
|
547
|
+
if (!mountedRef.current) {
|
|
548
|
+
groupEnd();
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
log("Resolving content for contentKey:", contentKey ?? "(null)");
|
|
371
552
|
const resolved = await resolveContent({
|
|
372
553
|
contentKey,
|
|
373
554
|
config,
|
|
374
555
|
resolveDatasource: context.resolveDatasource
|
|
375
556
|
});
|
|
376
|
-
if (!mountedRef.current)
|
|
557
|
+
if (!mountedRef.current) {
|
|
558
|
+
groupEnd();
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
377
561
|
if (resolved) {
|
|
562
|
+
log(`[${componentName}] Fields resolved \u2014 swapping props.fields`, { datasourceId: resolved.datasourceId, fieldNames: Object.keys(resolved.fields) });
|
|
378
563
|
setResolvedFields(resolved.fields);
|
|
564
|
+
} else {
|
|
565
|
+
warn(`[${componentName}] Content resolution returned null \u2014 component keeps original fields`);
|
|
379
566
|
}
|
|
567
|
+
groupEnd();
|
|
380
568
|
}, [config, context]);
|
|
381
569
|
useEffect2(() => {
|
|
382
570
|
mountedRef.current = true;
|
|
@@ -393,6 +581,7 @@ function withPersonalizeConnect(WrappedComponent, getConfig = DEFAULT_GET_CONFIG
|
|
|
393
581
|
const mergedProps = resolvedFields ? { ...props, fields: resolvedFields } : props;
|
|
394
582
|
const component = /* @__PURE__ */ jsx2(WrappedComponent, { ...mergedProps });
|
|
395
583
|
if (context.isEditing) {
|
|
584
|
+
log(`[${componentName}] Editing mode \u2014 rendering indicator badge`);
|
|
396
585
|
return /* @__PURE__ */ jsxs("div", { style: INDICATOR_BORDER, "data-personalize-connect": config.friendlyId, children: [
|
|
397
586
|
/* @__PURE__ */ jsx2("span", { style: INDICATOR_BADGE, title: `Personalize: ${config.friendlyId}`, children: "\u26A1 Personalized" }),
|
|
398
587
|
component
|
|
@@ -400,7 +589,7 @@ function withPersonalizeConnect(WrappedComponent, getConfig = DEFAULT_GET_CONFIG
|
|
|
400
589
|
}
|
|
401
590
|
return component;
|
|
402
591
|
}
|
|
403
|
-
PersonalizeConnectWrapper.displayName = `WithPersonalizeConnect(${
|
|
592
|
+
PersonalizeConnectWrapper.displayName = `WithPersonalizeConnect(${componentName})`;
|
|
404
593
|
return PersonalizeConnectWrapper;
|
|
405
594
|
}
|
|
406
595
|
|
|
@@ -411,7 +600,7 @@ function usePersonalizeExperience(config) {
|
|
|
411
600
|
const [contentKey, setContentKey] = useState3(null);
|
|
412
601
|
const [resolvedFields, setResolvedFields] = useState3(null);
|
|
413
602
|
const [isLoading, setIsLoading] = useState3(true);
|
|
414
|
-
const [
|
|
603
|
+
const [error2, setError] = useState3(null);
|
|
415
604
|
const mountedRef = useRef2(true);
|
|
416
605
|
const runPersonalization = useCallback3(async () => {
|
|
417
606
|
if (!config || !context) {
|
|
@@ -452,7 +641,7 @@ function usePersonalizeExperience(config) {
|
|
|
452
641
|
contentKey,
|
|
453
642
|
resolvedFields,
|
|
454
643
|
isLoading,
|
|
455
|
-
error
|
|
644
|
+
error: error2
|
|
456
645
|
};
|
|
457
646
|
}
|
|
458
647
|
export {
|
|
@@ -462,10 +651,12 @@ export {
|
|
|
462
651
|
createEdgeResolver,
|
|
463
652
|
getBrowserId,
|
|
464
653
|
getEdgeBrowserId,
|
|
654
|
+
isDebugEnabled,
|
|
465
655
|
isEditingMode,
|
|
466
656
|
resetEdgeInitCache,
|
|
467
657
|
resetEditingDetectionCache,
|
|
468
658
|
resolveContent,
|
|
659
|
+
setDebug,
|
|
469
660
|
usePersonalizeContext,
|
|
470
661
|
usePersonalizeExperience,
|
|
471
662
|
withPersonalizeConnect
|
package/package.json
CHANGED