@contentful/optimization-core 0.1.0-alpha10 → 0.1.0-alpha11
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/README.md +215 -169
- package/dist/160.mjs +3 -0
- package/dist/260.mjs +3 -3
- package/dist/260.mjs.map +1 -1
- package/dist/api-schemas.cjs +4 -1
- package/dist/api-schemas.mjs +1 -1
- package/dist/constants.cjs +7 -7
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +5 -5
- package/dist/constants.d.mts +5 -5
- package/dist/constants.d.ts +5 -5
- package/dist/constants.mjs +1 -1
- package/dist/index.cjs +1095 -1489
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1649 -1558
- package/dist/index.d.mts +1649 -1558
- package/dist/index.d.ts +1649 -1558
- package/dist/index.mjs +1062 -1507
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -2
- package/dist/808.mjs +0 -2
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,323 @@
|
|
|
1
1
|
import { batch, computed, effect, signal, untracked } from "@preact/signals-core";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { cloneDeep } from "es-toolkit";
|
|
3
|
+
import { merge } from "es-toolkit/object";
|
|
4
|
+
import { boolean as mini_boolean, extend, number, object, optional, partial, prefault, string } from "zod/mini";
|
|
5
|
+
import { isEqual as predicate_isEqual } from "es-toolkit/predicate";
|
|
6
|
+
import { __rspack_external__contentful_optimization_api_client_api_schemas_4192893e } from "./160.mjs";
|
|
4
7
|
import { __rspack_external__contentful_optimization_api_client_logger_f0d05f82 } from "./499.mjs";
|
|
5
8
|
import { __rspack_external__contentful_optimization_api_client_cba5a7ee } from "./942.mjs";
|
|
6
9
|
import { OPTIMIZATION_CORE_SDK_NAME, OPTIMIZATION_CORE_SDK_VERSION } from "./260.mjs";
|
|
7
10
|
import { PREVIEW_PANEL_SIGNALS_SYMBOL, PREVIEW_PANEL_SIGNAL_FNS_SYMBOL } from "./632.mjs";
|
|
11
|
+
function isNonNullish(value) {
|
|
12
|
+
return null != value;
|
|
13
|
+
}
|
|
14
|
+
function toError(value) {
|
|
15
|
+
if (value instanceof Error) return value;
|
|
16
|
+
return new Error(`Subscriber threw non-Error value: ${String(value)}`);
|
|
17
|
+
}
|
|
18
|
+
function toObservable(s) {
|
|
19
|
+
return {
|
|
20
|
+
get current () {
|
|
21
|
+
return cloneDeep(s.value);
|
|
22
|
+
},
|
|
23
|
+
subscribe (next) {
|
|
24
|
+
const dispose = effect(()=>{
|
|
25
|
+
next(cloneDeep(s.value));
|
|
26
|
+
});
|
|
27
|
+
return {
|
|
28
|
+
unsubscribe: dispose
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
subscribeOnce (next) {
|
|
32
|
+
let closed = false;
|
|
33
|
+
let isEffectActive = false;
|
|
34
|
+
let dispose = ()=>void 0;
|
|
35
|
+
const stop = ()=>{
|
|
36
|
+
if (closed) return;
|
|
37
|
+
closed = true;
|
|
38
|
+
if (isEffectActive) dispose();
|
|
39
|
+
};
|
|
40
|
+
dispose = effect(()=>{
|
|
41
|
+
if (closed) return;
|
|
42
|
+
const { value } = s;
|
|
43
|
+
if (!isNonNullish(value)) return;
|
|
44
|
+
closed = true;
|
|
45
|
+
let callbackError = null;
|
|
46
|
+
try {
|
|
47
|
+
next(cloneDeep(value));
|
|
48
|
+
} catch (error) {
|
|
49
|
+
callbackError = toError(error);
|
|
50
|
+
}
|
|
51
|
+
if (isEffectActive) dispose();
|
|
52
|
+
else queueMicrotask(dispose);
|
|
53
|
+
if (callbackError) throw callbackError;
|
|
54
|
+
});
|
|
55
|
+
isEffectActive = true;
|
|
56
|
+
return {
|
|
57
|
+
unsubscribe: stop
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function toDistinctObservable(s, isEqual) {
|
|
63
|
+
const observable = toObservable(s);
|
|
64
|
+
return {
|
|
65
|
+
get current () {
|
|
66
|
+
return observable.current;
|
|
67
|
+
},
|
|
68
|
+
subscribe (next) {
|
|
69
|
+
let hasPrevious = false;
|
|
70
|
+
let previous = cloneDeep(observable.current);
|
|
71
|
+
return observable.subscribe((value)=>{
|
|
72
|
+
if (hasPrevious && isEqual(previous, value)) return;
|
|
73
|
+
hasPrevious = true;
|
|
74
|
+
previous = cloneDeep(value);
|
|
75
|
+
next(value);
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
subscribeOnce (next) {
|
|
79
|
+
return observable.subscribeOnce(next);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const signals_changes = signal();
|
|
84
|
+
const blockedEvent = signal();
|
|
85
|
+
const consent = signal();
|
|
86
|
+
const signals_event = signal();
|
|
87
|
+
const online = signal(true);
|
|
88
|
+
const previewPanelAttached = signal(false);
|
|
89
|
+
const previewPanelOpen = signal(false);
|
|
90
|
+
const signals_selectedOptimizations = signal();
|
|
91
|
+
const canOptimize = computed(()=>void 0 !== signals_selectedOptimizations.value);
|
|
92
|
+
const signals_profile = signal();
|
|
93
|
+
const signals = {
|
|
94
|
+
blockedEvent: blockedEvent,
|
|
95
|
+
changes: signals_changes,
|
|
96
|
+
consent: consent,
|
|
97
|
+
event: signals_event,
|
|
98
|
+
online: online,
|
|
99
|
+
previewPanelAttached: previewPanelAttached,
|
|
100
|
+
previewPanelOpen: previewPanelOpen,
|
|
101
|
+
selectedOptimizations: signals_selectedOptimizations,
|
|
102
|
+
canOptimize: canOptimize,
|
|
103
|
+
profile: signals_profile
|
|
104
|
+
};
|
|
105
|
+
const signalFns = {
|
|
106
|
+
batch: batch,
|
|
107
|
+
computed: computed,
|
|
108
|
+
effect: effect,
|
|
109
|
+
untracked: untracked
|
|
110
|
+
};
|
|
111
|
+
const UniversalEventBuilderArgs = object({
|
|
112
|
+
campaign: optional(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.Campaign),
|
|
113
|
+
locale: optional(string()),
|
|
114
|
+
location: optional(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.GeoLocation),
|
|
115
|
+
page: optional(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.Page),
|
|
116
|
+
screen: optional(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.Screen),
|
|
117
|
+
userAgent: optional(string())
|
|
118
|
+
});
|
|
119
|
+
const EntryInteractionBuilderArgsBase = extend(UniversalEventBuilderArgs, {
|
|
120
|
+
componentId: string(),
|
|
121
|
+
experienceId: optional(string()),
|
|
122
|
+
variantIndex: optional(number())
|
|
123
|
+
});
|
|
124
|
+
const ViewBuilderArgs = extend(EntryInteractionBuilderArgsBase, {
|
|
125
|
+
sticky: optional(mini_boolean()),
|
|
126
|
+
viewId: string(),
|
|
127
|
+
viewDurationMs: number()
|
|
128
|
+
});
|
|
129
|
+
const FlagViewBuilderArgs = extend(EntryInteractionBuilderArgsBase, {
|
|
130
|
+
viewId: optional(string()),
|
|
131
|
+
viewDurationMs: optional(number())
|
|
132
|
+
});
|
|
133
|
+
const ClickBuilderArgs = EntryInteractionBuilderArgsBase;
|
|
134
|
+
const HoverBuilderArgs = extend(EntryInteractionBuilderArgsBase, {
|
|
135
|
+
hoverId: string(),
|
|
136
|
+
hoverDurationMs: number()
|
|
137
|
+
});
|
|
138
|
+
const IdentifyBuilderArgs = extend(UniversalEventBuilderArgs, {
|
|
139
|
+
traits: optional(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.Traits),
|
|
140
|
+
userId: string()
|
|
141
|
+
});
|
|
142
|
+
const PageViewBuilderArgs = extend(UniversalEventBuilderArgs, {
|
|
143
|
+
properties: optional(partial(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.Page))
|
|
144
|
+
});
|
|
145
|
+
const ScreenViewBuilderArgs = extend(UniversalEventBuilderArgs, {
|
|
146
|
+
name: string(),
|
|
147
|
+
properties: __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.Properties
|
|
148
|
+
});
|
|
149
|
+
const TrackBuilderArgs = extend(UniversalEventBuilderArgs, {
|
|
150
|
+
event: string(),
|
|
151
|
+
properties: optional(prefault(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.Properties, {}))
|
|
152
|
+
});
|
|
153
|
+
const DEFAULT_PAGE_PROPERTIES = {
|
|
154
|
+
path: '',
|
|
155
|
+
query: {},
|
|
156
|
+
referrer: '',
|
|
157
|
+
search: '',
|
|
158
|
+
title: '',
|
|
159
|
+
url: ''
|
|
160
|
+
};
|
|
161
|
+
class EventBuilder {
|
|
162
|
+
app;
|
|
163
|
+
channel;
|
|
164
|
+
library;
|
|
165
|
+
getLocale;
|
|
166
|
+
getPageProperties;
|
|
167
|
+
getUserAgent;
|
|
168
|
+
constructor(config){
|
|
169
|
+
const { app, channel, library, getLocale, getPageProperties, getUserAgent } = config;
|
|
170
|
+
this.app = app;
|
|
171
|
+
this.channel = channel;
|
|
172
|
+
this.library = library;
|
|
173
|
+
this.getLocale = getLocale ?? (()=>'en-US');
|
|
174
|
+
this.getPageProperties = getPageProperties ?? (()=>DEFAULT_PAGE_PROPERTIES);
|
|
175
|
+
this.getUserAgent = getUserAgent ?? (()=>void 0);
|
|
176
|
+
}
|
|
177
|
+
buildUniversalEventProperties({ campaign = {}, locale, location, page, screen, userAgent }) {
|
|
178
|
+
const timestamp = new Date().toISOString();
|
|
179
|
+
return {
|
|
180
|
+
channel: this.channel,
|
|
181
|
+
context: {
|
|
182
|
+
app: this.app,
|
|
183
|
+
campaign,
|
|
184
|
+
gdpr: {
|
|
185
|
+
isConsentGiven: true
|
|
186
|
+
},
|
|
187
|
+
library: this.library,
|
|
188
|
+
locale: locale ?? this.getLocale() ?? 'en-US',
|
|
189
|
+
location,
|
|
190
|
+
page: page ?? this.getPageProperties(),
|
|
191
|
+
screen,
|
|
192
|
+
userAgent: userAgent ?? this.getUserAgent()
|
|
193
|
+
},
|
|
194
|
+
messageId: crypto.randomUUID(),
|
|
195
|
+
originalTimestamp: timestamp,
|
|
196
|
+
sentAt: timestamp,
|
|
197
|
+
timestamp
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
buildEntryInteractionBase(universal, componentId, experienceId, variantIndex) {
|
|
201
|
+
return {
|
|
202
|
+
...this.buildUniversalEventProperties(universal),
|
|
203
|
+
componentType: 'Entry',
|
|
204
|
+
componentId,
|
|
205
|
+
experienceId,
|
|
206
|
+
variantIndex: variantIndex ?? 0
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
buildView(args) {
|
|
210
|
+
const { componentId, viewId, experienceId, variantIndex, viewDurationMs, ...universal } = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(ViewBuilderArgs, args);
|
|
211
|
+
return {
|
|
212
|
+
...this.buildEntryInteractionBase(universal, componentId, experienceId, variantIndex),
|
|
213
|
+
type: 'component',
|
|
214
|
+
viewId,
|
|
215
|
+
viewDurationMs
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
buildClick(args) {
|
|
219
|
+
const { componentId, experienceId, variantIndex, ...universal } = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(ClickBuilderArgs, args);
|
|
220
|
+
return {
|
|
221
|
+
...this.buildEntryInteractionBase(universal, componentId, experienceId, variantIndex),
|
|
222
|
+
type: 'component_click'
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
buildHover(args) {
|
|
226
|
+
const { hoverId, componentId, experienceId, hoverDurationMs, variantIndex, ...universal } = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(HoverBuilderArgs, args);
|
|
227
|
+
return {
|
|
228
|
+
...this.buildEntryInteractionBase(universal, componentId, experienceId, variantIndex),
|
|
229
|
+
type: 'component_hover',
|
|
230
|
+
hoverId,
|
|
231
|
+
hoverDurationMs
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
buildFlagView(args) {
|
|
235
|
+
const { componentId, experienceId, variantIndex, viewId, viewDurationMs, ...universal } = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(FlagViewBuilderArgs, args);
|
|
236
|
+
return {
|
|
237
|
+
...this.buildEntryInteractionBase(universal, componentId, experienceId, variantIndex),
|
|
238
|
+
...void 0 === viewDurationMs ? {} : {
|
|
239
|
+
viewDurationMs
|
|
240
|
+
},
|
|
241
|
+
...void 0 === viewId ? {} : {
|
|
242
|
+
viewId
|
|
243
|
+
},
|
|
244
|
+
type: 'component',
|
|
245
|
+
componentType: 'Variable'
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
buildIdentify(args) {
|
|
249
|
+
const { traits = {}, userId, ...universal } = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(IdentifyBuilderArgs, args);
|
|
250
|
+
return {
|
|
251
|
+
...this.buildUniversalEventProperties(universal),
|
|
252
|
+
type: 'identify',
|
|
253
|
+
traits,
|
|
254
|
+
userId
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
buildPageView(args = {}) {
|
|
258
|
+
const { properties = {}, ...universal } = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(PageViewBuilderArgs, args);
|
|
259
|
+
const pageProperties = this.getPageProperties();
|
|
260
|
+
const merged = merge({
|
|
261
|
+
...pageProperties,
|
|
262
|
+
title: pageProperties.title ?? DEFAULT_PAGE_PROPERTIES.title
|
|
263
|
+
}, properties);
|
|
264
|
+
const { context: { screen: _, ...universalContext }, ...universalProperties } = this.buildUniversalEventProperties(universal);
|
|
265
|
+
const context = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.PageEventContext, universalContext);
|
|
266
|
+
return {
|
|
267
|
+
...universalProperties,
|
|
268
|
+
context,
|
|
269
|
+
type: 'page',
|
|
270
|
+
properties: merged
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
buildScreenView(args) {
|
|
274
|
+
const { name, properties, ...universal } = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(ScreenViewBuilderArgs, args);
|
|
275
|
+
const { context: { page: _, ...universalContext }, ...universalProperties } = this.buildUniversalEventProperties(universal);
|
|
276
|
+
const context = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.ScreenEventContext, universalContext);
|
|
277
|
+
return {
|
|
278
|
+
...universalProperties,
|
|
279
|
+
context,
|
|
280
|
+
type: 'screen',
|
|
281
|
+
name,
|
|
282
|
+
properties
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
buildTrack(args) {
|
|
286
|
+
const { event, properties = {}, ...universal } = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(TrackBuilderArgs, args);
|
|
287
|
+
return {
|
|
288
|
+
...this.buildUniversalEventProperties(universal),
|
|
289
|
+
type: 'track',
|
|
290
|
+
event,
|
|
291
|
+
properties
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
const events_EventBuilder = EventBuilder;
|
|
296
|
+
class InterceptorManager {
|
|
297
|
+
interceptors = new Map();
|
|
298
|
+
nextId = 0;
|
|
299
|
+
add(interceptor) {
|
|
300
|
+
const { nextId: id } = this;
|
|
301
|
+
this.nextId += 1;
|
|
302
|
+
this.interceptors.set(id, interceptor);
|
|
303
|
+
return id;
|
|
304
|
+
}
|
|
305
|
+
remove(id) {
|
|
306
|
+
return this.interceptors.delete(id);
|
|
307
|
+
}
|
|
308
|
+
clear() {
|
|
309
|
+
this.interceptors.clear();
|
|
310
|
+
}
|
|
311
|
+
count() {
|
|
312
|
+
return this.interceptors.size;
|
|
313
|
+
}
|
|
314
|
+
async run(input) {
|
|
315
|
+
const fns = Array.from(this.interceptors.values());
|
|
316
|
+
let acc = input;
|
|
317
|
+
for (const fn of fns)acc = await fn(cloneDeep(acc));
|
|
318
|
+
return acc;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
8
321
|
const FlagsResolver = {
|
|
9
322
|
resolve (changes) {
|
|
10
323
|
if (!changes) return {};
|
|
@@ -16,7 +329,7 @@ const FlagsResolver = {
|
|
|
16
329
|
}
|
|
17
330
|
};
|
|
18
331
|
const resolvers_FlagsResolver = FlagsResolver;
|
|
19
|
-
const logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('
|
|
332
|
+
const logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('Optimization');
|
|
20
333
|
const RESOLUTION_WARNING_BASE = 'Could not resolve Merge Tag value:';
|
|
21
334
|
const getAtPath = (value, path)=>{
|
|
22
335
|
if (!value || 'object' != typeof value) return;
|
|
@@ -59,177 +372,284 @@ const MergeTagValueResolver = {
|
|
|
59
372
|
}
|
|
60
373
|
};
|
|
61
374
|
const resolvers_MergeTagValueResolver = MergeTagValueResolver;
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return
|
|
375
|
+
const OptimizedEntryResolver_logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('Optimization');
|
|
376
|
+
const OptimizedEntryResolver_RESOLUTION_WARNING_BASE = 'Could not resolve optimized entry variant:';
|
|
377
|
+
function resolve(entry, selectedOptimizations) {
|
|
378
|
+
OptimizedEntryResolver_logger.debug(`Resolving optimized entry for baseline entry ${entry.sys.id}`);
|
|
379
|
+
if (!selectedOptimizations?.length) {
|
|
380
|
+
OptimizedEntryResolver_logger.warn(`${OptimizedEntryResolver_RESOLUTION_WARNING_BASE} no selectedOptimizations exist for the current profile`);
|
|
381
|
+
return {
|
|
382
|
+
entry
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
if (!(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isOptimizedEntry)(entry)) {
|
|
386
|
+
OptimizedEntryResolver_logger.warn(`${OptimizedEntryResolver_RESOLUTION_WARNING_BASE} entry ${entry.sys.id} is not optimized`);
|
|
387
|
+
return {
|
|
388
|
+
entry
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
const optimizationEntry = OptimizedEntryResolver.getOptimizationEntry({
|
|
392
|
+
optimizedEntry: entry,
|
|
393
|
+
selectedOptimizations
|
|
394
|
+
}, true);
|
|
395
|
+
if (!optimizationEntry) {
|
|
396
|
+
OptimizedEntryResolver_logger.warn(`${OptimizedEntryResolver_RESOLUTION_WARNING_BASE} could not find an optimization entry for ${entry.sys.id}`);
|
|
397
|
+
return {
|
|
398
|
+
entry
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
const selectedOptimization = OptimizedEntryResolver.getSelectedOptimization({
|
|
402
|
+
optimizationEntry,
|
|
403
|
+
selectedOptimizations
|
|
404
|
+
}, true);
|
|
405
|
+
const selectedVariantIndex = selectedOptimization?.variantIndex ?? 0;
|
|
406
|
+
if (0 === selectedVariantIndex) {
|
|
407
|
+
OptimizedEntryResolver_logger.debug(`Resolved optimization entry for entry ${entry.sys.id} is baseline`);
|
|
408
|
+
return {
|
|
409
|
+
entry
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
const selectedVariant = OptimizedEntryResolver.getSelectedVariant({
|
|
413
|
+
optimizedEntry: entry,
|
|
414
|
+
optimizationEntry,
|
|
415
|
+
selectedVariantIndex
|
|
416
|
+
}, true);
|
|
417
|
+
if (!selectedVariant) {
|
|
418
|
+
OptimizedEntryResolver_logger.warn(`${OptimizedEntryResolver_RESOLUTION_WARNING_BASE} could not find a valid replacement variant entry for ${entry.sys.id}`);
|
|
419
|
+
return {
|
|
420
|
+
entry
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
const selectedVariantEntry = OptimizedEntryResolver.getSelectedVariantEntry({
|
|
424
|
+
optimizationEntry,
|
|
425
|
+
selectedVariant
|
|
426
|
+
}, true);
|
|
427
|
+
if (selectedVariantEntry) OptimizedEntryResolver_logger.debug(`Entry ${entry.sys.id} has been resolved to variant entry ${selectedVariantEntry.sys.id}`);
|
|
428
|
+
else {
|
|
429
|
+
OptimizedEntryResolver_logger.warn(`${OptimizedEntryResolver_RESOLUTION_WARNING_BASE} could not find a valid replacement variant entry for ${entry.sys.id}`);
|
|
430
|
+
return {
|
|
431
|
+
entry
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
return {
|
|
435
|
+
entry: selectedVariantEntry,
|
|
436
|
+
selectedOptimization
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
const OptimizedEntryResolver = {
|
|
440
|
+
getOptimizationEntry ({ optimizedEntry, selectedOptimizations }, skipValidation = false) {
|
|
441
|
+
if (!skipValidation && (!selectedOptimizations.length || !(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isOptimizedEntry)(optimizedEntry))) return;
|
|
442
|
+
const optimizationEntry = optimizedEntry.fields.nt_experiences.filter((maybeOptimization)=>(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isOptimizationEntry)(maybeOptimization)).find((optimizationEntry)=>selectedOptimizations.some(({ experienceId })=>experienceId === optimizationEntry.fields.nt_experience_id));
|
|
443
|
+
return optimizationEntry;
|
|
69
444
|
},
|
|
70
|
-
|
|
71
|
-
if (!skipValidation && (!
|
|
72
|
-
const
|
|
73
|
-
return
|
|
445
|
+
getSelectedOptimization ({ optimizationEntry, selectedOptimizations }, skipValidation = false) {
|
|
446
|
+
if (!skipValidation && (!selectedOptimizations.length || !(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isOptimizationEntry)(optimizationEntry))) return;
|
|
447
|
+
const selectedOptimization = selectedOptimizations.find(({ experienceId })=>experienceId === optimizationEntry.fields.nt_experience_id);
|
|
448
|
+
return selectedOptimization;
|
|
74
449
|
},
|
|
75
|
-
getSelectedVariant ({
|
|
76
|
-
if (!skipValidation && (!(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.
|
|
77
|
-
const relevantVariants =
|
|
450
|
+
getSelectedVariant ({ optimizedEntry, optimizationEntry, selectedVariantIndex }, skipValidation = false) {
|
|
451
|
+
if (!skipValidation && (!(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isOptimizedEntry)(optimizedEntry) || !(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isOptimizationEntry)(optimizationEntry))) return;
|
|
452
|
+
const relevantVariants = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.normalizeOptimizationConfig)(optimizationEntry.fields.nt_config).components.filter((component)=>(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isEntryReplacementComponent)(component) && !component.baseline.hidden).find((component)=>component.baseline.id === optimizedEntry.sys.id)?.variants;
|
|
78
453
|
if (!relevantVariants?.length) return;
|
|
79
454
|
return relevantVariants.at(selectedVariantIndex - 1);
|
|
80
455
|
},
|
|
81
|
-
getSelectedVariantEntry ({
|
|
82
|
-
if (!skipValidation && (!(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.
|
|
83
|
-
const selectedVariantEntry =
|
|
456
|
+
getSelectedVariantEntry ({ optimizationEntry, selectedVariant }, skipValidation = false) {
|
|
457
|
+
if (!skipValidation && (!(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isOptimizationEntry)(optimizationEntry) || !(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isEntryReplacementVariant)(selectedVariant))) return;
|
|
458
|
+
const selectedVariantEntry = optimizationEntry.fields.nt_variants?.find((variant)=>variant.sys.id === selectedVariant.id);
|
|
84
459
|
return (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isEntry)(selectedVariantEntry) ? selectedVariantEntry : void 0;
|
|
85
460
|
},
|
|
86
|
-
resolve
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const selectedPersonalization = PersonalizedEntryResolver.getSelectedPersonalization({
|
|
111
|
-
personalizationEntry,
|
|
112
|
-
selectedPersonalizations
|
|
113
|
-
}, true);
|
|
114
|
-
const selectedVariantIndex = selectedPersonalization?.variantIndex ?? 0;
|
|
115
|
-
if (0 === selectedVariantIndex) {
|
|
116
|
-
PersonalizedEntryResolver_logger.debug(`Resolved personalization entry for entry ${entry.sys.id} is baseline`);
|
|
117
|
-
return {
|
|
118
|
-
entry
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
const selectedVariant = PersonalizedEntryResolver.getSelectedVariant({
|
|
122
|
-
personalizedEntry: entry,
|
|
123
|
-
personalizationEntry,
|
|
124
|
-
selectedVariantIndex
|
|
125
|
-
}, true);
|
|
126
|
-
if (!selectedVariant) {
|
|
127
|
-
PersonalizedEntryResolver_logger.warn(`${PersonalizedEntryResolver_RESOLUTION_WARNING_BASE} could not find a valid replacement variant entry for ${entry.sys.id}`);
|
|
128
|
-
return {
|
|
129
|
-
entry
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
const selectedVariantEntry = PersonalizedEntryResolver.getSelectedVariantEntry({
|
|
133
|
-
personalizationEntry,
|
|
134
|
-
selectedVariant
|
|
135
|
-
}, true);
|
|
136
|
-
if (selectedVariantEntry) PersonalizedEntryResolver_logger.debug(`Entry ${entry.sys.id} has been resolved to variant entry ${selectedVariantEntry.sys.id}`);
|
|
137
|
-
else {
|
|
138
|
-
PersonalizedEntryResolver_logger.warn(`${PersonalizedEntryResolver_RESOLUTION_WARNING_BASE} could not find a valid replacement variant entry for ${entry.sys.id}`);
|
|
139
|
-
return {
|
|
140
|
-
entry
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
return {
|
|
144
|
-
entry: selectedVariantEntry,
|
|
145
|
-
personalization: selectedPersonalization
|
|
461
|
+
resolve: resolve
|
|
462
|
+
};
|
|
463
|
+
const resolvers_OptimizedEntryResolver = OptimizedEntryResolver;
|
|
464
|
+
class CoreBase {
|
|
465
|
+
api;
|
|
466
|
+
eventBuilder;
|
|
467
|
+
config;
|
|
468
|
+
flagsResolver = resolvers_FlagsResolver;
|
|
469
|
+
mergeTagValueResolver = resolvers_MergeTagValueResolver;
|
|
470
|
+
optimizedEntryResolver = resolvers_OptimizedEntryResolver;
|
|
471
|
+
interceptors = {
|
|
472
|
+
event: new InterceptorManager(),
|
|
473
|
+
state: new InterceptorManager()
|
|
474
|
+
};
|
|
475
|
+
constructor(config, api = {}){
|
|
476
|
+
this.config = config;
|
|
477
|
+
const { eventBuilder, logLevel, environment, clientId, fetchOptions } = config;
|
|
478
|
+
__rspack_external__contentful_optimization_api_client_logger_f0d05f82.logger.addSink(new __rspack_external__contentful_optimization_api_client_logger_f0d05f82.ConsoleLogSink(logLevel));
|
|
479
|
+
const apiConfig = {
|
|
480
|
+
clientId,
|
|
481
|
+
environment,
|
|
482
|
+
fetchOptions,
|
|
483
|
+
experience: api.experience,
|
|
484
|
+
insights: api.insights
|
|
146
485
|
};
|
|
486
|
+
this.api = new __rspack_external__contentful_optimization_api_client_cba5a7ee.ApiClient(apiConfig);
|
|
487
|
+
this.eventBuilder = new events_EventBuilder(eventBuilder ?? {
|
|
488
|
+
channel: 'server',
|
|
489
|
+
library: {
|
|
490
|
+
name: OPTIMIZATION_CORE_SDK_NAME,
|
|
491
|
+
version: OPTIMIZATION_CORE_SDK_VERSION
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
getFlag(name, changes) {
|
|
496
|
+
return this.flagsResolver.resolve(changes)[name];
|
|
147
497
|
}
|
|
498
|
+
resolveOptimizedEntry(entry, selectedOptimizations) {
|
|
499
|
+
return this.optimizedEntryResolver.resolve(entry, selectedOptimizations);
|
|
500
|
+
}
|
|
501
|
+
getMergeTagValue(embeddedEntryNodeTarget, profile) {
|
|
502
|
+
return this.mergeTagValueResolver.resolve(embeddedEntryNodeTarget, profile);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
const src_CoreBase = CoreBase;
|
|
506
|
+
const coreLogger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('CoreStateful');
|
|
507
|
+
const CONSENT_EVENT_TYPE_MAP = {
|
|
508
|
+
trackView: 'component',
|
|
509
|
+
trackFlagView: 'component',
|
|
510
|
+
trackClick: 'component_click',
|
|
511
|
+
trackHover: 'component_hover'
|
|
148
512
|
};
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
513
|
+
class CoreStatefulEventEmitter extends src_CoreBase {
|
|
514
|
+
flagObservables = new Map();
|
|
515
|
+
getFlag(name, changes = signals_changes.value) {
|
|
516
|
+
const value = super.getFlag(name, changes);
|
|
517
|
+
const payload = this.buildFlagViewBuilderArgs(name, changes);
|
|
518
|
+
this.trackFlagView(payload).catch((error)=>{
|
|
519
|
+
__rspack_external__contentful_optimization_api_client_logger_f0d05f82.logger.warn(`Failed to emit "flag view" event for "${name}"`, String(error));
|
|
520
|
+
});
|
|
521
|
+
return value;
|
|
522
|
+
}
|
|
523
|
+
resolveOptimizedEntry(entry, selectedOptimizations = signals_selectedOptimizations.value) {
|
|
524
|
+
return super.resolveOptimizedEntry(entry, selectedOptimizations);
|
|
525
|
+
}
|
|
526
|
+
getMergeTagValue(embeddedEntryNodeTarget, profile = signals_profile.value) {
|
|
527
|
+
return super.getMergeTagValue(embeddedEntryNodeTarget, profile);
|
|
528
|
+
}
|
|
529
|
+
async identify(payload) {
|
|
530
|
+
const { profile, ...builderArgs } = payload;
|
|
531
|
+
return await this.sendExperienceEvent('identify', [
|
|
532
|
+
payload
|
|
533
|
+
], this.eventBuilder.buildIdentify(builderArgs), profile);
|
|
534
|
+
}
|
|
535
|
+
async page(payload = {}) {
|
|
536
|
+
const { profile, ...builderArgs } = payload;
|
|
537
|
+
return await this.sendExperienceEvent('page', [
|
|
538
|
+
payload
|
|
539
|
+
], this.eventBuilder.buildPageView(builderArgs), profile);
|
|
540
|
+
}
|
|
541
|
+
async screen(payload) {
|
|
542
|
+
const { profile, ...builderArgs } = payload;
|
|
543
|
+
return await this.sendExperienceEvent('screen', [
|
|
544
|
+
payload
|
|
545
|
+
], this.eventBuilder.buildScreenView(builderArgs), profile);
|
|
546
|
+
}
|
|
547
|
+
async track(payload) {
|
|
548
|
+
const { profile, ...builderArgs } = payload;
|
|
549
|
+
return await this.sendExperienceEvent('track', [
|
|
550
|
+
payload
|
|
551
|
+
], this.eventBuilder.buildTrack(builderArgs), profile);
|
|
552
|
+
}
|
|
553
|
+
async trackView(payload) {
|
|
554
|
+
const { profile, ...builderArgs } = payload;
|
|
555
|
+
let result;
|
|
556
|
+
if (payload.sticky) result = await this.sendExperienceEvent('trackView', [
|
|
557
|
+
payload
|
|
558
|
+
], this.eventBuilder.buildView(builderArgs), profile);
|
|
559
|
+
await this.sendInsightsEvent('trackView', [
|
|
560
|
+
payload
|
|
561
|
+
], this.eventBuilder.buildView(builderArgs), profile);
|
|
562
|
+
return result;
|
|
563
|
+
}
|
|
564
|
+
async trackClick(payload) {
|
|
565
|
+
await this.sendInsightsEvent('trackClick', [
|
|
566
|
+
payload
|
|
567
|
+
], this.eventBuilder.buildClick(payload));
|
|
568
|
+
}
|
|
569
|
+
async trackHover(payload) {
|
|
570
|
+
await this.sendInsightsEvent('trackHover', [
|
|
571
|
+
payload
|
|
572
|
+
], this.eventBuilder.buildHover(payload));
|
|
573
|
+
}
|
|
574
|
+
async trackFlagView(payload) {
|
|
575
|
+
await this.sendInsightsEvent('trackFlagView', [
|
|
576
|
+
payload
|
|
577
|
+
], this.eventBuilder.buildFlagView(payload));
|
|
578
|
+
}
|
|
579
|
+
hasConsent(name) {
|
|
580
|
+
const { [name]: mappedEventType } = CONSENT_EVENT_TYPE_MAP;
|
|
581
|
+
const isAllowed = void 0 !== mappedEventType ? this.allowedEventTypes.includes(mappedEventType) : this.allowedEventTypes.some((eventType)=>eventType === name);
|
|
582
|
+
return !!consent.value || isAllowed;
|
|
583
|
+
}
|
|
584
|
+
onBlockedByConsent(name, args) {
|
|
585
|
+
coreLogger.warn(`Event "${name}" was blocked due to lack of consent; payload: ${JSON.stringify(args)}`);
|
|
586
|
+
this.reportBlockedEvent('consent', name, args);
|
|
587
|
+
}
|
|
588
|
+
async sendExperienceEvent(method, args, event, _profile) {
|
|
589
|
+
if (!this.hasConsent(method)) return void this.onBlockedByConsent(method, args);
|
|
590
|
+
return await this.experienceQueue.send(event);
|
|
591
|
+
}
|
|
592
|
+
async sendInsightsEvent(method, args, event, _profile) {
|
|
593
|
+
if (!this.hasConsent(method)) return void this.onBlockedByConsent(method, args);
|
|
594
|
+
await this.insightsQueue.send(event);
|
|
595
|
+
}
|
|
596
|
+
buildFlagViewBuilderArgs(name, changes = signals_changes.value) {
|
|
597
|
+
const change = changes?.find((candidate)=>candidate.key === name);
|
|
598
|
+
return {
|
|
599
|
+
componentId: name,
|
|
600
|
+
experienceId: change?.meta.experienceId,
|
|
601
|
+
variantIndex: change?.meta.variantIndex
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
getFlagObservable(name) {
|
|
605
|
+
const existingObservable = this.flagObservables.get(name);
|
|
606
|
+
if (existingObservable) return existingObservable;
|
|
607
|
+
const trackFlagView = this.trackFlagView.bind(this);
|
|
608
|
+
const buildFlagViewBuilderArgs = this.buildFlagViewBuilderArgs.bind(this);
|
|
609
|
+
const valueSignal = signalFns.computed(()=>super.getFlag(name, signals_changes.value));
|
|
610
|
+
const distinctObservable = toDistinctObservable(valueSignal, predicate_isEqual);
|
|
611
|
+
const trackedObservable = {
|
|
612
|
+
get current () {
|
|
613
|
+
const { current: value } = distinctObservable;
|
|
614
|
+
const payload = buildFlagViewBuilderArgs(name, signals_changes.value);
|
|
615
|
+
trackFlagView(payload).catch((error)=>{
|
|
616
|
+
__rspack_external__contentful_optimization_api_client_logger_f0d05f82.logger.warn(`Failed to emit "flag view" event for "${name}"`, String(error));
|
|
617
|
+
});
|
|
618
|
+
return value;
|
|
619
|
+
},
|
|
620
|
+
subscribe: (next)=>distinctObservable.subscribe((value)=>{
|
|
621
|
+
const payload = buildFlagViewBuilderArgs(name, signals_changes.value);
|
|
622
|
+
trackFlagView(payload).catch((error)=>{
|
|
623
|
+
__rspack_external__contentful_optimization_api_client_logger_f0d05f82.logger.warn(`Failed to emit "flag view" event for "${name}"`, String(error));
|
|
624
|
+
});
|
|
625
|
+
next(value);
|
|
626
|
+
}),
|
|
627
|
+
subscribeOnce: (next)=>distinctObservable.subscribeOnce((value)=>{
|
|
628
|
+
const payload = buildFlagViewBuilderArgs(name, signals_changes.value);
|
|
629
|
+
trackFlagView(payload).catch((error)=>{
|
|
630
|
+
__rspack_external__contentful_optimization_api_client_logger_f0d05f82.logger.warn(`Failed to emit "flag view" event for "${name}"`, String(error));
|
|
631
|
+
});
|
|
632
|
+
next(value);
|
|
633
|
+
})
|
|
634
|
+
};
|
|
635
|
+
this.flagObservables.set(name, trackedObservable);
|
|
636
|
+
return trackedObservable;
|
|
637
|
+
}
|
|
638
|
+
reportBlockedEvent(reason, method, args) {
|
|
639
|
+
const event = {
|
|
640
|
+
reason,
|
|
641
|
+
method,
|
|
642
|
+
args
|
|
643
|
+
};
|
|
644
|
+
try {
|
|
645
|
+
this.onEventBlocked?.(event);
|
|
646
|
+
} catch (error) {
|
|
647
|
+
coreLogger.warn(`onEventBlocked callback failed for method "${method}"`, error);
|
|
169
648
|
}
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
const signals = {
|
|
173
|
-
blockedEvent: blockedEvent,
|
|
174
|
-
changes: signals_changes,
|
|
175
|
-
consent: consent,
|
|
176
|
-
event: signals_event,
|
|
177
|
-
flags: flags,
|
|
178
|
-
online: online,
|
|
179
|
-
previewPanelAttached: previewPanelAttached,
|
|
180
|
-
previewPanelOpen: previewPanelOpen,
|
|
181
|
-
personalizations: signals_personalizations,
|
|
182
|
-
profile: signals_profile
|
|
183
|
-
};
|
|
184
|
-
const signalFns = {
|
|
185
|
-
batch: batch,
|
|
186
|
-
computed: computed,
|
|
187
|
-
effect: effect,
|
|
188
|
-
untracked: untracked
|
|
189
|
-
};
|
|
190
|
-
const isFunction = (v)=>'function' == typeof v;
|
|
191
|
-
const nameToString = (name)=>'string' == typeof name ? name : 'symbol' == typeof name ? name.description ?? String(name) : String(name);
|
|
192
|
-
const isOnBlockedKey = (v)=>'string' == typeof v || 'symbol' == typeof v;
|
|
193
|
-
const isAsyncFunction = (fn)=>'[object AsyncFunction]' === Object.prototype.toString.call(fn);
|
|
194
|
-
function guardedBy(predicateName, opts) {
|
|
195
|
-
return function(_value, context) {
|
|
196
|
-
const decoratedName = nameToString(context.name);
|
|
197
|
-
context.addInitializer(function() {
|
|
198
|
-
const originalUnknown = Reflect.get(this, context.name);
|
|
199
|
-
if (!isFunction(originalUnknown)) return;
|
|
200
|
-
const original = originalUnknown;
|
|
201
|
-
const originalIsAsync = isAsyncFunction(original);
|
|
202
|
-
const resolvePredicate = (self)=>{
|
|
203
|
-
const { [predicateName]: cand } = self;
|
|
204
|
-
if (!isFunction(cand)) throw new TypeError(`@guardedBy expects predicate "${String(predicateName)}" to be a synchronous function.`);
|
|
205
|
-
return cand;
|
|
206
|
-
};
|
|
207
|
-
const computeAllowed = (self, args)=>{
|
|
208
|
-
const pred = resolvePredicate(self);
|
|
209
|
-
const ok = Boolean(pred.call(self, decoratedName, args));
|
|
210
|
-
return opts?.invert === true ? !ok : ok;
|
|
211
|
-
};
|
|
212
|
-
const runOnBlocked = (self, args)=>{
|
|
213
|
-
const { onBlocked } = opts ?? {};
|
|
214
|
-
if (void 0 === onBlocked) return;
|
|
215
|
-
if (isFunction(onBlocked)) return void onBlocked.call(self, decoratedName, args);
|
|
216
|
-
if (isOnBlockedKey(onBlocked)) {
|
|
217
|
-
const { [onBlocked]: handlerCandidate } = self;
|
|
218
|
-
if (isFunction(handlerCandidate)) handlerCandidate.call(self, decoratedName, args);
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
const blockedReturn = ()=>originalIsAsync ? Promise.resolve(void 0) : void 0;
|
|
222
|
-
const wrapped = function(...args) {
|
|
223
|
-
if (!computeAllowed(this, args)) {
|
|
224
|
-
runOnBlocked(this, args);
|
|
225
|
-
return blockedReturn();
|
|
226
|
-
}
|
|
227
|
-
return original.call(this, ...args);
|
|
228
|
-
};
|
|
229
|
-
Reflect.set(this, context.name, wrapped);
|
|
230
|
-
});
|
|
231
|
-
};
|
|
649
|
+
blockedEvent.value = event;
|
|
650
|
+
}
|
|
232
651
|
}
|
|
652
|
+
const src_CoreStatefulEventEmitter = CoreStatefulEventEmitter;
|
|
233
653
|
const toPositiveInt = (value, fallback)=>{
|
|
234
654
|
if (!Number.isFinite(value) || void 0 === value || value < 1) return fallback;
|
|
235
655
|
return Math.floor(value);
|
|
@@ -239,6 +659,7 @@ const toRatio = (value, fallback)=>{
|
|
|
239
659
|
return Math.min(1, Math.max(0, value));
|
|
240
660
|
};
|
|
241
661
|
const DEFAULT_QUEUE_FLUSH_POLICY = {
|
|
662
|
+
flushIntervalMs: 30000,
|
|
242
663
|
baseBackoffMs: 500,
|
|
243
664
|
maxBackoffMs: 30000,
|
|
244
665
|
jitterRatio: 0.2,
|
|
@@ -246,17 +667,19 @@ const DEFAULT_QUEUE_FLUSH_POLICY = {
|
|
|
246
667
|
circuitOpenMs: 120000
|
|
247
668
|
};
|
|
248
669
|
const resolveQueueFlushPolicy = (policy, defaults = DEFAULT_QUEUE_FLUSH_POLICY)=>{
|
|
249
|
-
const
|
|
250
|
-
const
|
|
670
|
+
const configuredPolicy = policy ?? {};
|
|
671
|
+
const baseBackoffMs = toPositiveInt(configuredPolicy.baseBackoffMs, defaults.baseBackoffMs);
|
|
672
|
+
const maxBackoffMs = Math.max(baseBackoffMs, toPositiveInt(configuredPolicy.maxBackoffMs, defaults.maxBackoffMs));
|
|
251
673
|
return {
|
|
674
|
+
flushIntervalMs: toPositiveInt(configuredPolicy.flushIntervalMs, defaults.flushIntervalMs),
|
|
252
675
|
baseBackoffMs,
|
|
253
676
|
maxBackoffMs,
|
|
254
|
-
jitterRatio: toRatio(
|
|
255
|
-
maxConsecutiveFailures: toPositiveInt(
|
|
256
|
-
circuitOpenMs: toPositiveInt(
|
|
257
|
-
onCircuitOpen:
|
|
258
|
-
onFlushFailure:
|
|
259
|
-
onFlushRecovered:
|
|
677
|
+
jitterRatio: toRatio(configuredPolicy.jitterRatio, defaults.jitterRatio),
|
|
678
|
+
maxConsecutiveFailures: toPositiveInt(configuredPolicy.maxConsecutiveFailures, defaults.maxConsecutiveFailures),
|
|
679
|
+
circuitOpenMs: toPositiveInt(configuredPolicy.circuitOpenMs, defaults.circuitOpenMs),
|
|
680
|
+
onCircuitOpen: configuredPolicy.onCircuitOpen,
|
|
681
|
+
onFlushFailure: configuredPolicy.onFlushFailure,
|
|
682
|
+
onFlushRecovered: configuredPolicy.onFlushRecovered
|
|
260
683
|
};
|
|
261
684
|
};
|
|
262
685
|
const computeQueueFlushRetryDelayMs = (options)=>{
|
|
@@ -282,6 +705,23 @@ const createQueueFlushFailureWindow = (options)=>{
|
|
|
282
705
|
circuitOpenUntil
|
|
283
706
|
};
|
|
284
707
|
};
|
|
708
|
+
const STATEFUL_RUNTIME_LOCK_KEY = '__ctfl_optimization_stateful_runtime_lock__';
|
|
709
|
+
const getStatefulRuntimeLock = ()=>{
|
|
710
|
+
const singletonGlobal = globalThis;
|
|
711
|
+
singletonGlobal[STATEFUL_RUNTIME_LOCK_KEY] ??= {
|
|
712
|
+
owner: void 0
|
|
713
|
+
};
|
|
714
|
+
return singletonGlobal[STATEFUL_RUNTIME_LOCK_KEY];
|
|
715
|
+
};
|
|
716
|
+
const acquireStatefulRuntimeSingleton = (owner)=>{
|
|
717
|
+
const lock = getStatefulRuntimeLock();
|
|
718
|
+
if (lock.owner) throw new Error(`Stateful Optimization SDK already initialized (${lock.owner}). Only one stateful instance is supported per runtime.`);
|
|
719
|
+
lock.owner = owner;
|
|
720
|
+
};
|
|
721
|
+
const releaseStatefulRuntimeSingleton = (owner)=>{
|
|
722
|
+
const lock = getStatefulRuntimeLock();
|
|
723
|
+
if (lock.owner === owner) lock.owner = void 0;
|
|
724
|
+
};
|
|
285
725
|
class QueueFlushRuntime {
|
|
286
726
|
circuitOpenUntil = 0;
|
|
287
727
|
flushFailureCount = 0;
|
|
@@ -381,1255 +821,122 @@ class QueueFlushRuntime {
|
|
|
381
821
|
if ('onFlushRecovered' === callbackName) return void this.policy.onFlushRecovered?.(payload);
|
|
382
822
|
if ('onCircuitOpen' === callbackName) return void this.policy.onCircuitOpen?.(payload);
|
|
383
823
|
this.policy.onFlushFailure?.(payload);
|
|
384
|
-
} catch (error) {
|
|
385
|
-
this.onCallbackError?.(callbackName, error);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
const ProductBase_logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('ProductBase');
|
|
390
|
-
const defaultAllowedEvents = [
|
|
391
|
-
'identify',
|
|
392
|
-
'page',
|
|
393
|
-
'screen'
|
|
394
|
-
];
|
|
395
|
-
class ProductBase {
|
|
396
|
-
allowedEventTypes;
|
|
397
|
-
builder;
|
|
398
|
-
api;
|
|
399
|
-
interceptors;
|
|
400
|
-
onEventBlocked;
|
|
401
|
-
constructor(options){
|
|
402
|
-
const { api, builder, config, interceptors } = options;
|
|
403
|
-
this.allowedEventTypes = config?.allowedEventTypes ?? defaultAllowedEvents;
|
|
404
|
-
this.api = api;
|
|
405
|
-
this.builder = builder;
|
|
406
|
-
this.interceptors = interceptors;
|
|
407
|
-
this.onEventBlocked = config?.onEventBlocked;
|
|
408
|
-
}
|
|
409
|
-
reportBlockedEvent(reason, product, method, args) {
|
|
410
|
-
const event = {
|
|
411
|
-
reason,
|
|
412
|
-
product,
|
|
413
|
-
method,
|
|
414
|
-
args
|
|
415
|
-
};
|
|
416
|
-
try {
|
|
417
|
-
this.onEventBlocked?.(event);
|
|
418
|
-
} catch (error) {
|
|
419
|
-
ProductBase_logger.warn(`onEventBlocked callback failed for method "${method}"`, error);
|
|
420
|
-
}
|
|
421
|
-
blockedEvent.value = event;
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
const src_ProductBase = ProductBase;
|
|
425
|
-
class AnalyticsBase extends src_ProductBase {
|
|
426
|
-
}
|
|
427
|
-
const analytics_AnalyticsBase = AnalyticsBase;
|
|
428
|
-
function applyDecs2203RFactory() {
|
|
429
|
-
function createAddInitializerMethod(initializers, decoratorFinishedRef) {
|
|
430
|
-
return function(initializer) {
|
|
431
|
-
assertNotFinished(decoratorFinishedRef, "addInitializer");
|
|
432
|
-
assertCallable(initializer, "An initializer");
|
|
433
|
-
initializers.push(initializer);
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
function memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value) {
|
|
437
|
-
var kindStr;
|
|
438
|
-
switch(kind){
|
|
439
|
-
case 1:
|
|
440
|
-
kindStr = "accessor";
|
|
441
|
-
break;
|
|
442
|
-
case 2:
|
|
443
|
-
kindStr = "method";
|
|
444
|
-
break;
|
|
445
|
-
case 3:
|
|
446
|
-
kindStr = "getter";
|
|
447
|
-
break;
|
|
448
|
-
case 4:
|
|
449
|
-
kindStr = "setter";
|
|
450
|
-
break;
|
|
451
|
-
default:
|
|
452
|
-
kindStr = "field";
|
|
453
|
-
}
|
|
454
|
-
var ctx = {
|
|
455
|
-
kind: kindStr,
|
|
456
|
-
name: isPrivate ? "#" + name : name,
|
|
457
|
-
static: isStatic,
|
|
458
|
-
private: isPrivate,
|
|
459
|
-
metadata: metadata
|
|
460
|
-
};
|
|
461
|
-
var decoratorFinishedRef = {
|
|
462
|
-
v: false
|
|
463
|
-
};
|
|
464
|
-
ctx.addInitializer = createAddInitializerMethod(initializers, decoratorFinishedRef);
|
|
465
|
-
var get, set;
|
|
466
|
-
if (0 === kind) if (isPrivate) {
|
|
467
|
-
get = desc.get;
|
|
468
|
-
set = desc.set;
|
|
469
|
-
} else {
|
|
470
|
-
get = function() {
|
|
471
|
-
return this[name];
|
|
472
|
-
};
|
|
473
|
-
set = function(v) {
|
|
474
|
-
this[name] = v;
|
|
475
|
-
};
|
|
476
|
-
}
|
|
477
|
-
else if (2 === kind) get = function() {
|
|
478
|
-
return desc.value;
|
|
479
|
-
};
|
|
480
|
-
else {
|
|
481
|
-
if (1 === kind || 3 === kind) get = function() {
|
|
482
|
-
return desc.get.call(this);
|
|
483
|
-
};
|
|
484
|
-
if (1 === kind || 4 === kind) set = function(v) {
|
|
485
|
-
desc.set.call(this, v);
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
|
-
ctx.access = get && set ? {
|
|
489
|
-
get: get,
|
|
490
|
-
set: set
|
|
491
|
-
} : get ? {
|
|
492
|
-
get: get
|
|
493
|
-
} : {
|
|
494
|
-
set: set
|
|
495
|
-
};
|
|
496
|
-
try {
|
|
497
|
-
return dec(value, ctx);
|
|
498
|
-
} finally{
|
|
499
|
-
decoratorFinishedRef.v = true;
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
function assertNotFinished(decoratorFinishedRef, fnName) {
|
|
503
|
-
if (decoratorFinishedRef.v) throw new Error("attempted to call " + fnName + " after decoration was finished");
|
|
504
|
-
}
|
|
505
|
-
function assertCallable(fn, hint) {
|
|
506
|
-
if ("function" != typeof fn) throw new TypeError(hint + " must be a function");
|
|
507
|
-
}
|
|
508
|
-
function assertValidReturnValue(kind, value) {
|
|
509
|
-
var type = typeof value;
|
|
510
|
-
if (1 === kind) {
|
|
511
|
-
if ("object" !== type || null === value) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
|
|
512
|
-
if (void 0 !== value.get) assertCallable(value.get, "accessor.get");
|
|
513
|
-
if (void 0 !== value.set) assertCallable(value.set, "accessor.set");
|
|
514
|
-
if (void 0 !== value.init) assertCallable(value.init, "accessor.init");
|
|
515
|
-
} else if ("function" !== type) {
|
|
516
|
-
var hint;
|
|
517
|
-
hint = 0 === kind ? "field" : 10 === kind ? "class" : "method";
|
|
518
|
-
throw new TypeError(hint + " decorators must return a function or void 0");
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
function applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata) {
|
|
522
|
-
var decs = decInfo[0];
|
|
523
|
-
var desc, init, value;
|
|
524
|
-
if (isPrivate) desc = 0 === kind || 1 === kind ? {
|
|
525
|
-
get: decInfo[3],
|
|
526
|
-
set: decInfo[4]
|
|
527
|
-
} : 3 === kind ? {
|
|
528
|
-
get: decInfo[3]
|
|
529
|
-
} : 4 === kind ? {
|
|
530
|
-
set: decInfo[3]
|
|
531
|
-
} : {
|
|
532
|
-
value: decInfo[3]
|
|
533
|
-
};
|
|
534
|
-
else if (0 !== kind) desc = Object.getOwnPropertyDescriptor(base, name);
|
|
535
|
-
if (1 === kind) value = {
|
|
536
|
-
get: desc.get,
|
|
537
|
-
set: desc.set
|
|
538
|
-
};
|
|
539
|
-
else if (2 === kind) value = desc.value;
|
|
540
|
-
else if (3 === kind) value = desc.get;
|
|
541
|
-
else if (4 === kind) value = desc.set;
|
|
542
|
-
var newValue, get, set;
|
|
543
|
-
if ("function" == typeof decs) {
|
|
544
|
-
newValue = memberDec(decs, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
|
|
545
|
-
if (void 0 !== newValue) {
|
|
546
|
-
assertValidReturnValue(kind, newValue);
|
|
547
|
-
if (0 === kind) init = newValue;
|
|
548
|
-
else if (1 === kind) {
|
|
549
|
-
init = newValue.init;
|
|
550
|
-
get = newValue.get || value.get;
|
|
551
|
-
set = newValue.set || value.set;
|
|
552
|
-
value = {
|
|
553
|
-
get: get,
|
|
554
|
-
set: set
|
|
555
|
-
};
|
|
556
|
-
} else value = newValue;
|
|
557
|
-
}
|
|
558
|
-
} else for(var i = decs.length - 1; i >= 0; i--){
|
|
559
|
-
var dec = decs[i];
|
|
560
|
-
newValue = memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
|
|
561
|
-
if (void 0 !== newValue) {
|
|
562
|
-
assertValidReturnValue(kind, newValue);
|
|
563
|
-
var newInit;
|
|
564
|
-
if (0 === kind) newInit = newValue;
|
|
565
|
-
else if (1 === kind) {
|
|
566
|
-
newInit = newValue.init;
|
|
567
|
-
get = newValue.get || value.get;
|
|
568
|
-
set = newValue.set || value.set;
|
|
569
|
-
value = {
|
|
570
|
-
get: get,
|
|
571
|
-
set: set
|
|
572
|
-
};
|
|
573
|
-
} else value = newValue;
|
|
574
|
-
if (void 0 !== newInit) if (void 0 === init) init = newInit;
|
|
575
|
-
else if ("function" == typeof init) init = [
|
|
576
|
-
init,
|
|
577
|
-
newInit
|
|
578
|
-
];
|
|
579
|
-
else init.push(newInit);
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
if (0 === kind || 1 === kind) {
|
|
583
|
-
if (void 0 === init) init = function(instance, init) {
|
|
584
|
-
return init;
|
|
585
|
-
};
|
|
586
|
-
else if ("function" != typeof init) {
|
|
587
|
-
var ownInitializers = init;
|
|
588
|
-
init = function(instance, init) {
|
|
589
|
-
var value = init;
|
|
590
|
-
for(var i = 0; i < ownInitializers.length; i++)value = ownInitializers[i].call(instance, value);
|
|
591
|
-
return value;
|
|
592
|
-
};
|
|
593
|
-
} else {
|
|
594
|
-
var originalInitializer = init;
|
|
595
|
-
init = function(instance, init) {
|
|
596
|
-
return originalInitializer.call(instance, init);
|
|
597
|
-
};
|
|
598
|
-
}
|
|
599
|
-
ret.push(init);
|
|
600
|
-
}
|
|
601
|
-
if (0 !== kind) {
|
|
602
|
-
if (1 === kind) {
|
|
603
|
-
desc.get = value.get;
|
|
604
|
-
desc.set = value.set;
|
|
605
|
-
} else if (2 === kind) desc.value = value;
|
|
606
|
-
else if (3 === kind) desc.get = value;
|
|
607
|
-
else if (4 === kind) desc.set = value;
|
|
608
|
-
if (isPrivate) if (1 === kind) {
|
|
609
|
-
ret.push(function(instance, args) {
|
|
610
|
-
return value.get.call(instance, args);
|
|
611
|
-
});
|
|
612
|
-
ret.push(function(instance, args) {
|
|
613
|
-
return value.set.call(instance, args);
|
|
614
|
-
});
|
|
615
|
-
} else if (2 === kind) ret.push(value);
|
|
616
|
-
else ret.push(function(instance, args) {
|
|
617
|
-
return value.call(instance, args);
|
|
618
|
-
});
|
|
619
|
-
else Object.defineProperty(base, name, desc);
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
function applyMemberDecs(Class, decInfos, metadata) {
|
|
623
|
-
var ret = [];
|
|
624
|
-
var protoInitializers;
|
|
625
|
-
var staticInitializers;
|
|
626
|
-
var existingProtoNonFields = new Map();
|
|
627
|
-
var existingStaticNonFields = new Map();
|
|
628
|
-
for(var i = 0; i < decInfos.length; i++){
|
|
629
|
-
var decInfo = decInfos[i];
|
|
630
|
-
if (Array.isArray(decInfo)) {
|
|
631
|
-
var kind = decInfo[1];
|
|
632
|
-
var name = decInfo[2];
|
|
633
|
-
var isPrivate = decInfo.length > 3;
|
|
634
|
-
var isStatic = kind >= 5;
|
|
635
|
-
var base;
|
|
636
|
-
var initializers;
|
|
637
|
-
if (isStatic) {
|
|
638
|
-
base = Class;
|
|
639
|
-
kind -= 5;
|
|
640
|
-
staticInitializers = staticInitializers || [];
|
|
641
|
-
initializers = staticInitializers;
|
|
642
|
-
} else {
|
|
643
|
-
base = Class.prototype;
|
|
644
|
-
protoInitializers = protoInitializers || [];
|
|
645
|
-
initializers = protoInitializers;
|
|
646
|
-
}
|
|
647
|
-
if (0 !== kind && !isPrivate) {
|
|
648
|
-
var existingNonFields = isStatic ? existingStaticNonFields : existingProtoNonFields;
|
|
649
|
-
var existingKind = existingNonFields.get(name) || 0;
|
|
650
|
-
if (true === existingKind || 3 === existingKind && 4 !== kind || 4 === existingKind && 3 !== kind) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + name);
|
|
651
|
-
if (!existingKind && kind > 2) existingNonFields.set(name, kind);
|
|
652
|
-
else existingNonFields.set(name, true);
|
|
653
|
-
}
|
|
654
|
-
applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata);
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
pushInitializers(ret, protoInitializers);
|
|
658
|
-
pushInitializers(ret, staticInitializers);
|
|
659
|
-
return ret;
|
|
660
|
-
}
|
|
661
|
-
function pushInitializers(ret, initializers) {
|
|
662
|
-
if (initializers) ret.push(function(instance) {
|
|
663
|
-
for(var i = 0; i < initializers.length; i++)initializers[i].call(instance);
|
|
664
|
-
return instance;
|
|
665
|
-
});
|
|
666
|
-
}
|
|
667
|
-
function applyClassDecs(targetClass, classDecs, metadata) {
|
|
668
|
-
if (classDecs.length > 0) {
|
|
669
|
-
var initializers = [];
|
|
670
|
-
var newClass = targetClass;
|
|
671
|
-
var name = targetClass.name;
|
|
672
|
-
for(var i = classDecs.length - 1; i >= 0; i--){
|
|
673
|
-
var decoratorFinishedRef = {
|
|
674
|
-
v: false
|
|
675
|
-
};
|
|
676
|
-
try {
|
|
677
|
-
var nextNewClass = classDecs[i](newClass, {
|
|
678
|
-
kind: "class",
|
|
679
|
-
name: name,
|
|
680
|
-
addInitializer: createAddInitializerMethod(initializers, decoratorFinishedRef),
|
|
681
|
-
metadata
|
|
682
|
-
});
|
|
683
|
-
} finally{
|
|
684
|
-
decoratorFinishedRef.v = true;
|
|
685
|
-
}
|
|
686
|
-
if (void 0 !== nextNewClass) {
|
|
687
|
-
assertValidReturnValue(10, nextNewClass);
|
|
688
|
-
newClass = nextNewClass;
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
return [
|
|
692
|
-
defineMetadata(newClass, metadata),
|
|
693
|
-
function() {
|
|
694
|
-
for(var i = 0; i < initializers.length; i++)initializers[i].call(newClass);
|
|
695
|
-
}
|
|
696
|
-
];
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
function defineMetadata(Class, metadata) {
|
|
700
|
-
return Object.defineProperty(Class, Symbol.metadata || Symbol.for("Symbol.metadata"), {
|
|
701
|
-
configurable: true,
|
|
702
|
-
enumerable: true,
|
|
703
|
-
value: metadata
|
|
704
|
-
});
|
|
705
|
-
}
|
|
706
|
-
return function(targetClass, memberDecs, classDecs, parentClass) {
|
|
707
|
-
if (void 0 !== parentClass) var parentMetadata = parentClass[Symbol.metadata || Symbol.for("Symbol.metadata")];
|
|
708
|
-
var metadata = Object.create(void 0 === parentMetadata ? null : parentMetadata);
|
|
709
|
-
var e = applyMemberDecs(targetClass, memberDecs, metadata);
|
|
710
|
-
if (!classDecs.length) defineMetadata(targetClass, metadata);
|
|
711
|
-
return {
|
|
712
|
-
e: e,
|
|
713
|
-
get c () {
|
|
714
|
-
return applyClassDecs(targetClass, classDecs, metadata);
|
|
715
|
-
}
|
|
716
|
-
};
|
|
717
|
-
};
|
|
718
|
-
}
|
|
719
|
-
function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
|
|
720
|
-
return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
|
|
721
|
-
}
|
|
722
|
-
var _dec, _dec1, _dec2, _dec3, _initProto;
|
|
723
|
-
const AnalyticsStateful_logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('Analytics');
|
|
724
|
-
const MAX_QUEUED_EVENTS = 25;
|
|
725
|
-
const ANALYTICS_METHOD_EVENT_TYPE_MAP = {
|
|
726
|
-
trackComponentView: 'component',
|
|
727
|
-
trackFlagView: 'component',
|
|
728
|
-
trackComponentClick: 'component_click',
|
|
729
|
-
trackComponentHover: 'component_hover'
|
|
730
|
-
};
|
|
731
|
-
_dec = guardedBy('hasConsent', {
|
|
732
|
-
onBlocked: 'onBlockedByConsent'
|
|
733
|
-
}), _dec1 = guardedBy('hasConsent', {
|
|
734
|
-
onBlocked: 'onBlockedByConsent'
|
|
735
|
-
}), _dec2 = guardedBy('hasConsent', {
|
|
736
|
-
onBlocked: 'onBlockedByConsent'
|
|
737
|
-
}), _dec3 = guardedBy('hasConsent', {
|
|
738
|
-
onBlocked: 'onBlockedByConsent'
|
|
739
|
-
});
|
|
740
|
-
class AnalyticsStateful extends analytics_AnalyticsBase {
|
|
741
|
-
static{
|
|
742
|
-
({ e: [_initProto] } = _apply_decs_2203_r(this, [
|
|
743
|
-
[
|
|
744
|
-
_dec,
|
|
745
|
-
2,
|
|
746
|
-
"trackComponentView"
|
|
747
|
-
],
|
|
748
|
-
[
|
|
749
|
-
_dec1,
|
|
750
|
-
2,
|
|
751
|
-
"trackComponentClick"
|
|
752
|
-
],
|
|
753
|
-
[
|
|
754
|
-
_dec2,
|
|
755
|
-
2,
|
|
756
|
-
"trackComponentHover"
|
|
757
|
-
],
|
|
758
|
-
[
|
|
759
|
-
_dec3,
|
|
760
|
-
2,
|
|
761
|
-
"trackFlagView"
|
|
762
|
-
]
|
|
763
|
-
], []));
|
|
764
|
-
}
|
|
765
|
-
queue = (_initProto(this), new Map());
|
|
766
|
-
flushRuntime;
|
|
767
|
-
states = {
|
|
768
|
-
blockedEventStream: toObservable(blockedEvent),
|
|
769
|
-
eventStream: toObservable(signals_event),
|
|
770
|
-
profile: toObservable(signals_profile)
|
|
771
|
-
};
|
|
772
|
-
constructor(options){
|
|
773
|
-
const { api, builder, config, interceptors } = options;
|
|
774
|
-
super({
|
|
775
|
-
api,
|
|
776
|
-
builder,
|
|
777
|
-
config,
|
|
778
|
-
interceptors
|
|
779
|
-
});
|
|
780
|
-
this.applyDefaults(config?.defaults);
|
|
781
|
-
this.flushRuntime = new QueueFlushRuntime({
|
|
782
|
-
policy: resolveQueueFlushPolicy(config?.queuePolicy),
|
|
783
|
-
onRetry: ()=>{
|
|
784
|
-
this.flush();
|
|
785
|
-
},
|
|
786
|
-
onCallbackError: (callbackName, error)=>{
|
|
787
|
-
AnalyticsStateful_logger.warn(`Analytics flush policy callback "${callbackName}" failed`, error);
|
|
788
|
-
}
|
|
789
|
-
});
|
|
790
|
-
this.initializeEffects();
|
|
791
|
-
}
|
|
792
|
-
reset() {
|
|
793
|
-
this.flushRuntime.reset();
|
|
794
|
-
batch(()=>{
|
|
795
|
-
blockedEvent.value = void 0;
|
|
796
|
-
signals_event.value = void 0;
|
|
797
|
-
signals_profile.value = void 0;
|
|
798
|
-
});
|
|
799
|
-
}
|
|
800
|
-
hasConsent(name) {
|
|
801
|
-
const mappedEventType = ANALYTICS_METHOD_EVENT_TYPE_MAP[name] ?? name;
|
|
802
|
-
return !!consent.value || (this.allowedEventTypes ?? []).includes(mappedEventType);
|
|
803
|
-
}
|
|
804
|
-
onBlockedByConsent(name, payload) {
|
|
805
|
-
AnalyticsStateful_logger.warn(`Event "${name}" was blocked due to lack of consent; payload: ${JSON.stringify(payload)}`);
|
|
806
|
-
this.reportBlockedEvent('consent', 'analytics', name, payload);
|
|
807
|
-
}
|
|
808
|
-
async trackComponentView(payload) {
|
|
809
|
-
AnalyticsStateful_logger.info(`Processing "component view" event for ${payload.componentId}`);
|
|
810
|
-
await this.enqueueEvent(this.builder.buildComponentView(payload));
|
|
811
|
-
}
|
|
812
|
-
async trackComponentClick(payload) {
|
|
813
|
-
AnalyticsStateful_logger.info(`Processing "component click" event for ${payload.componentId}`);
|
|
814
|
-
await this.enqueueEvent(this.builder.buildComponentClick(payload));
|
|
815
|
-
}
|
|
816
|
-
async trackComponentHover(payload) {
|
|
817
|
-
AnalyticsStateful_logger.info(`Processing "component hover" event for ${payload.componentId}`);
|
|
818
|
-
await this.enqueueEvent(this.builder.buildComponentHover(payload));
|
|
819
|
-
}
|
|
820
|
-
async trackFlagView(payload) {
|
|
821
|
-
AnalyticsStateful_logger.debug(`Processing "flag view" event for ${payload.componentId}`);
|
|
822
|
-
await this.enqueueEvent(this.builder.buildFlagView(payload));
|
|
823
|
-
}
|
|
824
|
-
async enqueueEvent(event) {
|
|
825
|
-
const { value: profile } = signals_profile;
|
|
826
|
-
if (!profile) return void AnalyticsStateful_logger.warn('Attempting to emit an event without an Optimization profile');
|
|
827
|
-
const intercepted = await this.interceptors.event.run(event);
|
|
828
|
-
const validEvent = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.InsightsEvent, intercepted);
|
|
829
|
-
AnalyticsStateful_logger.debug(`Queueing ${validEvent.type} event for profile ${profile.id}`, validEvent);
|
|
830
|
-
const { id: profileId } = profile;
|
|
831
|
-
const queuedProfileEvents = this.queue.get(profileId);
|
|
832
|
-
signals_event.value = validEvent;
|
|
833
|
-
if (queuedProfileEvents) {
|
|
834
|
-
queuedProfileEvents.profile = profile;
|
|
835
|
-
queuedProfileEvents.events.push(validEvent);
|
|
836
|
-
} else this.queue.set(profileId, {
|
|
837
|
-
profile,
|
|
838
|
-
events: [
|
|
839
|
-
validEvent
|
|
840
|
-
]
|
|
841
|
-
});
|
|
842
|
-
await this.flushMaxEvents();
|
|
843
|
-
}
|
|
844
|
-
async flushMaxEvents() {
|
|
845
|
-
if (this.getQueuedEventCount() >= MAX_QUEUED_EVENTS) await this.flush();
|
|
846
|
-
}
|
|
847
|
-
async flush(options = {}) {
|
|
848
|
-
const { force = false } = options;
|
|
849
|
-
if (this.flushRuntime.shouldSkip({
|
|
850
|
-
force,
|
|
851
|
-
isOnline: !!online.value
|
|
852
|
-
})) return;
|
|
853
|
-
AnalyticsStateful_logger.debug('Flushing event queue');
|
|
854
|
-
const batches = this.createBatches();
|
|
855
|
-
if (!batches.length) return void this.flushRuntime.clearScheduledRetry();
|
|
856
|
-
this.flushRuntime.markFlushStarted();
|
|
857
|
-
try {
|
|
858
|
-
const sendSuccess = await this.trySendBatches(batches);
|
|
859
|
-
if (sendSuccess) {
|
|
860
|
-
this.queue.clear();
|
|
861
|
-
this.flushRuntime.handleFlushSuccess();
|
|
862
|
-
} else this.flushRuntime.handleFlushFailure({
|
|
863
|
-
queuedBatches: batches.length,
|
|
864
|
-
queuedEvents: this.getQueuedEventCount()
|
|
865
|
-
});
|
|
866
|
-
} finally{
|
|
867
|
-
this.flushRuntime.markFlushFinished();
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
applyDefaults(defaults) {
|
|
871
|
-
if (defaults?.profile === void 0) return;
|
|
872
|
-
const { profile: defaultProfile } = defaults;
|
|
873
|
-
signals_profile.value = defaultProfile;
|
|
874
|
-
}
|
|
875
|
-
initializeEffects() {
|
|
876
|
-
effect(()=>{
|
|
877
|
-
const id = signals_profile.value?.id;
|
|
878
|
-
AnalyticsStateful_logger.info(`Analytics ${consent.value ? 'will' : 'will not'} be collected due to consent (${consent.value})`);
|
|
879
|
-
AnalyticsStateful_logger.debug(`Profile ${id && `with ID ${id}`} has been ${id ? 'set' : 'cleared'}`);
|
|
880
|
-
});
|
|
881
|
-
effect(()=>{
|
|
882
|
-
if (!online.value) return;
|
|
883
|
-
this.flushRuntime.clearScheduledRetry();
|
|
884
|
-
this.flush({
|
|
885
|
-
force: true
|
|
886
|
-
});
|
|
887
|
-
});
|
|
888
|
-
}
|
|
889
|
-
createBatches() {
|
|
890
|
-
const batches = [];
|
|
891
|
-
this.queue.forEach(({ profile, events })=>{
|
|
892
|
-
batches.push({
|
|
893
|
-
profile,
|
|
894
|
-
events
|
|
895
|
-
});
|
|
896
|
-
});
|
|
897
|
-
return batches;
|
|
898
|
-
}
|
|
899
|
-
async trySendBatches(batches) {
|
|
900
|
-
try {
|
|
901
|
-
return await this.api.insights.sendBatchEvents(batches);
|
|
902
|
-
} catch (error) {
|
|
903
|
-
AnalyticsStateful_logger.warn('Analytics queue flush request threw an error', error);
|
|
904
|
-
return false;
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
getQueuedEventCount() {
|
|
908
|
-
let queuedCount = 0;
|
|
909
|
-
this.queue.forEach(({ events })=>{
|
|
910
|
-
queuedCount += events.length;
|
|
911
|
-
});
|
|
912
|
-
return queuedCount;
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
const analytics_AnalyticsStateful = AnalyticsStateful;
|
|
916
|
-
const AnalyticsStateless_logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('Analytics');
|
|
917
|
-
class AnalyticsStateless extends analytics_AnalyticsBase {
|
|
918
|
-
async trackComponentView(args) {
|
|
919
|
-
AnalyticsStateless_logger.info('Processing "component view" event');
|
|
920
|
-
const { profile, ...builderArgs } = args;
|
|
921
|
-
const event = this.builder.buildComponentView(builderArgs);
|
|
922
|
-
await this.sendBatchEvent(event, profile);
|
|
923
|
-
}
|
|
924
|
-
async trackComponentClick(args) {
|
|
925
|
-
AnalyticsStateless_logger.info('Processing "component click" event');
|
|
926
|
-
const { profile, ...builderArgs } = args;
|
|
927
|
-
const event = this.builder.buildComponentClick(builderArgs);
|
|
928
|
-
await this.sendBatchEvent(event, profile);
|
|
929
|
-
}
|
|
930
|
-
async trackComponentHover(args) {
|
|
931
|
-
AnalyticsStateless_logger.info('Processing "component hover" event');
|
|
932
|
-
const { profile, ...builderArgs } = args;
|
|
933
|
-
const event = this.builder.buildComponentHover(builderArgs);
|
|
934
|
-
await this.sendBatchEvent(event, profile);
|
|
935
|
-
}
|
|
936
|
-
async trackFlagView(args) {
|
|
937
|
-
AnalyticsStateless_logger.debug('Processing "flag view" event');
|
|
938
|
-
const { profile, ...builderArgs } = args;
|
|
939
|
-
const event = this.builder.buildFlagView(builderArgs);
|
|
940
|
-
await this.sendBatchEvent(event, profile);
|
|
941
|
-
}
|
|
942
|
-
async sendBatchEvent(event, profile) {
|
|
943
|
-
const intercepted = await this.interceptors.event.run(event);
|
|
944
|
-
const parsed = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.InsightsEvent, intercepted);
|
|
945
|
-
const batchEvent = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.BatchInsightsEventArray, [
|
|
946
|
-
{
|
|
947
|
-
profile,
|
|
948
|
-
events: [
|
|
949
|
-
parsed
|
|
950
|
-
]
|
|
951
|
-
}
|
|
952
|
-
]);
|
|
953
|
-
await this.api.insights.sendBatchEvents(batchEvent);
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
const analytics_AnalyticsStateless = AnalyticsStateless;
|
|
957
|
-
class InterceptorManager {
|
|
958
|
-
interceptors = new Map();
|
|
959
|
-
nextId = 0;
|
|
960
|
-
add(interceptor) {
|
|
961
|
-
const { nextId: id } = this;
|
|
962
|
-
this.nextId += 1;
|
|
963
|
-
this.interceptors.set(id, interceptor);
|
|
964
|
-
return id;
|
|
965
|
-
}
|
|
966
|
-
remove(id) {
|
|
967
|
-
return this.interceptors.delete(id);
|
|
968
|
-
}
|
|
969
|
-
clear() {
|
|
970
|
-
this.interceptors.clear();
|
|
971
|
-
}
|
|
972
|
-
count() {
|
|
973
|
-
return this.interceptors.size;
|
|
974
|
-
}
|
|
975
|
-
async run(input) {
|
|
976
|
-
const fns = Array.from(this.interceptors.values());
|
|
977
|
-
let acc = input;
|
|
978
|
-
for (const fn of fns)acc = await fn(acc);
|
|
979
|
-
return acc;
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
class CoreBase {
|
|
983
|
-
api;
|
|
984
|
-
eventBuilder;
|
|
985
|
-
config;
|
|
986
|
-
interceptors = {
|
|
987
|
-
event: new InterceptorManager(),
|
|
988
|
-
state: new InterceptorManager()
|
|
989
|
-
};
|
|
990
|
-
constructor(config){
|
|
991
|
-
this.config = config;
|
|
992
|
-
const { analytics, personalization, eventBuilder, logLevel, environment, clientId, fetchOptions } = config;
|
|
993
|
-
__rspack_external__contentful_optimization_api_client_logger_f0d05f82.logger.addSink(new __rspack_external__contentful_optimization_api_client_logger_f0d05f82.ConsoleLogSink(logLevel));
|
|
994
|
-
const apiConfig = {
|
|
995
|
-
clientId,
|
|
996
|
-
environment,
|
|
997
|
-
fetchOptions,
|
|
998
|
-
analytics,
|
|
999
|
-
personalization
|
|
1000
|
-
};
|
|
1001
|
-
this.api = new __rspack_external__contentful_optimization_api_client_cba5a7ee.ApiClient(apiConfig);
|
|
1002
|
-
this.eventBuilder = new __rspack_external__contentful_optimization_api_client_cba5a7ee.EventBuilder(eventBuilder ?? {
|
|
1003
|
-
channel: 'server',
|
|
1004
|
-
library: {
|
|
1005
|
-
name: OPTIMIZATION_CORE_SDK_NAME,
|
|
1006
|
-
version: OPTIMIZATION_CORE_SDK_VERSION
|
|
1007
|
-
}
|
|
1008
|
-
});
|
|
1009
|
-
}
|
|
1010
|
-
get flagsResolver() {
|
|
1011
|
-
return this._personalization.flagsResolver;
|
|
1012
|
-
}
|
|
1013
|
-
get mergeTagValueResolver() {
|
|
1014
|
-
return this._personalization.mergeTagValueResolver;
|
|
1015
|
-
}
|
|
1016
|
-
get personalizedEntryResolver() {
|
|
1017
|
-
return this._personalization.personalizedEntryResolver;
|
|
1018
|
-
}
|
|
1019
|
-
getCustomFlag(name, changes) {
|
|
1020
|
-
return this._personalization.getCustomFlag(name, changes);
|
|
1021
|
-
}
|
|
1022
|
-
getCustomFlags(changes) {
|
|
1023
|
-
return this._personalization.getCustomFlags(changes);
|
|
1024
|
-
}
|
|
1025
|
-
personalizeEntry(entry, personalizations) {
|
|
1026
|
-
return this._personalization.personalizeEntry(entry, personalizations);
|
|
1027
|
-
}
|
|
1028
|
-
getMergeTagValue(embeddedEntryNodeTarget, profile) {
|
|
1029
|
-
return this._personalization.getMergeTagValue(embeddedEntryNodeTarget, profile);
|
|
1030
|
-
}
|
|
1031
|
-
async identify(payload) {
|
|
1032
|
-
return await this._personalization.identify(payload);
|
|
1033
|
-
}
|
|
1034
|
-
async page(payload) {
|
|
1035
|
-
return await this._personalization.page(payload);
|
|
1036
|
-
}
|
|
1037
|
-
async screen(payload) {
|
|
1038
|
-
return await this._personalization.screen(payload);
|
|
1039
|
-
}
|
|
1040
|
-
async track(payload) {
|
|
1041
|
-
return await this._personalization.track(payload);
|
|
1042
|
-
}
|
|
1043
|
-
async trackComponentView(payload) {
|
|
1044
|
-
if (payload.sticky) return await this._personalization.trackComponentView(payload);
|
|
1045
|
-
await this._analytics.trackComponentView(payload);
|
|
1046
|
-
}
|
|
1047
|
-
async trackComponentClick(payload) {
|
|
1048
|
-
await this._analytics.trackComponentClick(payload);
|
|
1049
|
-
}
|
|
1050
|
-
async trackComponentHover(payload) {
|
|
1051
|
-
await this._analytics.trackComponentHover(payload);
|
|
1052
|
-
}
|
|
1053
|
-
async trackFlagView(payload) {
|
|
1054
|
-
await this._analytics.trackFlagView(payload);
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
const src_CoreBase = CoreBase;
|
|
1058
|
-
const STATEFUL_RUNTIME_LOCK_KEY = '__ctfl_optimization_stateful_runtime_lock__';
|
|
1059
|
-
const getStatefulRuntimeLock = ()=>{
|
|
1060
|
-
const singletonGlobal = globalThis;
|
|
1061
|
-
singletonGlobal[STATEFUL_RUNTIME_LOCK_KEY] ??= {
|
|
1062
|
-
owner: void 0
|
|
1063
|
-
};
|
|
1064
|
-
return singletonGlobal[STATEFUL_RUNTIME_LOCK_KEY];
|
|
1065
|
-
};
|
|
1066
|
-
const acquireStatefulRuntimeSingleton = (owner)=>{
|
|
1067
|
-
const lock = getStatefulRuntimeLock();
|
|
1068
|
-
if (lock.owner) throw new Error(`Stateful Optimization SDK already initialized (${lock.owner}). Only one stateful instance is supported per runtime.`);
|
|
1069
|
-
lock.owner = owner;
|
|
1070
|
-
};
|
|
1071
|
-
const releaseStatefulRuntimeSingleton = (owner)=>{
|
|
1072
|
-
const lock = getStatefulRuntimeLock();
|
|
1073
|
-
if (lock.owner === owner) lock.owner = void 0;
|
|
1074
|
-
};
|
|
1075
|
-
class PersonalizationBase extends src_ProductBase {
|
|
1076
|
-
flagsResolver = resolvers_FlagsResolver;
|
|
1077
|
-
mergeTagValueResolver = resolvers_MergeTagValueResolver;
|
|
1078
|
-
personalizedEntryResolver = resolvers_PersonalizedEntryResolver;
|
|
1079
|
-
getCustomFlag(name, changes) {
|
|
1080
|
-
return this.getCustomFlags(changes)[name];
|
|
1081
|
-
}
|
|
1082
|
-
getCustomFlags(changes) {
|
|
1083
|
-
return resolvers_FlagsResolver.resolve(changes);
|
|
1084
|
-
}
|
|
1085
|
-
personalizeEntry(entry, personalizations) {
|
|
1086
|
-
return resolvers_PersonalizedEntryResolver.resolve(entry, personalizations);
|
|
1087
|
-
}
|
|
1088
|
-
getMergeTagValue(embeddedEntryNodeTarget, profile) {
|
|
1089
|
-
return resolvers_MergeTagValueResolver.resolve(embeddedEntryNodeTarget, profile);
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
const personalization_PersonalizationBase = PersonalizationBase;
|
|
1093
|
-
function PersonalizationStateful_applyDecs2203RFactory() {
|
|
1094
|
-
function createAddInitializerMethod(initializers, decoratorFinishedRef) {
|
|
1095
|
-
return function(initializer) {
|
|
1096
|
-
assertNotFinished(decoratorFinishedRef, "addInitializer");
|
|
1097
|
-
assertCallable(initializer, "An initializer");
|
|
1098
|
-
initializers.push(initializer);
|
|
1099
|
-
};
|
|
1100
|
-
}
|
|
1101
|
-
function memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value) {
|
|
1102
|
-
var kindStr;
|
|
1103
|
-
switch(kind){
|
|
1104
|
-
case 1:
|
|
1105
|
-
kindStr = "accessor";
|
|
1106
|
-
break;
|
|
1107
|
-
case 2:
|
|
1108
|
-
kindStr = "method";
|
|
1109
|
-
break;
|
|
1110
|
-
case 3:
|
|
1111
|
-
kindStr = "getter";
|
|
1112
|
-
break;
|
|
1113
|
-
case 4:
|
|
1114
|
-
kindStr = "setter";
|
|
1115
|
-
break;
|
|
1116
|
-
default:
|
|
1117
|
-
kindStr = "field";
|
|
1118
|
-
}
|
|
1119
|
-
var ctx = {
|
|
1120
|
-
kind: kindStr,
|
|
1121
|
-
name: isPrivate ? "#" + name : name,
|
|
1122
|
-
static: isStatic,
|
|
1123
|
-
private: isPrivate,
|
|
1124
|
-
metadata: metadata
|
|
1125
|
-
};
|
|
1126
|
-
var decoratorFinishedRef = {
|
|
1127
|
-
v: false
|
|
1128
|
-
};
|
|
1129
|
-
ctx.addInitializer = createAddInitializerMethod(initializers, decoratorFinishedRef);
|
|
1130
|
-
var get, set;
|
|
1131
|
-
if (0 === kind) if (isPrivate) {
|
|
1132
|
-
get = desc.get;
|
|
1133
|
-
set = desc.set;
|
|
1134
|
-
} else {
|
|
1135
|
-
get = function() {
|
|
1136
|
-
return this[name];
|
|
1137
|
-
};
|
|
1138
|
-
set = function(v) {
|
|
1139
|
-
this[name] = v;
|
|
1140
|
-
};
|
|
1141
|
-
}
|
|
1142
|
-
else if (2 === kind) get = function() {
|
|
1143
|
-
return desc.value;
|
|
1144
|
-
};
|
|
1145
|
-
else {
|
|
1146
|
-
if (1 === kind || 3 === kind) get = function() {
|
|
1147
|
-
return desc.get.call(this);
|
|
1148
|
-
};
|
|
1149
|
-
if (1 === kind || 4 === kind) set = function(v) {
|
|
1150
|
-
desc.set.call(this, v);
|
|
1151
|
-
};
|
|
1152
|
-
}
|
|
1153
|
-
ctx.access = get && set ? {
|
|
1154
|
-
get: get,
|
|
1155
|
-
set: set
|
|
1156
|
-
} : get ? {
|
|
1157
|
-
get: get
|
|
1158
|
-
} : {
|
|
1159
|
-
set: set
|
|
1160
|
-
};
|
|
1161
|
-
try {
|
|
1162
|
-
return dec(value, ctx);
|
|
1163
|
-
} finally{
|
|
1164
|
-
decoratorFinishedRef.v = true;
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
function assertNotFinished(decoratorFinishedRef, fnName) {
|
|
1168
|
-
if (decoratorFinishedRef.v) throw new Error("attempted to call " + fnName + " after decoration was finished");
|
|
1169
|
-
}
|
|
1170
|
-
function assertCallable(fn, hint) {
|
|
1171
|
-
if ("function" != typeof fn) throw new TypeError(hint + " must be a function");
|
|
1172
|
-
}
|
|
1173
|
-
function assertValidReturnValue(kind, value) {
|
|
1174
|
-
var type = typeof value;
|
|
1175
|
-
if (1 === kind) {
|
|
1176
|
-
if ("object" !== type || null === value) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
|
|
1177
|
-
if (void 0 !== value.get) assertCallable(value.get, "accessor.get");
|
|
1178
|
-
if (void 0 !== value.set) assertCallable(value.set, "accessor.set");
|
|
1179
|
-
if (void 0 !== value.init) assertCallable(value.init, "accessor.init");
|
|
1180
|
-
} else if ("function" !== type) {
|
|
1181
|
-
var hint;
|
|
1182
|
-
hint = 0 === kind ? "field" : 10 === kind ? "class" : "method";
|
|
1183
|
-
throw new TypeError(hint + " decorators must return a function or void 0");
|
|
1184
|
-
}
|
|
1185
|
-
}
|
|
1186
|
-
function applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata) {
|
|
1187
|
-
var decs = decInfo[0];
|
|
1188
|
-
var desc, init, value;
|
|
1189
|
-
if (isPrivate) desc = 0 === kind || 1 === kind ? {
|
|
1190
|
-
get: decInfo[3],
|
|
1191
|
-
set: decInfo[4]
|
|
1192
|
-
} : 3 === kind ? {
|
|
1193
|
-
get: decInfo[3]
|
|
1194
|
-
} : 4 === kind ? {
|
|
1195
|
-
set: decInfo[3]
|
|
1196
|
-
} : {
|
|
1197
|
-
value: decInfo[3]
|
|
1198
|
-
};
|
|
1199
|
-
else if (0 !== kind) desc = Object.getOwnPropertyDescriptor(base, name);
|
|
1200
|
-
if (1 === kind) value = {
|
|
1201
|
-
get: desc.get,
|
|
1202
|
-
set: desc.set
|
|
1203
|
-
};
|
|
1204
|
-
else if (2 === kind) value = desc.value;
|
|
1205
|
-
else if (3 === kind) value = desc.get;
|
|
1206
|
-
else if (4 === kind) value = desc.set;
|
|
1207
|
-
var newValue, get, set;
|
|
1208
|
-
if ("function" == typeof decs) {
|
|
1209
|
-
newValue = memberDec(decs, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
|
|
1210
|
-
if (void 0 !== newValue) {
|
|
1211
|
-
assertValidReturnValue(kind, newValue);
|
|
1212
|
-
if (0 === kind) init = newValue;
|
|
1213
|
-
else if (1 === kind) {
|
|
1214
|
-
init = newValue.init;
|
|
1215
|
-
get = newValue.get || value.get;
|
|
1216
|
-
set = newValue.set || value.set;
|
|
1217
|
-
value = {
|
|
1218
|
-
get: get,
|
|
1219
|
-
set: set
|
|
1220
|
-
};
|
|
1221
|
-
} else value = newValue;
|
|
1222
|
-
}
|
|
1223
|
-
} else for(var i = decs.length - 1; i >= 0; i--){
|
|
1224
|
-
var dec = decs[i];
|
|
1225
|
-
newValue = memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
|
|
1226
|
-
if (void 0 !== newValue) {
|
|
1227
|
-
assertValidReturnValue(kind, newValue);
|
|
1228
|
-
var newInit;
|
|
1229
|
-
if (0 === kind) newInit = newValue;
|
|
1230
|
-
else if (1 === kind) {
|
|
1231
|
-
newInit = newValue.init;
|
|
1232
|
-
get = newValue.get || value.get;
|
|
1233
|
-
set = newValue.set || value.set;
|
|
1234
|
-
value = {
|
|
1235
|
-
get: get,
|
|
1236
|
-
set: set
|
|
1237
|
-
};
|
|
1238
|
-
} else value = newValue;
|
|
1239
|
-
if (void 0 !== newInit) if (void 0 === init) init = newInit;
|
|
1240
|
-
else if ("function" == typeof init) init = [
|
|
1241
|
-
init,
|
|
1242
|
-
newInit
|
|
1243
|
-
];
|
|
1244
|
-
else init.push(newInit);
|
|
1245
|
-
}
|
|
1246
|
-
}
|
|
1247
|
-
if (0 === kind || 1 === kind) {
|
|
1248
|
-
if (void 0 === init) init = function(instance, init) {
|
|
1249
|
-
return init;
|
|
1250
|
-
};
|
|
1251
|
-
else if ("function" != typeof init) {
|
|
1252
|
-
var ownInitializers = init;
|
|
1253
|
-
init = function(instance, init) {
|
|
1254
|
-
var value = init;
|
|
1255
|
-
for(var i = 0; i < ownInitializers.length; i++)value = ownInitializers[i].call(instance, value);
|
|
1256
|
-
return value;
|
|
1257
|
-
};
|
|
1258
|
-
} else {
|
|
1259
|
-
var originalInitializer = init;
|
|
1260
|
-
init = function(instance, init) {
|
|
1261
|
-
return originalInitializer.call(instance, init);
|
|
1262
|
-
};
|
|
1263
|
-
}
|
|
1264
|
-
ret.push(init);
|
|
1265
|
-
}
|
|
1266
|
-
if (0 !== kind) {
|
|
1267
|
-
if (1 === kind) {
|
|
1268
|
-
desc.get = value.get;
|
|
1269
|
-
desc.set = value.set;
|
|
1270
|
-
} else if (2 === kind) desc.value = value;
|
|
1271
|
-
else if (3 === kind) desc.get = value;
|
|
1272
|
-
else if (4 === kind) desc.set = value;
|
|
1273
|
-
if (isPrivate) if (1 === kind) {
|
|
1274
|
-
ret.push(function(instance, args) {
|
|
1275
|
-
return value.get.call(instance, args);
|
|
1276
|
-
});
|
|
1277
|
-
ret.push(function(instance, args) {
|
|
1278
|
-
return value.set.call(instance, args);
|
|
1279
|
-
});
|
|
1280
|
-
} else if (2 === kind) ret.push(value);
|
|
1281
|
-
else ret.push(function(instance, args) {
|
|
1282
|
-
return value.call(instance, args);
|
|
1283
|
-
});
|
|
1284
|
-
else Object.defineProperty(base, name, desc);
|
|
1285
|
-
}
|
|
1286
|
-
}
|
|
1287
|
-
function applyMemberDecs(Class, decInfos, metadata) {
|
|
1288
|
-
var ret = [];
|
|
1289
|
-
var protoInitializers;
|
|
1290
|
-
var staticInitializers;
|
|
1291
|
-
var existingProtoNonFields = new Map();
|
|
1292
|
-
var existingStaticNonFields = new Map();
|
|
1293
|
-
for(var i = 0; i < decInfos.length; i++){
|
|
1294
|
-
var decInfo = decInfos[i];
|
|
1295
|
-
if (Array.isArray(decInfo)) {
|
|
1296
|
-
var kind = decInfo[1];
|
|
1297
|
-
var name = decInfo[2];
|
|
1298
|
-
var isPrivate = decInfo.length > 3;
|
|
1299
|
-
var isStatic = kind >= 5;
|
|
1300
|
-
var base;
|
|
1301
|
-
var initializers;
|
|
1302
|
-
if (isStatic) {
|
|
1303
|
-
base = Class;
|
|
1304
|
-
kind -= 5;
|
|
1305
|
-
staticInitializers = staticInitializers || [];
|
|
1306
|
-
initializers = staticInitializers;
|
|
1307
|
-
} else {
|
|
1308
|
-
base = Class.prototype;
|
|
1309
|
-
protoInitializers = protoInitializers || [];
|
|
1310
|
-
initializers = protoInitializers;
|
|
1311
|
-
}
|
|
1312
|
-
if (0 !== kind && !isPrivate) {
|
|
1313
|
-
var existingNonFields = isStatic ? existingStaticNonFields : existingProtoNonFields;
|
|
1314
|
-
var existingKind = existingNonFields.get(name) || 0;
|
|
1315
|
-
if (true === existingKind || 3 === existingKind && 4 !== kind || 4 === existingKind && 3 !== kind) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + name);
|
|
1316
|
-
if (!existingKind && kind > 2) existingNonFields.set(name, kind);
|
|
1317
|
-
else existingNonFields.set(name, true);
|
|
1318
|
-
}
|
|
1319
|
-
applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata);
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
pushInitializers(ret, protoInitializers);
|
|
1323
|
-
pushInitializers(ret, staticInitializers);
|
|
1324
|
-
return ret;
|
|
1325
|
-
}
|
|
1326
|
-
function pushInitializers(ret, initializers) {
|
|
1327
|
-
if (initializers) ret.push(function(instance) {
|
|
1328
|
-
for(var i = 0; i < initializers.length; i++)initializers[i].call(instance);
|
|
1329
|
-
return instance;
|
|
1330
|
-
});
|
|
1331
|
-
}
|
|
1332
|
-
function applyClassDecs(targetClass, classDecs, metadata) {
|
|
1333
|
-
if (classDecs.length > 0) {
|
|
1334
|
-
var initializers = [];
|
|
1335
|
-
var newClass = targetClass;
|
|
1336
|
-
var name = targetClass.name;
|
|
1337
|
-
for(var i = classDecs.length - 1; i >= 0; i--){
|
|
1338
|
-
var decoratorFinishedRef = {
|
|
1339
|
-
v: false
|
|
1340
|
-
};
|
|
1341
|
-
try {
|
|
1342
|
-
var nextNewClass = classDecs[i](newClass, {
|
|
1343
|
-
kind: "class",
|
|
1344
|
-
name: name,
|
|
1345
|
-
addInitializer: createAddInitializerMethod(initializers, decoratorFinishedRef),
|
|
1346
|
-
metadata
|
|
1347
|
-
});
|
|
1348
|
-
} finally{
|
|
1349
|
-
decoratorFinishedRef.v = true;
|
|
1350
|
-
}
|
|
1351
|
-
if (void 0 !== nextNewClass) {
|
|
1352
|
-
assertValidReturnValue(10, nextNewClass);
|
|
1353
|
-
newClass = nextNewClass;
|
|
1354
|
-
}
|
|
1355
|
-
}
|
|
1356
|
-
return [
|
|
1357
|
-
defineMetadata(newClass, metadata),
|
|
1358
|
-
function() {
|
|
1359
|
-
for(var i = 0; i < initializers.length; i++)initializers[i].call(newClass);
|
|
1360
|
-
}
|
|
1361
|
-
];
|
|
1362
|
-
}
|
|
1363
|
-
}
|
|
1364
|
-
function defineMetadata(Class, metadata) {
|
|
1365
|
-
return Object.defineProperty(Class, Symbol.metadata || Symbol.for("Symbol.metadata"), {
|
|
1366
|
-
configurable: true,
|
|
1367
|
-
enumerable: true,
|
|
1368
|
-
value: metadata
|
|
1369
|
-
});
|
|
1370
|
-
}
|
|
1371
|
-
return function(targetClass, memberDecs, classDecs, parentClass) {
|
|
1372
|
-
if (void 0 !== parentClass) var parentMetadata = parentClass[Symbol.metadata || Symbol.for("Symbol.metadata")];
|
|
1373
|
-
var metadata = Object.create(void 0 === parentMetadata ? null : parentMetadata);
|
|
1374
|
-
var e = applyMemberDecs(targetClass, memberDecs, metadata);
|
|
1375
|
-
if (!classDecs.length) defineMetadata(targetClass, metadata);
|
|
1376
|
-
return {
|
|
1377
|
-
e: e,
|
|
1378
|
-
get c () {
|
|
1379
|
-
return applyClassDecs(targetClass, classDecs, metadata);
|
|
1380
|
-
}
|
|
1381
|
-
};
|
|
1382
|
-
};
|
|
1383
|
-
}
|
|
1384
|
-
function PersonalizationStateful_apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
|
|
1385
|
-
return (PersonalizationStateful_apply_decs_2203_r = PersonalizationStateful_applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
|
|
1386
|
-
}
|
|
1387
|
-
var PersonalizationStateful_dec, PersonalizationStateful_dec1, PersonalizationStateful_dec2, PersonalizationStateful_dec3, _dec4, PersonalizationStateful_initProto;
|
|
1388
|
-
const PersonalizationStateful_logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('Personalization');
|
|
1389
|
-
const OFFLINE_QUEUE_MAX_EVENTS = 100;
|
|
1390
|
-
const resolvePersonalizationQueuePolicy = (policy)=>({
|
|
1391
|
-
maxEvents: toPositiveInt(policy?.maxEvents, OFFLINE_QUEUE_MAX_EVENTS),
|
|
1392
|
-
onDrop: policy?.onDrop,
|
|
1393
|
-
flushPolicy: resolveQueueFlushPolicy(policy?.flushPolicy)
|
|
1394
|
-
});
|
|
1395
|
-
PersonalizationStateful_dec = guardedBy('hasConsent', {
|
|
1396
|
-
onBlocked: 'onBlockedByConsent'
|
|
1397
|
-
}), PersonalizationStateful_dec1 = guardedBy('hasConsent', {
|
|
1398
|
-
onBlocked: 'onBlockedByConsent'
|
|
1399
|
-
}), PersonalizationStateful_dec2 = guardedBy('hasConsent', {
|
|
1400
|
-
onBlocked: 'onBlockedByConsent'
|
|
1401
|
-
}), PersonalizationStateful_dec3 = guardedBy('hasConsent', {
|
|
1402
|
-
onBlocked: 'onBlockedByConsent'
|
|
1403
|
-
}), _dec4 = guardedBy('hasConsent', {
|
|
1404
|
-
onBlocked: 'onBlockedByConsent'
|
|
1405
|
-
});
|
|
1406
|
-
class PersonalizationStateful extends personalization_PersonalizationBase {
|
|
1407
|
-
static{
|
|
1408
|
-
({ e: [PersonalizationStateful_initProto] } = PersonalizationStateful_apply_decs_2203_r(this, [
|
|
1409
|
-
[
|
|
1410
|
-
PersonalizationStateful_dec,
|
|
1411
|
-
2,
|
|
1412
|
-
"identify"
|
|
1413
|
-
],
|
|
1414
|
-
[
|
|
1415
|
-
PersonalizationStateful_dec1,
|
|
1416
|
-
2,
|
|
1417
|
-
"page"
|
|
1418
|
-
],
|
|
1419
|
-
[
|
|
1420
|
-
PersonalizationStateful_dec2,
|
|
1421
|
-
2,
|
|
1422
|
-
"screen"
|
|
1423
|
-
],
|
|
1424
|
-
[
|
|
1425
|
-
PersonalizationStateful_dec3,
|
|
1426
|
-
2,
|
|
1427
|
-
"track"
|
|
1428
|
-
],
|
|
1429
|
-
[
|
|
1430
|
-
_dec4,
|
|
1431
|
-
2,
|
|
1432
|
-
"trackComponentView"
|
|
1433
|
-
]
|
|
1434
|
-
], []));
|
|
1435
|
-
}
|
|
1436
|
-
offlineQueue = (PersonalizationStateful_initProto(this), new Set());
|
|
1437
|
-
queuePolicy;
|
|
1438
|
-
flushRuntime;
|
|
1439
|
-
states = {
|
|
1440
|
-
blockedEventStream: toObservable(blockedEvent),
|
|
1441
|
-
eventStream: toObservable(signals_event),
|
|
1442
|
-
flags: toObservable(flags),
|
|
1443
|
-
profile: toObservable(signals_profile),
|
|
1444
|
-
personalizations: toObservable(signals_personalizations)
|
|
1445
|
-
};
|
|
1446
|
-
getAnonymousId;
|
|
1447
|
-
constructor(options){
|
|
1448
|
-
const { api, builder, config, interceptors } = options;
|
|
1449
|
-
super({
|
|
1450
|
-
api,
|
|
1451
|
-
builder,
|
|
1452
|
-
config,
|
|
1453
|
-
interceptors
|
|
1454
|
-
});
|
|
1455
|
-
const { defaults, getAnonymousId, queuePolicy } = config ?? {};
|
|
1456
|
-
this.queuePolicy = resolvePersonalizationQueuePolicy(queuePolicy);
|
|
1457
|
-
this.flushRuntime = new QueueFlushRuntime({
|
|
1458
|
-
policy: this.queuePolicy.flushPolicy,
|
|
1459
|
-
onRetry: ()=>{
|
|
1460
|
-
this.flush();
|
|
1461
|
-
},
|
|
1462
|
-
onCallbackError: (callbackName, error)=>{
|
|
1463
|
-
PersonalizationStateful_logger.warn(`Personalization flush policy callback "${callbackName}" failed`, error);
|
|
1464
|
-
}
|
|
1465
|
-
});
|
|
1466
|
-
if (defaults) {
|
|
1467
|
-
const { changes: defaultChanges, personalizations: defaultPersonalizations, profile: defaultProfile } = defaults;
|
|
1468
|
-
batch(()=>{
|
|
1469
|
-
signals_changes.value = defaultChanges;
|
|
1470
|
-
signals_personalizations.value = defaultPersonalizations;
|
|
1471
|
-
signals_profile.value = defaultProfile;
|
|
1472
|
-
});
|
|
1473
|
-
}
|
|
1474
|
-
if (defaults?.consent !== void 0) {
|
|
1475
|
-
const { consent: defaultConsent } = defaults;
|
|
1476
|
-
consent.value = defaultConsent;
|
|
1477
|
-
}
|
|
1478
|
-
this.getAnonymousId = getAnonymousId ?? (()=>void 0);
|
|
1479
|
-
effect(()=>{
|
|
1480
|
-
PersonalizationStateful_logger.debug(`Profile ${signals_profile.value && `with ID ${signals_profile.value.id}`} has been ${signals_profile.value ? 'set' : 'cleared'}`);
|
|
1481
|
-
});
|
|
1482
|
-
effect(()=>{
|
|
1483
|
-
PersonalizationStateful_logger.debug(`Variants have been ${signals_personalizations.value?.length ? 'populated' : 'cleared'}`);
|
|
1484
|
-
});
|
|
1485
|
-
effect(()=>{
|
|
1486
|
-
PersonalizationStateful_logger.info(`Personalization ${consent.value ? 'will' : 'will not'} take effect due to consent (${consent.value})`);
|
|
1487
|
-
});
|
|
1488
|
-
effect(()=>{
|
|
1489
|
-
if (!online.value) return;
|
|
1490
|
-
this.flushRuntime.clearScheduledRetry();
|
|
1491
|
-
this.flush({
|
|
1492
|
-
force: true
|
|
1493
|
-
});
|
|
1494
|
-
});
|
|
1495
|
-
}
|
|
1496
|
-
reset() {
|
|
1497
|
-
this.flushRuntime.reset();
|
|
1498
|
-
batch(()=>{
|
|
1499
|
-
signals_changes.value = void 0;
|
|
1500
|
-
blockedEvent.value = void 0;
|
|
1501
|
-
signals_event.value = void 0;
|
|
1502
|
-
signals_profile.value = void 0;
|
|
1503
|
-
signals_personalizations.value = void 0;
|
|
1504
|
-
});
|
|
1505
|
-
}
|
|
1506
|
-
getCustomFlag(name, changes = signals_changes.value) {
|
|
1507
|
-
return super.getCustomFlag(name, changes);
|
|
1508
|
-
}
|
|
1509
|
-
getCustomFlags(changes = signals_changes.value) {
|
|
1510
|
-
return super.getCustomFlags(changes);
|
|
1511
|
-
}
|
|
1512
|
-
personalizeEntry(entry, personalizations = signals_personalizations.value) {
|
|
1513
|
-
return super.personalizeEntry(entry, personalizations);
|
|
1514
|
-
}
|
|
1515
|
-
getMergeTagValue(embeddedEntryNodeTarget, profile = signals_profile.value) {
|
|
1516
|
-
return super.getMergeTagValue(embeddedEntryNodeTarget, profile);
|
|
1517
|
-
}
|
|
1518
|
-
hasConsent(name) {
|
|
1519
|
-
return !!consent.value || (this.allowedEventTypes ?? []).includes('trackComponentView' === name || 'trackFlagView' === name ? 'component' : name);
|
|
1520
|
-
}
|
|
1521
|
-
onBlockedByConsent(name, payload) {
|
|
1522
|
-
PersonalizationStateful_logger.warn(`Event "${name}" was blocked due to lack of consent; payload: ${JSON.stringify(payload)}`);
|
|
1523
|
-
this.reportBlockedEvent('consent', 'personalization', name, payload);
|
|
1524
|
-
}
|
|
1525
|
-
async identify(payload) {
|
|
1526
|
-
PersonalizationStateful_logger.info('Sending "identify" event');
|
|
1527
|
-
const event = this.builder.buildIdentify(payload);
|
|
1528
|
-
return await this.sendOrEnqueueEvent(event);
|
|
1529
|
-
}
|
|
1530
|
-
async page(payload) {
|
|
1531
|
-
PersonalizationStateful_logger.info('Sending "page" event');
|
|
1532
|
-
const event = this.builder.buildPageView(payload);
|
|
1533
|
-
return await this.sendOrEnqueueEvent(event);
|
|
1534
|
-
}
|
|
1535
|
-
async screen(payload) {
|
|
1536
|
-
PersonalizationStateful_logger.info(`Sending "screen" event for "${payload.name}"`);
|
|
1537
|
-
const event = this.builder.buildScreenView(payload);
|
|
1538
|
-
return await this.sendOrEnqueueEvent(event);
|
|
824
|
+
} catch (error) {
|
|
825
|
+
this.onCallbackError?.(callbackName, error);
|
|
826
|
+
}
|
|
1539
827
|
}
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
828
|
+
}
|
|
829
|
+
const ExperienceQueue_coreLogger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('CoreStateful');
|
|
830
|
+
class ExperienceQueue {
|
|
831
|
+
experienceApi;
|
|
832
|
+
eventInterceptors;
|
|
833
|
+
flushRuntime;
|
|
834
|
+
getAnonymousId;
|
|
835
|
+
offlineMaxEvents;
|
|
836
|
+
onOfflineDrop;
|
|
837
|
+
queuedExperienceEvents = new Set();
|
|
838
|
+
stateInterceptors;
|
|
839
|
+
constructor(options){
|
|
840
|
+
const { experienceApi, eventInterceptors, flushPolicy, getAnonymousId, offlineMaxEvents, onOfflineDrop, stateInterceptors } = options;
|
|
841
|
+
this.experienceApi = experienceApi;
|
|
842
|
+
this.eventInterceptors = eventInterceptors;
|
|
843
|
+
this.getAnonymousId = getAnonymousId;
|
|
844
|
+
this.offlineMaxEvents = offlineMaxEvents;
|
|
845
|
+
this.onOfflineDrop = onOfflineDrop;
|
|
846
|
+
this.stateInterceptors = stateInterceptors;
|
|
847
|
+
this.flushRuntime = new QueueFlushRuntime({
|
|
848
|
+
policy: flushPolicy,
|
|
849
|
+
onRetry: ()=>{
|
|
850
|
+
this.flush();
|
|
851
|
+
},
|
|
852
|
+
onCallbackError: (callbackName, error)=>{
|
|
853
|
+
ExperienceQueue_coreLogger.warn(`Experience flush policy callback "${callbackName}" failed`, error);
|
|
854
|
+
}
|
|
855
|
+
});
|
|
1544
856
|
}
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
const event = this.builder.buildComponentView(payload);
|
|
1548
|
-
return await this.sendOrEnqueueEvent(event);
|
|
857
|
+
clearScheduledRetry() {
|
|
858
|
+
this.flushRuntime.clearScheduledRetry();
|
|
1549
859
|
}
|
|
1550
|
-
async
|
|
1551
|
-
const intercepted = await this.
|
|
860
|
+
async send(event) {
|
|
861
|
+
const intercepted = await this.eventInterceptors.run(event);
|
|
1552
862
|
const validEvent = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.ExperienceEvent, intercepted);
|
|
1553
863
|
signals_event.value = validEvent;
|
|
1554
864
|
if (online.value) return await this.upsertProfile([
|
|
1555
865
|
validEvent
|
|
1556
866
|
]);
|
|
1557
|
-
|
|
1558
|
-
this.
|
|
1559
|
-
}
|
|
1560
|
-
enqueueOfflineEvent(event) {
|
|
1561
|
-
let droppedEvents = [];
|
|
1562
|
-
if (this.offlineQueue.size >= this.queuePolicy.maxEvents) {
|
|
1563
|
-
const dropCount = this.offlineQueue.size - this.queuePolicy.maxEvents + 1;
|
|
1564
|
-
droppedEvents = this.dropOldestOfflineEvents(dropCount);
|
|
1565
|
-
if (droppedEvents.length > 0) PersonalizationStateful_logger.warn(`Dropped ${droppedEvents.length} oldest personalization offline event(s) due to queue limit (${this.queuePolicy.maxEvents})`);
|
|
1566
|
-
}
|
|
1567
|
-
this.offlineQueue.add(event);
|
|
1568
|
-
if (droppedEvents.length > 0) this.invokeQueueDropCallback({
|
|
1569
|
-
droppedCount: droppedEvents.length,
|
|
1570
|
-
droppedEvents,
|
|
1571
|
-
maxEvents: this.queuePolicy.maxEvents,
|
|
1572
|
-
queuedEvents: this.offlineQueue.size
|
|
1573
|
-
});
|
|
1574
|
-
}
|
|
1575
|
-
dropOldestOfflineEvents(count) {
|
|
1576
|
-
const droppedEvents = [];
|
|
1577
|
-
for(let index = 0; index < count; index += 1){
|
|
1578
|
-
const oldestEvent = this.offlineQueue.values().next();
|
|
1579
|
-
if (oldestEvent.done) break;
|
|
1580
|
-
this.offlineQueue.delete(oldestEvent.value);
|
|
1581
|
-
droppedEvents.push(oldestEvent.value);
|
|
1582
|
-
}
|
|
1583
|
-
return droppedEvents;
|
|
1584
|
-
}
|
|
1585
|
-
invokeQueueDropCallback(context) {
|
|
1586
|
-
try {
|
|
1587
|
-
this.queuePolicy.onDrop?.(context);
|
|
1588
|
-
} catch (error) {
|
|
1589
|
-
PersonalizationStateful_logger.warn('Personalization offline queue drop callback failed', error);
|
|
1590
|
-
}
|
|
867
|
+
ExperienceQueue_coreLogger.debug(`Queueing ${validEvent.type} event`, validEvent);
|
|
868
|
+
this.enqueueEvent(validEvent);
|
|
1591
869
|
}
|
|
1592
870
|
async flush(options = {}) {
|
|
1593
|
-
await this.flushOfflineQueue(options);
|
|
1594
|
-
}
|
|
1595
|
-
async flushOfflineQueue(options = {}) {
|
|
1596
871
|
const { force = false } = options;
|
|
1597
872
|
if (this.flushRuntime.shouldSkip({
|
|
1598
873
|
force,
|
|
1599
874
|
isOnline: !!online.value
|
|
1600
875
|
})) return;
|
|
1601
|
-
if (0 === this.
|
|
1602
|
-
|
|
1603
|
-
const queuedEvents = Array.from(this.
|
|
876
|
+
if (0 === this.queuedExperienceEvents.size) return void this.flushRuntime.clearScheduledRetry();
|
|
877
|
+
ExperienceQueue_coreLogger.debug('Flushing offline Experience event queue');
|
|
878
|
+
const queuedEvents = Array.from(this.queuedExperienceEvents);
|
|
1604
879
|
this.flushRuntime.markFlushStarted();
|
|
1605
880
|
try {
|
|
1606
881
|
const sendSuccess = await this.tryUpsertQueuedEvents(queuedEvents);
|
|
1607
882
|
if (sendSuccess) {
|
|
1608
|
-
queuedEvents.forEach((
|
|
1609
|
-
this.
|
|
883
|
+
queuedEvents.forEach((queuedEvent)=>{
|
|
884
|
+
this.queuedExperienceEvents.delete(queuedEvent);
|
|
1610
885
|
});
|
|
1611
886
|
this.flushRuntime.handleFlushSuccess();
|
|
1612
887
|
} else this.flushRuntime.handleFlushFailure({
|
|
1613
|
-
queuedBatches: this.
|
|
1614
|
-
queuedEvents: this.
|
|
888
|
+
queuedBatches: this.queuedExperienceEvents.size > 0 ? 1 : 0,
|
|
889
|
+
queuedEvents: this.queuedExperienceEvents.size
|
|
1615
890
|
});
|
|
1616
891
|
} finally{
|
|
1617
892
|
this.flushRuntime.markFlushFinished();
|
|
1618
893
|
}
|
|
1619
894
|
}
|
|
895
|
+
enqueueEvent(event) {
|
|
896
|
+
let droppedEvents = [];
|
|
897
|
+
if (this.queuedExperienceEvents.size >= this.offlineMaxEvents) {
|
|
898
|
+
const dropCount = this.queuedExperienceEvents.size - this.offlineMaxEvents + 1;
|
|
899
|
+
droppedEvents = this.dropOldestEvents(dropCount);
|
|
900
|
+
if (droppedEvents.length > 0) ExperienceQueue_coreLogger.warn(`Dropped ${droppedEvents.length} oldest offline event(s) due to queue limit (${this.offlineMaxEvents})`);
|
|
901
|
+
}
|
|
902
|
+
this.queuedExperienceEvents.add(event);
|
|
903
|
+
if (droppedEvents.length > 0) this.invokeOfflineDropCallback({
|
|
904
|
+
droppedCount: droppedEvents.length,
|
|
905
|
+
droppedEvents,
|
|
906
|
+
maxEvents: this.offlineMaxEvents,
|
|
907
|
+
queuedEvents: this.queuedExperienceEvents.size
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
dropOldestEvents(count) {
|
|
911
|
+
const droppedEvents = [];
|
|
912
|
+
for(let index = 0; index < count; index += 1){
|
|
913
|
+
const oldestEvent = this.queuedExperienceEvents.values().next();
|
|
914
|
+
if (oldestEvent.done) break;
|
|
915
|
+
this.queuedExperienceEvents.delete(oldestEvent.value);
|
|
916
|
+
droppedEvents.push(oldestEvent.value);
|
|
917
|
+
}
|
|
918
|
+
return droppedEvents;
|
|
919
|
+
}
|
|
920
|
+
invokeOfflineDropCallback(context) {
|
|
921
|
+
try {
|
|
922
|
+
this.onOfflineDrop?.(context);
|
|
923
|
+
} catch (error) {
|
|
924
|
+
ExperienceQueue_coreLogger.warn('Offline queue drop callback failed', error);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
1620
927
|
async tryUpsertQueuedEvents(events) {
|
|
1621
928
|
try {
|
|
1622
929
|
await this.upsertProfile(events);
|
|
1623
930
|
return true;
|
|
1624
931
|
} catch (error) {
|
|
1625
|
-
|
|
932
|
+
ExperienceQueue_coreLogger.warn('Experience queue flush request threw an error', error);
|
|
1626
933
|
return false;
|
|
1627
934
|
}
|
|
1628
935
|
}
|
|
1629
936
|
async upsertProfile(events) {
|
|
1630
937
|
const anonymousId = this.getAnonymousId();
|
|
1631
|
-
if (anonymousId)
|
|
1632
|
-
const data = await this.
|
|
938
|
+
if (anonymousId) ExperienceQueue_coreLogger.debug(`Anonymous ID found: ${anonymousId}`);
|
|
939
|
+
const data = await this.experienceApi.upsertProfile({
|
|
1633
940
|
profileId: anonymousId ?? signals_profile.value?.id,
|
|
1634
941
|
events
|
|
1635
942
|
});
|
|
@@ -1637,161 +944,275 @@ class PersonalizationStateful extends personalization_PersonalizationBase {
|
|
|
1637
944
|
return data;
|
|
1638
945
|
}
|
|
1639
946
|
async updateOutputSignals(data) {
|
|
1640
|
-
const intercepted = await this.
|
|
1641
|
-
const { changes,
|
|
947
|
+
const intercepted = await this.stateInterceptors.run(data);
|
|
948
|
+
const { changes, profile, selectedOptimizations } = intercepted;
|
|
1642
949
|
batch(()=>{
|
|
1643
|
-
if (!
|
|
1644
|
-
if (!
|
|
1645
|
-
if (!
|
|
950
|
+
if (!predicate_isEqual(signals_changes.value, changes)) signals_changes.value = changes;
|
|
951
|
+
if (!predicate_isEqual(signals_profile.value, profile)) signals_profile.value = profile;
|
|
952
|
+
if (!predicate_isEqual(signals_selectedOptimizations.value, selectedOptimizations)) signals_selectedOptimizations.value = selectedOptimizations;
|
|
1646
953
|
});
|
|
1647
954
|
}
|
|
1648
955
|
}
|
|
1649
|
-
const
|
|
1650
|
-
const
|
|
1651
|
-
class
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
const {
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
956
|
+
const InsightsQueue_coreLogger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('CoreStateful');
|
|
957
|
+
const MAX_QUEUED_INSIGHTS_EVENTS = 25;
|
|
958
|
+
class InsightsQueue {
|
|
959
|
+
eventInterceptors;
|
|
960
|
+
flushIntervalMs;
|
|
961
|
+
flushRuntime;
|
|
962
|
+
insightsApi;
|
|
963
|
+
queuedInsightsByProfile = new Map();
|
|
964
|
+
insightsPeriodicFlushTimer;
|
|
965
|
+
constructor(options){
|
|
966
|
+
const { eventInterceptors, flushPolicy, insightsApi } = options;
|
|
967
|
+
const { flushIntervalMs } = flushPolicy;
|
|
968
|
+
this.eventInterceptors = eventInterceptors;
|
|
969
|
+
this.flushIntervalMs = flushIntervalMs;
|
|
970
|
+
this.insightsApi = insightsApi;
|
|
971
|
+
this.flushRuntime = new QueueFlushRuntime({
|
|
972
|
+
policy: flushPolicy,
|
|
973
|
+
onRetry: ()=>{
|
|
974
|
+
this.flush();
|
|
975
|
+
},
|
|
976
|
+
onCallbackError: (callbackName, error)=>{
|
|
977
|
+
InsightsQueue_coreLogger.warn(`Insights flush policy callback "${callbackName}" failed`, error);
|
|
978
|
+
}
|
|
979
|
+
});
|
|
1669
980
|
}
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
const { profile, ...builderArgs } = payload;
|
|
1673
|
-
const event = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.TrackEvent, this.builder.buildTrack(builderArgs));
|
|
1674
|
-
return await this.upsertProfile(event, profile);
|
|
981
|
+
clearScheduledRetry() {
|
|
982
|
+
this.flushRuntime.clearScheduledRetry();
|
|
1675
983
|
}
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
return await this.upsertProfile(event, profile);
|
|
984
|
+
clearPeriodicFlushTimer() {
|
|
985
|
+
if (void 0 === this.insightsPeriodicFlushTimer) return;
|
|
986
|
+
clearInterval(this.insightsPeriodicFlushTimer);
|
|
987
|
+
this.insightsPeriodicFlushTimer = void 0;
|
|
1681
988
|
}
|
|
1682
|
-
async
|
|
1683
|
-
const
|
|
1684
|
-
|
|
1685
|
-
const
|
|
1686
|
-
|
|
989
|
+
async send(event) {
|
|
990
|
+
const { value: profile } = signals_profile;
|
|
991
|
+
if (!profile) return void InsightsQueue_coreLogger.warn('Attempting to emit an event without an Optimization profile');
|
|
992
|
+
const intercepted = await this.eventInterceptors.run(event);
|
|
993
|
+
const validEvent = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.InsightsEvent, intercepted);
|
|
994
|
+
InsightsQueue_coreLogger.debug(`Queueing ${validEvent.type} event for profile ${profile.id}`, validEvent);
|
|
995
|
+
const queuedProfileEvents = this.queuedInsightsByProfile.get(profile.id);
|
|
996
|
+
signals_event.value = validEvent;
|
|
997
|
+
if (queuedProfileEvents) {
|
|
998
|
+
queuedProfileEvents.profile = profile;
|
|
999
|
+
queuedProfileEvents.events.push(validEvent);
|
|
1000
|
+
} else this.queuedInsightsByProfile.set(profile.id, {
|
|
1001
|
+
profile,
|
|
1687
1002
|
events: [
|
|
1688
1003
|
validEvent
|
|
1689
1004
|
]
|
|
1690
1005
|
});
|
|
1691
|
-
|
|
1006
|
+
this.ensurePeriodicFlushTimer();
|
|
1007
|
+
if (this.getQueuedEventCount() >= MAX_QUEUED_INSIGHTS_EVENTS) await this.flush();
|
|
1008
|
+
this.reconcilePeriodicFlushTimer();
|
|
1009
|
+
}
|
|
1010
|
+
async flush(options = {}) {
|
|
1011
|
+
const { force = false } = options;
|
|
1012
|
+
if (this.flushRuntime.shouldSkip({
|
|
1013
|
+
force,
|
|
1014
|
+
isOnline: !!online.value
|
|
1015
|
+
})) return;
|
|
1016
|
+
InsightsQueue_coreLogger.debug('Flushing insights event queue');
|
|
1017
|
+
const batches = this.createBatches();
|
|
1018
|
+
if (!batches.length) {
|
|
1019
|
+
this.flushRuntime.clearScheduledRetry();
|
|
1020
|
+
this.reconcilePeriodicFlushTimer();
|
|
1021
|
+
return;
|
|
1022
|
+
}
|
|
1023
|
+
this.flushRuntime.markFlushStarted();
|
|
1024
|
+
try {
|
|
1025
|
+
const sendSuccess = await this.trySendBatches(batches);
|
|
1026
|
+
if (sendSuccess) {
|
|
1027
|
+
this.queuedInsightsByProfile.clear();
|
|
1028
|
+
this.flushRuntime.handleFlushSuccess();
|
|
1029
|
+
} else this.flushRuntime.handleFlushFailure({
|
|
1030
|
+
queuedBatches: batches.length,
|
|
1031
|
+
queuedEvents: this.getQueuedEventCount()
|
|
1032
|
+
});
|
|
1033
|
+
} finally{
|
|
1034
|
+
this.flushRuntime.markFlushFinished();
|
|
1035
|
+
this.reconcilePeriodicFlushTimer();
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
createBatches() {
|
|
1039
|
+
const batches = [];
|
|
1040
|
+
this.queuedInsightsByProfile.forEach(({ profile, events })=>{
|
|
1041
|
+
batches.push({
|
|
1042
|
+
profile,
|
|
1043
|
+
events
|
|
1044
|
+
});
|
|
1045
|
+
});
|
|
1046
|
+
return batches;
|
|
1047
|
+
}
|
|
1048
|
+
async trySendBatches(batches) {
|
|
1049
|
+
try {
|
|
1050
|
+
return await this.insightsApi.sendBatchEvents(batches);
|
|
1051
|
+
} catch (error) {
|
|
1052
|
+
InsightsQueue_coreLogger.warn('Insights queue flush request threw an error', error);
|
|
1053
|
+
return false;
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
getQueuedEventCount() {
|
|
1057
|
+
let queuedCount = 0;
|
|
1058
|
+
this.queuedInsightsByProfile.forEach(({ events })=>{
|
|
1059
|
+
queuedCount += events.length;
|
|
1060
|
+
});
|
|
1061
|
+
return queuedCount;
|
|
1062
|
+
}
|
|
1063
|
+
ensurePeriodicFlushTimer() {
|
|
1064
|
+
if (void 0 !== this.insightsPeriodicFlushTimer) return;
|
|
1065
|
+
if (0 === this.getQueuedEventCount()) return;
|
|
1066
|
+
this.insightsPeriodicFlushTimer = setInterval(()=>{
|
|
1067
|
+
this.flush();
|
|
1068
|
+
}, this.flushIntervalMs);
|
|
1069
|
+
}
|
|
1070
|
+
reconcilePeriodicFlushTimer() {
|
|
1071
|
+
if (this.getQueuedEventCount() > 0) return void this.ensurePeriodicFlushTimer();
|
|
1072
|
+
this.clearPeriodicFlushTimer();
|
|
1692
1073
|
}
|
|
1693
1074
|
}
|
|
1694
|
-
const
|
|
1695
|
-
const
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1075
|
+
const CoreStateful_coreLogger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('CoreStateful');
|
|
1076
|
+
const DEFAULT_ALLOWED_EVENT_TYPES = [
|
|
1077
|
+
'identify',
|
|
1078
|
+
'page',
|
|
1079
|
+
'screen'
|
|
1080
|
+
];
|
|
1081
|
+
const OFFLINE_QUEUE_MAX_EVENTS = 100;
|
|
1082
|
+
const hasDefinedValues = (record)=>Object.values(record).some((value)=>void 0 !== value);
|
|
1083
|
+
const createStatefulExperienceApiConfig = (api)=>{
|
|
1084
|
+
if (void 0 === api) return;
|
|
1085
|
+
const experienceConfig = {
|
|
1086
|
+
baseUrl: api.experienceBaseUrl,
|
|
1087
|
+
enabledFeatures: api.enabledFeatures,
|
|
1088
|
+
ip: api.ip,
|
|
1089
|
+
locale: api.locale,
|
|
1090
|
+
plainText: api.plainText,
|
|
1091
|
+
preflight: api.preflight
|
|
1699
1092
|
};
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1093
|
+
return hasDefinedValues(experienceConfig) ? experienceConfig : void 0;
|
|
1094
|
+
};
|
|
1095
|
+
const createStatefulInsightsApiConfig = (api)=>{
|
|
1096
|
+
if (void 0 === api) return;
|
|
1097
|
+
const insightsConfig = {
|
|
1098
|
+
baseUrl: api.insightsBaseUrl,
|
|
1099
|
+
beaconHandler: api.beaconHandler
|
|
1705
1100
|
};
|
|
1101
|
+
return hasDefinedValues(insightsConfig) ? insightsConfig : void 0;
|
|
1706
1102
|
};
|
|
1103
|
+
const resolveQueuePolicy = (policy)=>({
|
|
1104
|
+
flush: resolveQueueFlushPolicy(policy?.flush),
|
|
1105
|
+
offlineMaxEvents: toPositiveInt(policy?.offlineMaxEvents, OFFLINE_QUEUE_MAX_EVENTS),
|
|
1106
|
+
onOfflineDrop: policy?.onOfflineDrop
|
|
1107
|
+
});
|
|
1707
1108
|
let statefulInstanceCounter = 0;
|
|
1708
|
-
class CoreStateful extends
|
|
1109
|
+
class CoreStateful extends src_CoreStatefulEventEmitter {
|
|
1709
1110
|
singletonOwner;
|
|
1710
1111
|
destroyed = false;
|
|
1711
|
-
|
|
1712
|
-
|
|
1112
|
+
allowedEventTypes;
|
|
1113
|
+
experienceQueue;
|
|
1114
|
+
insightsQueue;
|
|
1115
|
+
onEventBlocked;
|
|
1116
|
+
states = {
|
|
1117
|
+
blockedEventStream: toObservable(blockedEvent),
|
|
1118
|
+
flag: (name)=>this.getFlagObservable(name),
|
|
1119
|
+
consent: toObservable(consent),
|
|
1120
|
+
eventStream: toObservable(signals_event),
|
|
1121
|
+
canOptimize: toObservable(canOptimize),
|
|
1122
|
+
selectedOptimizations: toObservable(signals_selectedOptimizations),
|
|
1123
|
+
previewPanelAttached: toObservable(previewPanelAttached),
|
|
1124
|
+
previewPanelOpen: toObservable(previewPanelOpen),
|
|
1125
|
+
profile: toObservable(signals_profile)
|
|
1126
|
+
};
|
|
1713
1127
|
constructor(config){
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
analytics: analyticsApiConfig,
|
|
1719
|
-
personalization: personalizationApiConfig
|
|
1720
|
-
};
|
|
1721
|
-
super(baseConfig);
|
|
1128
|
+
super(config, {
|
|
1129
|
+
experience: createStatefulExperienceApiConfig(config.api),
|
|
1130
|
+
insights: createStatefulInsightsApiConfig(config.api)
|
|
1131
|
+
});
|
|
1722
1132
|
this.singletonOwner = `CoreStateful#${++statefulInstanceCounter}`;
|
|
1723
1133
|
acquireStatefulRuntimeSingleton(this.singletonOwner);
|
|
1724
1134
|
try {
|
|
1725
|
-
const { allowedEventTypes, defaults, getAnonymousId, onEventBlocked } = config;
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
this.
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
allowedEventTypes,
|
|
1735
|
-
queuePolicy: analyticsRuntimeQueuePolicy,
|
|
1736
|
-
onEventBlocked,
|
|
1737
|
-
defaults: {
|
|
1738
|
-
consent: defaults?.consent,
|
|
1739
|
-
profile: defaults?.profile
|
|
1740
|
-
}
|
|
1741
|
-
},
|
|
1742
|
-
interceptors: this.interceptors
|
|
1135
|
+
const { allowedEventTypes, defaults, getAnonymousId, onEventBlocked, queuePolicy } = config;
|
|
1136
|
+
const { changes: defaultChanges, consent: defaultConsent, selectedOptimizations: defaultSelectedOptimizations, profile: defaultProfile } = defaults ?? {};
|
|
1137
|
+
const resolvedQueuePolicy = resolveQueuePolicy(queuePolicy);
|
|
1138
|
+
this.allowedEventTypes = allowedEventTypes ?? DEFAULT_ALLOWED_EVENT_TYPES;
|
|
1139
|
+
this.onEventBlocked = onEventBlocked;
|
|
1140
|
+
this.insightsQueue = new InsightsQueue({
|
|
1141
|
+
eventInterceptors: this.interceptors.event,
|
|
1142
|
+
flushPolicy: resolvedQueuePolicy.flush,
|
|
1143
|
+
insightsApi: this.api.insights
|
|
1743
1144
|
});
|
|
1744
|
-
this.
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
},
|
|
1759
|
-
interceptors: this.interceptors
|
|
1145
|
+
this.experienceQueue = new ExperienceQueue({
|
|
1146
|
+
experienceApi: this.api.experience,
|
|
1147
|
+
eventInterceptors: this.interceptors.event,
|
|
1148
|
+
flushPolicy: resolvedQueuePolicy.flush,
|
|
1149
|
+
getAnonymousId: getAnonymousId ?? (()=>void 0),
|
|
1150
|
+
offlineMaxEvents: resolvedQueuePolicy.offlineMaxEvents,
|
|
1151
|
+
onOfflineDrop: resolvedQueuePolicy.onOfflineDrop,
|
|
1152
|
+
stateInterceptors: this.interceptors.state
|
|
1153
|
+
});
|
|
1154
|
+
if (void 0 !== defaultConsent) consent.value = defaultConsent;
|
|
1155
|
+
batch(()=>{
|
|
1156
|
+
if (void 0 !== defaultChanges) signals_changes.value = defaultChanges;
|
|
1157
|
+
if (void 0 !== defaultSelectedOptimizations) signals_selectedOptimizations.value = defaultSelectedOptimizations;
|
|
1158
|
+
if (void 0 !== defaultProfile) signals_profile.value = defaultProfile;
|
|
1760
1159
|
});
|
|
1160
|
+
this.initializeEffects();
|
|
1761
1161
|
} catch (error) {
|
|
1762
1162
|
releaseStatefulRuntimeSingleton(this.singletonOwner);
|
|
1763
1163
|
throw error;
|
|
1764
1164
|
}
|
|
1765
1165
|
}
|
|
1166
|
+
initializeEffects() {
|
|
1167
|
+
effect(()=>{
|
|
1168
|
+
CoreStateful_coreLogger.debug(`Profile ${signals_profile.value && `with ID ${signals_profile.value.id}`} has been ${signals_profile.value ? 'set' : 'cleared'}`);
|
|
1169
|
+
});
|
|
1170
|
+
effect(()=>{
|
|
1171
|
+
CoreStateful_coreLogger.debug(`Variants have been ${signals_selectedOptimizations.value?.length ? 'populated' : 'cleared'}`);
|
|
1172
|
+
});
|
|
1173
|
+
effect(()=>{
|
|
1174
|
+
CoreStateful_coreLogger.info(`Core ${consent.value ? 'will' : 'will not'} emit gated events due to consent (${consent.value})`);
|
|
1175
|
+
});
|
|
1176
|
+
effect(()=>{
|
|
1177
|
+
if (!online.value) return;
|
|
1178
|
+
this.insightsQueue.clearScheduledRetry();
|
|
1179
|
+
this.experienceQueue.clearScheduledRetry();
|
|
1180
|
+
this.flushQueues({
|
|
1181
|
+
force: true
|
|
1182
|
+
});
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
async flushQueues(options = {}) {
|
|
1186
|
+
await this.insightsQueue.flush(options);
|
|
1187
|
+
await this.experienceQueue.flush(options);
|
|
1188
|
+
}
|
|
1766
1189
|
destroy() {
|
|
1767
1190
|
if (this.destroyed) return;
|
|
1768
1191
|
this.destroyed = true;
|
|
1192
|
+
this.insightsQueue.flush({
|
|
1193
|
+
force: true
|
|
1194
|
+
}).catch((error)=>{
|
|
1195
|
+
__rspack_external__contentful_optimization_api_client_logger_f0d05f82.logger.warn('Failed to flush insights queue during destroy()', String(error));
|
|
1196
|
+
});
|
|
1197
|
+
this.experienceQueue.flush({
|
|
1198
|
+
force: true
|
|
1199
|
+
}).catch((error)=>{
|
|
1200
|
+
__rspack_external__contentful_optimization_api_client_logger_f0d05f82.logger.warn('Failed to flush Experience queue during destroy()', String(error));
|
|
1201
|
+
});
|
|
1202
|
+
this.insightsQueue.clearPeriodicFlushTimer();
|
|
1769
1203
|
releaseStatefulRuntimeSingleton(this.singletonOwner);
|
|
1770
1204
|
}
|
|
1771
|
-
get states() {
|
|
1772
|
-
return {
|
|
1773
|
-
blockedEventStream: toObservable(blockedEvent),
|
|
1774
|
-
consent: toObservable(consent),
|
|
1775
|
-
eventStream: toObservable(signals_event),
|
|
1776
|
-
flags: toObservable(flags),
|
|
1777
|
-
personalizations: toObservable(signals_personalizations),
|
|
1778
|
-
previewPanelAttached: toObservable(previewPanelAttached),
|
|
1779
|
-
previewPanelOpen: toObservable(previewPanelOpen),
|
|
1780
|
-
profile: toObservable(signals_profile)
|
|
1781
|
-
};
|
|
1782
|
-
}
|
|
1783
1205
|
reset() {
|
|
1784
1206
|
batch(()=>{
|
|
1785
1207
|
blockedEvent.value = void 0;
|
|
1786
1208
|
signals_event.value = void 0;
|
|
1787
1209
|
signals_changes.value = void 0;
|
|
1788
1210
|
signals_profile.value = void 0;
|
|
1789
|
-
|
|
1211
|
+
signals_selectedOptimizations.value = void 0;
|
|
1790
1212
|
});
|
|
1791
1213
|
}
|
|
1792
1214
|
async flush() {
|
|
1793
|
-
await this.
|
|
1794
|
-
await this._personalization.flush();
|
|
1215
|
+
await this.flushQueues();
|
|
1795
1216
|
}
|
|
1796
1217
|
consent(accept) {
|
|
1797
1218
|
consent.value = accept;
|
|
@@ -1808,26 +1229,160 @@ class CoreStateful extends src_CoreBase {
|
|
|
1808
1229
|
}
|
|
1809
1230
|
}
|
|
1810
1231
|
const src_CoreStateful = CoreStateful;
|
|
1232
|
+
const TRACK_CLICK_PROFILE_ERROR = 'CoreStateless.forRequest().trackClick() requires `payload.profile.id` for Insights delivery.';
|
|
1233
|
+
const TRACK_HOVER_PROFILE_ERROR = 'CoreStateless.forRequest().trackHover() requires `payload.profile.id` for Insights delivery.';
|
|
1234
|
+
const TRACK_FLAG_VIEW_PROFILE_ERROR = 'CoreStateless.forRequest().trackFlagView() requires `payload.profile.id` for Insights delivery.';
|
|
1235
|
+
const NON_STICKY_TRACK_VIEW_PROFILE_ERROR = 'CoreStateless.forRequest().trackView() requires `payload.profile.id` when `payload.sticky` is not `true`.';
|
|
1236
|
+
const STICKY_TRACK_VIEW_PROFILE_ERROR = 'CoreStateless.forRequest().trackView() could not derive a profile from the sticky Experience response. Pass `payload.profile.id` explicitly if you need a fallback.';
|
|
1237
|
+
const requireInsightsProfile = (profile, errorMessage)=>{
|
|
1238
|
+
if (void 0 !== profile) return profile;
|
|
1239
|
+
throw new Error(errorMessage);
|
|
1240
|
+
};
|
|
1241
|
+
class CoreStatelessRequestScope {
|
|
1242
|
+
core;
|
|
1243
|
+
options;
|
|
1244
|
+
constructor(core, options = {}){
|
|
1245
|
+
this.core = core;
|
|
1246
|
+
this.options = Object.freeze({
|
|
1247
|
+
...options
|
|
1248
|
+
});
|
|
1249
|
+
}
|
|
1250
|
+
async identify(payload) {
|
|
1251
|
+
const { profile, ...builderArgs } = payload;
|
|
1252
|
+
return await this.sendExperienceEvent(this.core.eventBuilder.buildIdentify(builderArgs), profile);
|
|
1253
|
+
}
|
|
1254
|
+
async page(payload = {}) {
|
|
1255
|
+
const { profile, ...builderArgs } = payload;
|
|
1256
|
+
return await this.sendExperienceEvent(this.core.eventBuilder.buildPageView(builderArgs), profile);
|
|
1257
|
+
}
|
|
1258
|
+
async screen(payload) {
|
|
1259
|
+
const { profile, ...builderArgs } = payload;
|
|
1260
|
+
return await this.sendExperienceEvent(this.core.eventBuilder.buildScreenView(builderArgs), profile);
|
|
1261
|
+
}
|
|
1262
|
+
async track(payload) {
|
|
1263
|
+
const { profile, ...builderArgs } = payload;
|
|
1264
|
+
return await this.sendExperienceEvent(this.core.eventBuilder.buildTrack(builderArgs), profile);
|
|
1265
|
+
}
|
|
1266
|
+
async trackView(payload) {
|
|
1267
|
+
const { profile, ...builderArgs } = payload;
|
|
1268
|
+
let result;
|
|
1269
|
+
let insightsProfile = profile;
|
|
1270
|
+
if (payload.sticky) {
|
|
1271
|
+
result = await this.sendExperienceEvent(this.core.eventBuilder.buildView(builderArgs), profile);
|
|
1272
|
+
const { profile: responseProfile } = result;
|
|
1273
|
+
insightsProfile = responseProfile;
|
|
1274
|
+
}
|
|
1275
|
+
await this.sendInsightsEvent(this.core.eventBuilder.buildView(builderArgs), requireInsightsProfile(insightsProfile, payload.sticky ? STICKY_TRACK_VIEW_PROFILE_ERROR : NON_STICKY_TRACK_VIEW_PROFILE_ERROR));
|
|
1276
|
+
return result;
|
|
1277
|
+
}
|
|
1278
|
+
async trackClick(payload) {
|
|
1279
|
+
const { profile, ...builderArgs } = payload;
|
|
1280
|
+
await this.sendInsightsEvent(this.core.eventBuilder.buildClick(builderArgs), requireInsightsProfile(profile, TRACK_CLICK_PROFILE_ERROR));
|
|
1281
|
+
}
|
|
1282
|
+
async trackHover(payload) {
|
|
1283
|
+
const { profile, ...builderArgs } = payload;
|
|
1284
|
+
await this.sendInsightsEvent(this.core.eventBuilder.buildHover(builderArgs), requireInsightsProfile(profile, TRACK_HOVER_PROFILE_ERROR));
|
|
1285
|
+
}
|
|
1286
|
+
async trackFlagView(payload) {
|
|
1287
|
+
const { profile, ...builderArgs } = payload;
|
|
1288
|
+
await this.sendInsightsEvent(this.core.eventBuilder.buildFlagView(builderArgs), requireInsightsProfile(profile, TRACK_FLAG_VIEW_PROFILE_ERROR));
|
|
1289
|
+
}
|
|
1290
|
+
async sendExperienceEvent(event, profile) {
|
|
1291
|
+
const intercepted = await this.core.interceptors.event.run(event);
|
|
1292
|
+
const validEvent = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.ExperienceEvent, intercepted);
|
|
1293
|
+
return await this.core.api.experience.upsertProfile({
|
|
1294
|
+
profileId: profile?.id,
|
|
1295
|
+
events: [
|
|
1296
|
+
validEvent
|
|
1297
|
+
]
|
|
1298
|
+
}, this.options);
|
|
1299
|
+
}
|
|
1300
|
+
async sendInsightsEvent(event, profile) {
|
|
1301
|
+
const intercepted = await this.core.interceptors.event.run(event);
|
|
1302
|
+
const validEvent = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.InsightsEvent, intercepted);
|
|
1303
|
+
const batchEvent = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.BatchInsightsEventArray, [
|
|
1304
|
+
{
|
|
1305
|
+
profile: (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.PartialProfile, profile),
|
|
1306
|
+
events: [
|
|
1307
|
+
validEvent
|
|
1308
|
+
]
|
|
1309
|
+
}
|
|
1310
|
+
]);
|
|
1311
|
+
await this.core.api.insights.sendBatchEvents(batchEvent);
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
const CoreStateless_hasDefinedValues = (record)=>Object.values(record).some((value)=>void 0 !== value);
|
|
1315
|
+
const createStatelessExperienceApiConfig = (api)=>{
|
|
1316
|
+
if (void 0 === api) return;
|
|
1317
|
+
const experienceConfig = {
|
|
1318
|
+
baseUrl: api.experienceBaseUrl,
|
|
1319
|
+
enabledFeatures: api.enabledFeatures
|
|
1320
|
+
};
|
|
1321
|
+
return CoreStateless_hasDefinedValues(experienceConfig) ? experienceConfig : void 0;
|
|
1322
|
+
};
|
|
1323
|
+
const createStatelessInsightsApiConfig = (api)=>{
|
|
1324
|
+
if (api?.insightsBaseUrl === void 0) return;
|
|
1325
|
+
return {
|
|
1326
|
+
baseUrl: api.insightsBaseUrl
|
|
1327
|
+
};
|
|
1328
|
+
};
|
|
1811
1329
|
class CoreStateless extends src_CoreBase {
|
|
1812
|
-
_analytics;
|
|
1813
|
-
_personalization;
|
|
1814
1330
|
constructor(config){
|
|
1815
|
-
super(config
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
builder: this.eventBuilder,
|
|
1819
|
-
interceptors: this.interceptors
|
|
1820
|
-
});
|
|
1821
|
-
this._personalization = new personalization_PersonalizationStateless({
|
|
1822
|
-
api: this.api,
|
|
1823
|
-
builder: this.eventBuilder,
|
|
1824
|
-
interceptors: this.interceptors
|
|
1331
|
+
super(config, {
|
|
1332
|
+
experience: createStatelessExperienceApiConfig(config.api),
|
|
1333
|
+
insights: createStatelessInsightsApiConfig(config.api)
|
|
1825
1334
|
});
|
|
1826
1335
|
}
|
|
1336
|
+
forRequest(options = {}) {
|
|
1337
|
+
return new CoreStatelessRequestScope(this, options);
|
|
1338
|
+
}
|
|
1827
1339
|
}
|
|
1828
1340
|
const src_CoreStateless = CoreStateless;
|
|
1829
|
-
|
|
1341
|
+
const isFunction = (v)=>'function' == typeof v;
|
|
1342
|
+
const nameToString = (name)=>'string' == typeof name ? name : 'symbol' == typeof name ? name.description ?? String(name) : String(name);
|
|
1343
|
+
const isOnBlockedKey = (v)=>'string' == typeof v || 'symbol' == typeof v;
|
|
1344
|
+
const isAsyncFunction = (fn)=>'[object AsyncFunction]' === Object.prototype.toString.call(fn);
|
|
1345
|
+
function guardedBy(predicateName, opts) {
|
|
1346
|
+
return function(_value, context) {
|
|
1347
|
+
const decoratedName = nameToString(context.name);
|
|
1348
|
+
context.addInitializer(function() {
|
|
1349
|
+
const originalUnknown = Reflect.get(this, context.name);
|
|
1350
|
+
if (!isFunction(originalUnknown)) return;
|
|
1351
|
+
const original = originalUnknown;
|
|
1352
|
+
const originalIsAsync = isAsyncFunction(original);
|
|
1353
|
+
const resolvePredicate = (self)=>{
|
|
1354
|
+
const { [predicateName]: cand } = self;
|
|
1355
|
+
if (!isFunction(cand)) throw new TypeError(`@guardedBy expects predicate "${String(predicateName)}" to be a synchronous function.`);
|
|
1356
|
+
return cand;
|
|
1357
|
+
};
|
|
1358
|
+
const computeAllowed = (self, args)=>{
|
|
1359
|
+
const pred = resolvePredicate(self);
|
|
1360
|
+
const ok = Boolean(pred.call(self, decoratedName, args));
|
|
1361
|
+
return opts?.invert === true ? !ok : ok;
|
|
1362
|
+
};
|
|
1363
|
+
const runOnBlocked = (self, args)=>{
|
|
1364
|
+
const { onBlocked } = opts ?? {};
|
|
1365
|
+
if (void 0 === onBlocked) return;
|
|
1366
|
+
if (isFunction(onBlocked)) return void onBlocked.call(self, decoratedName, args);
|
|
1367
|
+
if (isOnBlockedKey(onBlocked)) {
|
|
1368
|
+
const { [onBlocked]: handlerCandidate } = self;
|
|
1369
|
+
if (isFunction(handlerCandidate)) handlerCandidate.call(self, decoratedName, args);
|
|
1370
|
+
}
|
|
1371
|
+
};
|
|
1372
|
+
const blockedReturn = ()=>originalIsAsync ? Promise.resolve(void 0) : void 0;
|
|
1373
|
+
const wrapped = function(...args) {
|
|
1374
|
+
if (!computeAllowed(this, args)) {
|
|
1375
|
+
runOnBlocked(this, args);
|
|
1376
|
+
return blockedReturn();
|
|
1377
|
+
}
|
|
1378
|
+
return original.call(this, ...args);
|
|
1379
|
+
};
|
|
1380
|
+
Reflect.set(this, context.name, wrapped);
|
|
1381
|
+
});
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
export { ANONYMOUS_ID_COOKIE, ANONYMOUS_ID_COOKIE_LEGACY, ANONYMOUS_ID_KEY, ANONYMOUS_ID_KEY_LEGACY, CHANGES_CACHE_KEY, CONSENT_KEY, DEBUG_FLAG_KEY, OPTIMIZATION_CORE_SDK_NAME, OPTIMIZATION_CORE_SDK_VERSION, PROFILE_CACHE_KEY, SELECTED_OPTIMIZATIONS_CACHE_KEY } from "./260.mjs";
|
|
1830
1385
|
export { PREVIEW_PANEL_SIGNALS_SYMBOL, PREVIEW_PANEL_SIGNAL_FNS_SYMBOL } from "./632.mjs";
|
|
1831
|
-
export {
|
|
1386
|
+
export { ClickBuilderArgs, CoreStatelessRequestScope, DEFAULT_PAGE_PROPERTIES, EntryInteractionBuilderArgsBase, FlagViewBuilderArgs, HoverBuilderArgs, IdentifyBuilderArgs, InterceptorManager, PageViewBuilderArgs, ScreenViewBuilderArgs, TrackBuilderArgs, UniversalEventBuilderArgs, ViewBuilderArgs, batch, effect, events_EventBuilder as EventBuilder, guardedBy, resolvers_FlagsResolver as FlagsResolver, resolvers_MergeTagValueResolver as MergeTagValueResolver, resolvers_OptimizedEntryResolver as OptimizedEntryResolver, signalFns, signals, src_CoreStateful as CoreStateful, src_CoreStateless as CoreStateless, toDistinctObservable, toObservable };
|
|
1832
1387
|
|
|
1833
1388
|
//# sourceMappingURL=index.mjs.map
|