@contentful/optimization-core 0.1.0-alpha10 → 0.1.0-alpha12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,10 +1,323 @@
1
1
  import { batch, computed, effect, signal, untracked } from "@preact/signals-core";
2
- import { isEqual } from "es-toolkit/predicate";
3
- import { __rspack_external__contentful_optimization_api_client_api_schemas_4192893e } from "./808.mjs";
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)('Personalization');
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 PersonalizedEntryResolver_logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('Personalization');
63
- const PersonalizedEntryResolver_RESOLUTION_WARNING_BASE = 'Could not resolve personalized entry variant:';
64
- const PersonalizedEntryResolver = {
65
- getPersonalizationEntry ({ personalizedEntry, selectedPersonalizations }, skipValidation = false) {
66
- if (!skipValidation && (!selectedPersonalizations.length || !(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isPersonalizedEntry)(personalizedEntry))) return;
67
- const personalizationEntry = personalizedEntry.fields.nt_experiences.filter((maybePersonalization)=>(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isPersonalizationEntry)(maybePersonalization)).find((personalizationEntry)=>selectedPersonalizations.some(({ experienceId })=>experienceId === personalizationEntry.fields.nt_experience_id));
68
- return personalizationEntry;
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
- getSelectedPersonalization ({ personalizationEntry, selectedPersonalizations }, skipValidation = false) {
71
- if (!skipValidation && (!selectedPersonalizations.length || !(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isPersonalizationEntry)(personalizationEntry))) return;
72
- const selectedPersonalization = selectedPersonalizations.find(({ experienceId })=>experienceId === personalizationEntry.fields.nt_experience_id);
73
- return selectedPersonalization;
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 ({ personalizedEntry, personalizationEntry, selectedVariantIndex }, skipValidation = false) {
76
- if (!skipValidation && (!(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isPersonalizedEntry)(personalizedEntry) || !(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isPersonalizationEntry)(personalizationEntry))) return;
77
- const relevantVariants = personalizationEntry.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 === personalizedEntry.sys.id)?.variants;
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 ({ personalizationEntry, selectedVariant }, skipValidation = false) {
82
- if (!skipValidation && (!(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isPersonalizationEntry)(personalizationEntry) || !(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isEntryReplacementVariant)(selectedVariant))) return;
83
- const selectedVariantEntry = personalizationEntry.fields.nt_variants?.find((variant)=>variant.sys.id === selectedVariant.id);
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 (entry, selectedPersonalizations) {
87
- PersonalizedEntryResolver_logger.debug(`Resolving personalized entry for baseline entry ${entry.sys.id}`);
88
- if (!selectedPersonalizations?.length) {
89
- PersonalizedEntryResolver_logger.warn(`${PersonalizedEntryResolver_RESOLUTION_WARNING_BASE} no selectedPersonalizations exist for the current profile`);
90
- return {
91
- entry
92
- };
93
- }
94
- if (!(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isPersonalizedEntry)(entry)) {
95
- PersonalizedEntryResolver_logger.warn(`${PersonalizedEntryResolver_RESOLUTION_WARNING_BASE} entry ${entry.sys.id} is not personalized`);
96
- return {
97
- entry
98
- };
99
- }
100
- const personalizationEntry = PersonalizedEntryResolver.getPersonalizationEntry({
101
- personalizedEntry: entry,
102
- selectedPersonalizations
103
- }, true);
104
- if (!personalizationEntry) {
105
- PersonalizedEntryResolver_logger.warn(`${PersonalizedEntryResolver_RESOLUTION_WARNING_BASE} could not find a personalization entry for ${entry.sys.id}`);
106
- return {
107
- entry
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
- const resolvers_PersonalizedEntryResolver = PersonalizedEntryResolver;
150
- const signals_changes = signal();
151
- const blockedEvent = signal();
152
- const consent = signal();
153
- const signals_event = signal();
154
- const flags = computed(()=>resolvers_FlagsResolver.resolve(signals_changes.value ?? []));
155
- const online = signal(true);
156
- const previewPanelAttached = signal(false);
157
- const previewPanelOpen = signal(false);
158
- const signals_personalizations = signal();
159
- const signals_profile = signal();
160
- function toObservable(s) {
161
- return {
162
- subscribe (next) {
163
- const dispose = effect(()=>{
164
- next(s.value);
165
- });
166
- return {
167
- unsubscribe: dispose
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 baseBackoffMs = toPositiveInt(policy?.baseBackoffMs, defaults.baseBackoffMs);
250
- const maxBackoffMs = Math.max(baseBackoffMs, toPositiveInt(policy?.maxBackoffMs, defaults.maxBackoffMs));
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(policy?.jitterRatio, defaults.jitterRatio),
255
- maxConsecutiveFailures: toPositiveInt(policy?.maxConsecutiveFailures, defaults.maxConsecutiveFailures),
256
- circuitOpenMs: toPositiveInt(policy?.circuitOpenMs, defaults.circuitOpenMs),
257
- onCircuitOpen: policy?.onCircuitOpen,
258
- onFlushFailure: policy?.onFlushFailure,
259
- onFlushRecovered: policy?.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;
@@ -378,1258 +818,125 @@ class QueueFlushRuntime {
378
818
  safeInvoke(...args) {
379
819
  const [callbackName, payload] = args;
380
820
  try {
381
- if ('onFlushRecovered' === callbackName) return void this.policy.onFlushRecovered?.(payload);
382
- if ('onCircuitOpen' === callbackName) return void this.policy.onCircuitOpen?.(payload);
383
- 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);
821
+ if ('onFlushRecovered' === callbackName) return void this.policy.onFlushRecovered?.(payload);
822
+ if ('onCircuitOpen' === callbackName) return void this.policy.onCircuitOpen?.(payload);
823
+ this.policy.onFlushFailure?.(payload);
824
+ } catch (error) {
825
+ this.onCallbackError?.(callbackName, error);
826
+ }
1539
827
  }
1540
- async track(payload) {
1541
- PersonalizationStateful_logger.info(`Sending "track" event "${payload.event}"`);
1542
- const event = this.builder.buildTrack(payload);
1543
- return await this.sendOrEnqueueEvent(event);
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
- async trackComponentView(payload) {
1546
- PersonalizationStateful_logger.info(`Sending "track personalization" event for ${payload.componentId}`);
1547
- const event = this.builder.buildComponentView(payload);
1548
- return await this.sendOrEnqueueEvent(event);
857
+ clearScheduledRetry() {
858
+ this.flushRuntime.clearScheduledRetry();
1549
859
  }
1550
- async sendOrEnqueueEvent(event) {
1551
- const intercepted = await this.interceptors.event.run(event);
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
- PersonalizationStateful_logger.debug(`Queueing ${validEvent.type} event`, validEvent);
1558
- this.enqueueOfflineEvent(validEvent);
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.offlineQueue.size) return void this.flushRuntime.clearScheduledRetry();
1602
- PersonalizationStateful_logger.debug('Flushing offline event queue');
1603
- const queuedEvents = Array.from(this.offlineQueue);
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((event)=>{
1609
- this.offlineQueue.delete(event);
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.offlineQueue.size > 0 ? 1 : 0,
1614
- queuedEvents: this.offlineQueue.size
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
- PersonalizationStateful_logger.warn('Personalization offline queue flush request threw an error', error);
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) PersonalizationStateful_logger.debug(`Anonymous ID found: ${anonymousId}`);
1632
- const data = await this.api.experience.upsertProfile({
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.interceptors.state.run(data);
1641
- const { changes, personalizations, profile } = intercepted;
947
+ const intercepted = await this.stateInterceptors.run(data);
948
+ const { changes, profile, selectedOptimizations } = intercepted;
1642
949
  batch(()=>{
1643
- if (!isEqual(signals_changes.value, changes)) signals_changes.value = changes;
1644
- if (!isEqual(signals_profile.value, profile)) signals_profile.value = profile;
1645
- if (!isEqual(signals_personalizations.value, personalizations)) signals_personalizations.value = personalizations;
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 personalization_PersonalizationStateful = PersonalizationStateful;
1650
- const PersonalizationStateless_logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('Personalization');
1651
- class PersonalizationStateless extends personalization_PersonalizationBase {
1652
- async identify(payload) {
1653
- PersonalizationStateless_logger.info('Sending "identify" event');
1654
- const { profile, ...builderArgs } = payload;
1655
- const event = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.IdentifyEvent, this.builder.buildIdentify(builderArgs));
1656
- return await this.upsertProfile(event, profile);
1657
- }
1658
- async page(payload) {
1659
- PersonalizationStateless_logger.info('Sending "page" event');
1660
- const { profile, ...builderArgs } = payload;
1661
- const event = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.PageViewEvent, this.builder.buildPageView(builderArgs));
1662
- return await this.upsertProfile(event, profile);
1663
- }
1664
- async screen(payload) {
1665
- PersonalizationStateless_logger.info(`Sending "screen" event for "${payload.name}"`);
1666
- const { profile, ...builderArgs } = payload;
1667
- const event = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.ScreenViewEvent, this.builder.buildScreenView(builderArgs));
1668
- return await this.upsertProfile(event, profile);
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
- async track(payload) {
1671
- PersonalizationStateless_logger.info(`Sending "track" event "${payload.event}"`);
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
- async trackComponentView(payload) {
1677
- PersonalizationStateless_logger.info('Sending "track personalization" event');
1678
- const { profile, ...builderArgs } = payload;
1679
- const event = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.ComponentViewEvent, this.builder.buildComponentView(builderArgs));
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 upsertProfile(event, profile) {
1683
- const intercepted = await this.interceptors.event.run(event);
1684
- const validEvent = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.ExperienceEvent, intercepted);
1685
- const data = await this.api.experience.upsertProfile({
1686
- profileId: profile?.id,
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
- return data;
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 personalization_PersonalizationStateless = PersonalizationStateless;
1695
- const splitScopedQueuePolicy = (config)=>{
1696
- if (void 0 === config) return {
1697
- apiConfig: void 0,
1698
- queuePolicy: void 0
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
- const { queuePolicy, ...apiConfig } = config;
1701
- const resolvedApiConfig = Object.keys(apiConfig).length > 0 ? apiConfig : void 0;
1702
- return {
1703
- apiConfig: resolvedApiConfig,
1704
- queuePolicy
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 src_CoreBase {
1109
+ class CoreStateful extends src_CoreStatefulEventEmitter {
1709
1110
  singletonOwner;
1710
1111
  destroyed = false;
1711
- _analytics;
1712
- _personalization;
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
- const { apiConfig: analyticsApiConfig, queuePolicy: analyticsRuntimeQueuePolicy } = splitScopedQueuePolicy(config.analytics);
1715
- const { apiConfig: personalizationApiConfig, queuePolicy: personalizationRuntimeQueuePolicy } = splitScopedQueuePolicy(config.personalization);
1716
- const baseConfig = {
1717
- ...config,
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
- if (defaults?.consent !== void 0) {
1727
- const { consent: defaultConsent } = defaults;
1728
- consent.value = defaultConsent;
1729
- }
1730
- this._analytics = new analytics_AnalyticsStateful({
1731
- api: this.api,
1732
- builder: this.eventBuilder,
1733
- config: {
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._personalization = new personalization_PersonalizationStateful({
1745
- api: this.api,
1746
- builder: this.eventBuilder,
1747
- config: {
1748
- allowedEventTypes,
1749
- getAnonymousId,
1750
- queuePolicy: personalizationRuntimeQueuePolicy,
1751
- onEventBlocked,
1752
- defaults: {
1753
- consent: defaults?.consent,
1754
- changes: defaults?.changes,
1755
- profile: defaults?.profile,
1756
- personalizations: defaults?.personalizations
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
- signals_personalizations.value = void 0;
1211
+ signals_selectedOptimizations.value = void 0;
1790
1212
  });
1791
1213
  }
1792
1214
  async flush() {
1793
- await this._analytics.flush();
1794
- await this._personalization.flush();
1215
+ await this.flushQueues();
1795
1216
  }
1796
1217
  consent(accept) {
1797
1218
  consent.value = accept;
@@ -1808,26 +1229,147 @@ class CoreStateful extends src_CoreBase {
1808
1229
  }
1809
1230
  }
1810
1231
  const src_CoreStateful = CoreStateful;
1232
+ const TRACK_CLICK_PROFILE_ERROR = 'CoreStateless.trackClick() requires `payload.profile.id` for Insights delivery.';
1233
+ const TRACK_HOVER_PROFILE_ERROR = 'CoreStateless.trackHover() requires `payload.profile.id` for Insights delivery.';
1234
+ const TRACK_FLAG_VIEW_PROFILE_ERROR = 'CoreStateless.trackFlagView() requires `payload.profile.id` for Insights delivery.';
1235
+ const NON_STICKY_TRACK_VIEW_PROFILE_ERROR = 'CoreStateless.trackView() requires `payload.profile.id` when `payload.sticky` is not `true`.';
1236
+ const STICKY_TRACK_VIEW_PROFILE_ERROR = 'CoreStateless.trackView() could not derive a profile from the sticky Experience response. Pass `payload.profile.id` explicitly if you need a fallback.';
1237
+ const CoreStateless_hasDefinedValues = (record)=>Object.values(record).some((value)=>void 0 !== value);
1238
+ const requireInsightsProfile = (profile, errorMessage)=>{
1239
+ if (void 0 !== profile) return profile;
1240
+ throw new Error(errorMessage);
1241
+ };
1242
+ const createStatelessExperienceApiConfig = (api)=>{
1243
+ if (void 0 === api) return;
1244
+ const experienceConfig = {
1245
+ baseUrl: api.experienceBaseUrl,
1246
+ enabledFeatures: api.enabledFeatures
1247
+ };
1248
+ return CoreStateless_hasDefinedValues(experienceConfig) ? experienceConfig : void 0;
1249
+ };
1250
+ const createStatelessInsightsApiConfig = (api)=>{
1251
+ if (api?.insightsBaseUrl === void 0) return;
1252
+ return {
1253
+ baseUrl: api.insightsBaseUrl
1254
+ };
1255
+ };
1811
1256
  class CoreStateless extends src_CoreBase {
1812
- _analytics;
1813
- _personalization;
1814
1257
  constructor(config){
1815
- super(config);
1816
- this._analytics = new analytics_AnalyticsStateless({
1817
- api: this.api,
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
1258
+ super(config, {
1259
+ experience: createStatelessExperienceApiConfig(config.api),
1260
+ insights: createStatelessInsightsApiConfig(config.api)
1825
1261
  });
1826
1262
  }
1263
+ async identify(payload, requestOptions) {
1264
+ const { profile, ...builderArgs } = payload;
1265
+ return await this.sendExperienceEvent(this.eventBuilder.buildIdentify(builderArgs), profile, requestOptions);
1266
+ }
1267
+ async page(payload = {}, requestOptions) {
1268
+ const { profile, ...builderArgs } = payload;
1269
+ return await this.sendExperienceEvent(this.eventBuilder.buildPageView(builderArgs), profile, requestOptions);
1270
+ }
1271
+ async screen(payload, requestOptions) {
1272
+ const { profile, ...builderArgs } = payload;
1273
+ return await this.sendExperienceEvent(this.eventBuilder.buildScreenView(builderArgs), profile, requestOptions);
1274
+ }
1275
+ async track(payload, requestOptions) {
1276
+ const { profile, ...builderArgs } = payload;
1277
+ return await this.sendExperienceEvent(this.eventBuilder.buildTrack(builderArgs), profile, requestOptions);
1278
+ }
1279
+ async trackView(payload, requestOptions) {
1280
+ const { profile, ...builderArgs } = payload;
1281
+ let result;
1282
+ let insightsProfile = profile;
1283
+ if (payload.sticky) {
1284
+ result = await this.sendExperienceEvent(this.eventBuilder.buildView(builderArgs), profile, requestOptions);
1285
+ const { profile: responseProfile } = result;
1286
+ insightsProfile = responseProfile;
1287
+ }
1288
+ await this.sendInsightsEvent(this.eventBuilder.buildView(builderArgs), requireInsightsProfile(insightsProfile, payload.sticky ? STICKY_TRACK_VIEW_PROFILE_ERROR : NON_STICKY_TRACK_VIEW_PROFILE_ERROR));
1289
+ return result;
1290
+ }
1291
+ async trackClick(payload, _requestOptions) {
1292
+ const { profile, ...builderArgs } = payload;
1293
+ await this.sendInsightsEvent(this.eventBuilder.buildClick(builderArgs), requireInsightsProfile(profile, TRACK_CLICK_PROFILE_ERROR));
1294
+ }
1295
+ async trackHover(payload, _requestOptions) {
1296
+ const { profile, ...builderArgs } = payload;
1297
+ await this.sendInsightsEvent(this.eventBuilder.buildHover(builderArgs), requireInsightsProfile(profile, TRACK_HOVER_PROFILE_ERROR));
1298
+ }
1299
+ async trackFlagView(payload, _requestOptions) {
1300
+ const { profile, ...builderArgs } = payload;
1301
+ await this.sendInsightsEvent(this.eventBuilder.buildFlagView(builderArgs), requireInsightsProfile(profile, TRACK_FLAG_VIEW_PROFILE_ERROR));
1302
+ }
1303
+ async sendExperienceEvent(event, profile, requestOptions) {
1304
+ const intercepted = await this.interceptors.event.run(event);
1305
+ const validEvent = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.ExperienceEvent, intercepted);
1306
+ return await this.api.experience.upsertProfile({
1307
+ profileId: profile?.id,
1308
+ events: [
1309
+ validEvent
1310
+ ]
1311
+ }, requestOptions);
1312
+ }
1313
+ async sendInsightsEvent(event, profile) {
1314
+ const intercepted = await this.interceptors.event.run(event);
1315
+ const validEvent = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.InsightsEvent, intercepted);
1316
+ const batchEvent = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.BatchInsightsEventArray, [
1317
+ {
1318
+ profile: (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.PartialProfile, profile),
1319
+ events: [
1320
+ validEvent
1321
+ ]
1322
+ }
1323
+ ]);
1324
+ await this.api.insights.sendBatchEvents(batchEvent);
1325
+ }
1827
1326
  }
1828
1327
  const src_CoreStateless = CoreStateless;
1829
- 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, PERSONALIZATIONS_CACHE_KEY, PROFILE_CACHE_KEY } from "./260.mjs";
1328
+ const isFunction = (v)=>'function' == typeof v;
1329
+ const nameToString = (name)=>'string' == typeof name ? name : 'symbol' == typeof name ? name.description ?? String(name) : String(name);
1330
+ const isOnBlockedKey = (v)=>'string' == typeof v || 'symbol' == typeof v;
1331
+ const isAsyncFunction = (fn)=>'[object AsyncFunction]' === Object.prototype.toString.call(fn);
1332
+ function guardedBy(predicateName, opts) {
1333
+ return function(_value, context) {
1334
+ const decoratedName = nameToString(context.name);
1335
+ context.addInitializer(function() {
1336
+ const originalUnknown = Reflect.get(this, context.name);
1337
+ if (!isFunction(originalUnknown)) return;
1338
+ const original = originalUnknown;
1339
+ const originalIsAsync = isAsyncFunction(original);
1340
+ const resolvePredicate = (self)=>{
1341
+ const { [predicateName]: cand } = self;
1342
+ if (!isFunction(cand)) throw new TypeError(`@guardedBy expects predicate "${String(predicateName)}" to be a synchronous function.`);
1343
+ return cand;
1344
+ };
1345
+ const computeAllowed = (self, args)=>{
1346
+ const pred = resolvePredicate(self);
1347
+ const ok = Boolean(pred.call(self, decoratedName, args));
1348
+ return opts?.invert === true ? !ok : ok;
1349
+ };
1350
+ const runOnBlocked = (self, args)=>{
1351
+ const { onBlocked } = opts ?? {};
1352
+ if (void 0 === onBlocked) return;
1353
+ if (isFunction(onBlocked)) return void onBlocked.call(self, decoratedName, args);
1354
+ if (isOnBlockedKey(onBlocked)) {
1355
+ const { [onBlocked]: handlerCandidate } = self;
1356
+ if (isFunction(handlerCandidate)) handlerCandidate.call(self, decoratedName, args);
1357
+ }
1358
+ };
1359
+ const blockedReturn = ()=>originalIsAsync ? Promise.resolve(void 0) : void 0;
1360
+ const wrapped = function(...args) {
1361
+ if (!computeAllowed(this, args)) {
1362
+ runOnBlocked(this, args);
1363
+ return blockedReturn();
1364
+ }
1365
+ return original.call(this, ...args);
1366
+ };
1367
+ Reflect.set(this, context.name, wrapped);
1368
+ });
1369
+ };
1370
+ }
1371
+ 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
1372
  export { PREVIEW_PANEL_SIGNALS_SYMBOL, PREVIEW_PANEL_SIGNAL_FNS_SYMBOL } from "./632.mjs";
1831
- export { InterceptorManager, analytics_AnalyticsStateful as AnalyticsStateful, analytics_AnalyticsStateless as AnalyticsStateless, batch, effect, guardedBy, personalization_PersonalizationBase as PersonalizationBase, personalization_PersonalizationStateful as PersonalizationStateful, personalization_PersonalizationStateless as PersonalizationStateless, resolvers_FlagsResolver as FlagsResolver, resolvers_MergeTagValueResolver as MergeTagValueResolver, resolvers_PersonalizedEntryResolver as PersonalizedEntryResolver, signalFns, signals, src_CoreStateful as CoreStateful, src_CoreStateless as CoreStateless };
1373
+ export { ClickBuilderArgs, 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
1374
 
1833
1375
  //# sourceMappingURL=index.mjs.map