@contentful/optimization-core 0.1.0-alpha8 → 0.1.0-alpha9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/README.md +221 -31
  2. package/dist/260.mjs +14 -0
  3. package/dist/260.mjs.map +1 -0
  4. package/dist/499.mjs +4 -0
  5. package/dist/632.mjs +5 -0
  6. package/dist/632.mjs.map +1 -0
  7. package/dist/808.mjs +2 -0
  8. package/dist/942.mjs +2 -0
  9. package/dist/api-client.cjs +60 -0
  10. package/dist/api-client.cjs.map +1 -0
  11. package/dist/api-client.d.cts +4 -0
  12. package/dist/api-client.d.mts +4 -0
  13. package/dist/api-client.d.ts +4 -0
  14. package/dist/api-client.mjs +2 -0
  15. package/dist/api-schemas.cjs +60 -0
  16. package/dist/api-schemas.cjs.map +1 -0
  17. package/dist/api-schemas.d.cts +4 -0
  18. package/dist/api-schemas.d.mts +4 -0
  19. package/dist/api-schemas.d.ts +4 -0
  20. package/dist/api-schemas.mjs +2 -0
  21. package/dist/constants.cjs +78 -0
  22. package/dist/constants.cjs.map +1 -0
  23. package/dist/{global-constants.d.ts → constants.d.cts} +88 -67
  24. package/dist/{global-constants.js → constants.d.mts} +88 -69
  25. package/dist/constants.d.ts +88 -0
  26. package/dist/constants.mjs +1 -0
  27. package/dist/index.cjs +1833 -1706
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +774 -341
  30. package/dist/index.d.mts +774 -341
  31. package/dist/index.d.ts +2432 -15
  32. package/dist/index.mjs +617 -341
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/logger.cjs +67 -0
  35. package/dist/logger.cjs.map +1 -0
  36. package/dist/logger.d.cts +8 -0
  37. package/dist/logger.d.mts +8 -0
  38. package/dist/logger.d.ts +8 -0
  39. package/dist/logger.mjs +2 -0
  40. package/dist/symbols.cjs +42 -0
  41. package/dist/symbols.cjs.map +1 -0
  42. package/dist/symbols.d.cts +10 -0
  43. package/dist/symbols.d.mts +10 -0
  44. package/dist/symbols.d.ts +10 -0
  45. package/dist/symbols.mjs +1 -0
  46. package/package.json +56 -8
  47. package/dist/Consent.d.ts +0 -44
  48. package/dist/Consent.d.ts.map +0 -1
  49. package/dist/Consent.js +0 -2
  50. package/dist/Consent.js.map +0 -1
  51. package/dist/CoreBase.d.ts +0 -161
  52. package/dist/CoreBase.d.ts.map +0 -1
  53. package/dist/CoreBase.js +0 -151
  54. package/dist/CoreBase.js.map +0 -1
  55. package/dist/CoreStateful.d.ts +0 -144
  56. package/dist/CoreStateful.d.ts.map +0 -1
  57. package/dist/CoreStateful.js +0 -141
  58. package/dist/CoreStateful.js.map +0 -1
  59. package/dist/CoreStateless.d.ts +0 -53
  60. package/dist/CoreStateless.d.ts.map +0 -1
  61. package/dist/CoreStateless.js +0 -43
  62. package/dist/CoreStateless.js.map +0 -1
  63. package/dist/ProductBase.d.ts +0 -83
  64. package/dist/ProductBase.d.ts.map +0 -1
  65. package/dist/ProductBase.js +0 -50
  66. package/dist/ProductBase.js.map +0 -1
  67. package/dist/analytics/AnalyticsBase.d.ts +0 -35
  68. package/dist/analytics/AnalyticsBase.d.ts.map +0 -1
  69. package/dist/analytics/AnalyticsBase.js +0 -13
  70. package/dist/analytics/AnalyticsBase.js.map +0 -1
  71. package/dist/analytics/AnalyticsStateful.d.ts +0 -138
  72. package/dist/analytics/AnalyticsStateful.d.ts.map +0 -1
  73. package/dist/analytics/AnalyticsStateful.js +0 -179
  74. package/dist/analytics/AnalyticsStateful.js.map +0 -1
  75. package/dist/analytics/AnalyticsStateless.d.ts +0 -48
  76. package/dist/analytics/AnalyticsStateless.d.ts.map +0 -1
  77. package/dist/analytics/AnalyticsStateless.js +0 -61
  78. package/dist/analytics/AnalyticsStateless.js.map +0 -1
  79. package/dist/analytics/index.d.ts +0 -5
  80. package/dist/analytics/index.d.ts.map +0 -1
  81. package/dist/analytics/index.js +0 -5
  82. package/dist/analytics/index.js.map +0 -1
  83. package/dist/global-constants.d.ts.map +0 -1
  84. package/dist/global-constants.js.map +0 -1
  85. package/dist/index.d.ts.map +0 -1
  86. package/dist/index.js +0 -15
  87. package/dist/index.js.map +0 -1
  88. package/dist/lib/decorators/guardedBy.d.ts +0 -113
  89. package/dist/lib/decorators/guardedBy.d.ts.map +0 -1
  90. package/dist/lib/decorators/guardedBy.js +0 -143
  91. package/dist/lib/decorators/guardedBy.js.map +0 -1
  92. package/dist/lib/decorators/index.d.ts +0 -2
  93. package/dist/lib/decorators/index.d.ts.map +0 -1
  94. package/dist/lib/decorators/index.js +0 -2
  95. package/dist/lib/decorators/index.js.map +0 -1
  96. package/dist/lib/interceptor/InterceptorManager.d.ts +0 -127
  97. package/dist/lib/interceptor/InterceptorManager.d.ts.map +0 -1
  98. package/dist/lib/interceptor/InterceptorManager.js +0 -125
  99. package/dist/lib/interceptor/InterceptorManager.js.map +0 -1
  100. package/dist/lib/interceptor/index.d.ts +0 -2
  101. package/dist/lib/interceptor/index.d.ts.map +0 -1
  102. package/dist/lib/interceptor/index.js +0 -2
  103. package/dist/lib/interceptor/index.js.map +0 -1
  104. package/dist/lib/value-presence/ValuePresence.d.ts +0 -123
  105. package/dist/lib/value-presence/ValuePresence.d.ts.map +0 -1
  106. package/dist/lib/value-presence/ValuePresence.js +0 -141
  107. package/dist/lib/value-presence/ValuePresence.js.map +0 -1
  108. package/dist/lib/value-presence/index.d.ts +0 -2
  109. package/dist/lib/value-presence/index.d.ts.map +0 -1
  110. package/dist/lib/value-presence/index.js +0 -2
  111. package/dist/lib/value-presence/index.js.map +0 -1
  112. package/dist/personalization/PersonalizationBase.d.ts +0 -184
  113. package/dist/personalization/PersonalizationBase.d.ts.map +0 -1
  114. package/dist/personalization/PersonalizationBase.js +0 -76
  115. package/dist/personalization/PersonalizationBase.js.map +0 -1
  116. package/dist/personalization/PersonalizationStateful.d.ts +0 -226
  117. package/dist/personalization/PersonalizationStateful.d.ts.map +0 -1
  118. package/dist/personalization/PersonalizationStateful.js +0 -297
  119. package/dist/personalization/PersonalizationStateful.js.map +0 -1
  120. package/dist/personalization/PersonalizationStateless.d.ts +0 -74
  121. package/dist/personalization/PersonalizationStateless.d.ts.map +0 -1
  122. package/dist/personalization/PersonalizationStateless.js +0 -98
  123. package/dist/personalization/PersonalizationStateless.js.map +0 -1
  124. package/dist/personalization/index.d.ts +0 -6
  125. package/dist/personalization/index.d.ts.map +0 -1
  126. package/dist/personalization/index.js +0 -6
  127. package/dist/personalization/index.js.map +0 -1
  128. package/dist/personalization/resolvers/FlagsResolver.d.ts +0 -35
  129. package/dist/personalization/resolvers/FlagsResolver.d.ts.map +0 -1
  130. package/dist/personalization/resolvers/FlagsResolver.js +0 -47
  131. package/dist/personalization/resolvers/FlagsResolver.js.map +0 -1
  132. package/dist/personalization/resolvers/MergeTagValueResolver.d.ts +0 -74
  133. package/dist/personalization/resolvers/MergeTagValueResolver.d.ts.map +0 -1
  134. package/dist/personalization/resolvers/MergeTagValueResolver.js +0 -109
  135. package/dist/personalization/resolvers/MergeTagValueResolver.js.map +0 -1
  136. package/dist/personalization/resolvers/PersonalizedEntryResolver.d.ts +0 -142
  137. package/dist/personalization/resolvers/PersonalizedEntryResolver.d.ts.map +0 -1
  138. package/dist/personalization/resolvers/PersonalizedEntryResolver.js +0 -196
  139. package/dist/personalization/resolvers/PersonalizedEntryResolver.js.map +0 -1
  140. package/dist/personalization/resolvers/index.d.ts +0 -7
  141. package/dist/personalization/resolvers/index.d.ts.map +0 -1
  142. package/dist/personalization/resolvers/index.js +0 -7
  143. package/dist/personalization/resolvers/index.js.map +0 -1
  144. package/dist/signals.d.ts +0 -42
  145. package/dist/signals.d.ts.map +0 -1
  146. package/dist/signals.js +0 -36
  147. package/dist/signals.js.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,9 +1,10 @@
1
- import * as __rspack_external__contentful_optimization_api_client_cba5a7ee from "@contentful/optimization-api-client";
2
1
  import { batch, computed, effect, signal, untracked } from "@preact/signals-core";
3
- import { get as compat_get } from "es-toolkit/compat";
4
- import { diary, enable } from "diary";
5
- import { compare } from "diary/utils";
6
- import { isEqual } from "es-toolkit";
2
+ import { isEqual } from "es-toolkit/predicate";
3
+ import { __rspack_external__contentful_optimization_api_client_api_schemas_4192893e } from "./808.mjs";
4
+ import { __rspack_external__contentful_optimization_api_client_logger_f0d05f82 } from "./499.mjs";
5
+ import { __rspack_external__contentful_optimization_api_client_cba5a7ee } from "./942.mjs";
6
+ import { OPTIMIZATION_CORE_SDK_NAME, OPTIMIZATION_CORE_SDK_VERSION } from "./260.mjs";
7
+ import { PREVIEW_PANEL_SIGNALS_SYMBOL, PREVIEW_PANEL_SIGNAL_FNS_SYMBOL } from "./632.mjs";
7
8
  const FlagsResolver = {
8
9
  resolve (changes) {
9
10
  if (!changes) return {};
@@ -15,126 +16,20 @@ const FlagsResolver = {
15
16
  }
16
17
  };
17
18
  const resolvers_FlagsResolver = FlagsResolver;
18
- class Logger {
19
- name = '@contentful/optimization';
20
- PREFIX_PARTS = [
21
- 'Ctfl',
22
- 'O10n'
23
- ];
24
- DELIMITER = ':';
25
- diary;
26
- sinks = [];
27
- constructor(){
28
- this.diary = diary(this.name, this.onLogEvent.bind(this));
29
- enable(this.name);
30
- }
31
- assembleLocationPrefix(logLocation) {
32
- return `[${[
33
- ...this.PREFIX_PARTS,
34
- logLocation
35
- ].join(this.DELIMITER)}]`;
36
- }
37
- addSink(sink) {
38
- this.sinks = [
39
- ...this.sinks.filter((existingSink)=>existingSink.name !== sink.name),
40
- sink
41
- ];
42
- }
43
- removeSink(name) {
44
- this.sinks = this.sinks.filter((sink)=>sink.name !== name);
45
- }
46
- removeSinks() {
47
- this.sinks = [];
48
- }
49
- debug(logLocation, message, ...args) {
50
- this.diary.debug(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args);
51
- }
52
- info(logLocation, message, ...args) {
53
- this.diary.info(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args);
54
- }
55
- log(logLocation, message, ...args) {
56
- this.diary.log(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args);
57
- }
58
- warn(logLocation, message, ...args) {
59
- this.diary.warn(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args);
60
- }
61
- error(logLocation, message, ...args) {
62
- this.diary.error(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args);
63
- }
64
- fatal(logLocation, message, ...args) {
65
- this.diary.fatal(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args);
66
- }
67
- onLogEvent(event) {
68
- this.sinks.forEach((sink)=>{
69
- sink.ingest(event);
70
- });
71
- }
72
- }
73
- const logger = new Logger();
74
- function createScopedLogger(location) {
75
- return {
76
- debug: (message, ...args)=>{
77
- logger.debug(location, message, ...args);
78
- },
79
- info: (message, ...args)=>{
80
- logger.info(location, message, ...args);
81
- },
82
- log: (message, ...args)=>{
83
- logger.log(location, message, ...args);
84
- },
85
- warn: (message, ...args)=>{
86
- logger.warn(location, message, ...args);
87
- },
88
- error: (message, ...args)=>{
89
- logger.error(location, message, ...args);
90
- },
91
- fatal: (message, ...args)=>{
92
- logger.fatal(location, message, ...args);
93
- }
94
- };
95
- }
96
- class LogSink {
97
- }
98
- const src_LogSink = LogSink;
99
- const consoleMap = {
100
- debug: (...args)=>{
101
- console.debug(...args);
102
- },
103
- info: (...args)=>{
104
- console.info(...args);
105
- },
106
- log: (...args)=>{
107
- console.log(...args);
108
- },
109
- warn: (...args)=>{
110
- console.warn(...args);
111
- },
112
- error: (...args)=>{
113
- console.error(...args);
114
- },
115
- fatal: (...args)=>{
116
- console.error(...args);
117
- }
118
- };
119
- const COMPARISON_EQUALITY = 0;
120
- class ConsoleLogSink extends src_LogSink {
121
- name = 'ConsoleLogSink';
122
- verbosity;
123
- constructor(verbosity){
124
- super();
125
- this.verbosity = verbosity ?? 'error';
126
- }
127
- ingest(event) {
128
- if (compare(this.verbosity, event.level) > COMPARISON_EQUALITY) return;
129
- consoleMap[event.level](...event.messages);
130
- }
131
- }
132
- const MergeTagValueResolver_logger = createScopedLogger('Personalization');
19
+ const logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('Personalization');
133
20
  const RESOLUTION_WARNING_BASE = 'Could not resolve Merge Tag value:';
21
+ const getAtPath = (value, path)=>{
22
+ if (!value || 'object' != typeof value) return;
23
+ if (!path) return value;
24
+ let current = value;
25
+ const segments = path.split('.').filter(Boolean);
26
+ for (const segment of segments){
27
+ if (!current || 'object' != typeof current && 'function' != typeof current) return;
28
+ current = Reflect.get(current, segment);
29
+ }
30
+ return current;
31
+ };
134
32
  const MergeTagValueResolver = {
135
- isMergeTagEntry (embeddedEntryNodeTarget) {
136
- return __rspack_external__contentful_optimization_api_client_cba5a7ee.MergeTagEntry.safeParse(embeddedEntryNodeTarget).success;
137
- },
138
33
  normalizeSelectors (id) {
139
34
  return id.split('_').map((_path, index, paths)=>{
140
35
  const dotPath = paths.slice(0, index).join('.');
@@ -147,46 +42,46 @@ const MergeTagValueResolver = {
147
42
  },
148
43
  getValueFromProfile (id, profile) {
149
44
  const selectors = MergeTagValueResolver.normalizeSelectors(id);
150
- const matchingSelector = selectors.find((selector)=>compat_get(profile, selector));
45
+ const matchingSelector = selectors.find((selector)=>getAtPath(profile, selector));
151
46
  if (!matchingSelector) return;
152
- const value = compat_get(profile, matchingSelector);
47
+ const value = getAtPath(profile, matchingSelector);
153
48
  if (!value || 'string' != typeof value && 'number' != typeof value && 'boolean' != typeof value) return;
154
49
  return `${value}`;
155
50
  },
156
51
  resolve (mergeTagEntry, profile) {
157
- if (!MergeTagValueResolver.isMergeTagEntry(mergeTagEntry)) return void MergeTagValueResolver_logger.warn(`${RESOLUTION_WARNING_BASE} supplied entry is not a Merge Tag entry`);
52
+ if (!(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isMergeTagEntry)(mergeTagEntry)) return void logger.warn(`${RESOLUTION_WARNING_BASE} supplied entry is not a Merge Tag entry`);
158
53
  const { fields: { nt_fallback: fallback } } = mergeTagEntry;
159
- if (!__rspack_external__contentful_optimization_api_client_cba5a7ee.Profile.safeParse(profile).success) {
160
- MergeTagValueResolver_logger.warn(`${RESOLUTION_WARNING_BASE} no valid profile`);
54
+ if (!__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.Profile.safeParse(profile).success) {
55
+ logger.warn(`${RESOLUTION_WARNING_BASE} no valid profile`);
161
56
  return fallback;
162
57
  }
163
58
  return MergeTagValueResolver.getValueFromProfile(mergeTagEntry.fields.nt_mergetag_id, profile) ?? fallback;
164
59
  }
165
60
  };
166
61
  const resolvers_MergeTagValueResolver = MergeTagValueResolver;
167
- const PersonalizedEntryResolver_logger = createScopedLogger('Personalization');
62
+ const PersonalizedEntryResolver_logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('Personalization');
168
63
  const PersonalizedEntryResolver_RESOLUTION_WARNING_BASE = 'Could not resolve personalized entry variant:';
169
64
  const PersonalizedEntryResolver = {
170
65
  getPersonalizationEntry ({ personalizedEntry, selectedPersonalizations }, skipValidation = false) {
171
- if (!skipValidation && (!selectedPersonalizations.length || !(0, __rspack_external__contentful_optimization_api_client_cba5a7ee.isPersonalizedEntry)(personalizedEntry))) return;
172
- const personalizationEntry = personalizedEntry.fields.nt_experiences.filter((maybePersonalization)=>(0, __rspack_external__contentful_optimization_api_client_cba5a7ee.isPersonalizationEntry)(maybePersonalization)).find((personalizationEntry)=>selectedPersonalizations.some(({ experienceId })=>experienceId === personalizationEntry.fields.nt_experience_id));
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));
173
68
  return personalizationEntry;
174
69
  },
175
70
  getSelectedPersonalization ({ personalizationEntry, selectedPersonalizations }, skipValidation = false) {
176
- if (!skipValidation && (!selectedPersonalizations.length || !(0, __rspack_external__contentful_optimization_api_client_cba5a7ee.isPersonalizationEntry)(personalizationEntry))) return;
71
+ if (!skipValidation && (!selectedPersonalizations.length || !(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isPersonalizationEntry)(personalizationEntry))) return;
177
72
  const selectedPersonalization = selectedPersonalizations.find(({ experienceId })=>experienceId === personalizationEntry.fields.nt_experience_id);
178
73
  return selectedPersonalization;
179
74
  },
180
75
  getSelectedVariant ({ personalizedEntry, personalizationEntry, selectedVariantIndex }, skipValidation = false) {
181
- if (!skipValidation && (!(0, __rspack_external__contentful_optimization_api_client_cba5a7ee.isPersonalizedEntry)(personalizedEntry) || !(0, __rspack_external__contentful_optimization_api_client_cba5a7ee.isPersonalizationEntry)(personalizationEntry))) return;
182
- const relevantVariants = personalizationEntry.fields.nt_config?.components?.filter((component)=>(0, __rspack_external__contentful_optimization_api_client_cba5a7ee.isEntryReplacementComponent)(component) && !component.baseline.hidden).find((component)=>component.baseline.id === personalizedEntry.sys.id)?.variants;
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;
183
78
  if (!relevantVariants?.length) return;
184
79
  return relevantVariants.at(selectedVariantIndex - 1);
185
80
  },
186
81
  getSelectedVariantEntry ({ personalizationEntry, selectedVariant }, skipValidation = false) {
187
- if (!skipValidation && (!(0, __rspack_external__contentful_optimization_api_client_cba5a7ee.isPersonalizationEntry)(personalizationEntry) || !(0, __rspack_external__contentful_optimization_api_client_cba5a7ee.isEntryReplacementVariant)(selectedVariant))) return;
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;
188
83
  const selectedVariantEntry = personalizationEntry.fields.nt_variants?.find((variant)=>variant.sys.id === selectedVariant.id);
189
- return (0, __rspack_external__contentful_optimization_api_client_cba5a7ee.isEntry)(selectedVariantEntry) ? selectedVariantEntry : void 0;
84
+ return (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isEntry)(selectedVariantEntry) ? selectedVariantEntry : void 0;
190
85
  },
191
86
  resolve (entry, selectedPersonalizations) {
192
87
  PersonalizedEntryResolver_logger.debug(`Resolving personalized entry for baseline entry ${entry.sys.id}`);
@@ -196,7 +91,7 @@ const PersonalizedEntryResolver = {
196
91
  entry
197
92
  };
198
93
  }
199
- if (!(0, __rspack_external__contentful_optimization_api_client_cba5a7ee.isPersonalizedEntry)(entry)) {
94
+ if (!(0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.isPersonalizedEntry)(entry)) {
200
95
  PersonalizedEntryResolver_logger.warn(`${PersonalizedEntryResolver_RESOLUTION_WARNING_BASE} entry ${entry.sys.id} is not personalized`);
201
96
  return {
202
97
  entry
@@ -253,10 +148,13 @@ const PersonalizedEntryResolver = {
253
148
  };
254
149
  const resolvers_PersonalizedEntryResolver = PersonalizedEntryResolver;
255
150
  const signals_changes = signal();
151
+ const blockedEvent = signal();
256
152
  const consent = signal();
257
153
  const signals_event = signal();
258
154
  const flags = computed(()=>resolvers_FlagsResolver.resolve(signals_changes.value ?? []));
259
155
  const online = signal(true);
156
+ const previewPanelAttached = signal(false);
157
+ const previewPanelOpen = signal(false);
260
158
  const signals_personalizations = signal();
261
159
  const signals_profile = signal();
262
160
  function toObservable(s) {
@@ -272,11 +170,14 @@ function toObservable(s) {
272
170
  };
273
171
  }
274
172
  const signals = {
173
+ blockedEvent: blockedEvent,
275
174
  changes: signals_changes,
276
175
  consent: consent,
277
176
  event: signals_event,
278
177
  flags: flags,
279
178
  online: online,
179
+ previewPanelAttached: previewPanelAttached,
180
+ previewPanelOpen: previewPanelOpen,
280
181
  personalizations: signals_personalizations,
281
182
  profile: signals_profile
282
183
  };
@@ -329,49 +230,195 @@ function guardedBy(predicateName, opts) {
329
230
  });
330
231
  };
331
232
  }
332
- class ValuePresence {
333
- #map;
334
- constructor(defaultMap){
335
- const map = new Map();
336
- if (defaultMap) Object.entries(defaultMap).map(([scope, values])=>map.set(scope.length ? scope : void 0, new Set(values)));
337
- this.#map = map;
338
- }
339
- isPresent(scope, value) {
340
- return this.#map.get(scope)?.has(value) ?? false;
341
- }
342
- addValue(scope, value) {
343
- const values = this.#map.get(scope);
344
- if (values) values.add(value);
345
- else this.#map.set(scope, new Set([
346
- value
347
- ]));
348
- }
349
- removeValue(scope, value) {
350
- this.#map.get(scope)?.delete(value);
351
- }
352
- reset(scope) {
353
- if (void 0 !== scope) this.#map.get(scope)?.clear();
354
- else this.#map.clear();
233
+ const toPositiveInt = (value, fallback)=>{
234
+ if (!Number.isFinite(value) || void 0 === value || value < 1) return fallback;
235
+ return Math.floor(value);
236
+ };
237
+ const toRatio = (value, fallback)=>{
238
+ if (!Number.isFinite(value) || void 0 === value) return fallback;
239
+ return Math.min(1, Math.max(0, value));
240
+ };
241
+ const DEFAULT_QUEUE_FLUSH_POLICY = {
242
+ baseBackoffMs: 500,
243
+ maxBackoffMs: 30000,
244
+ jitterRatio: 0.2,
245
+ maxConsecutiveFailures: 8,
246
+ circuitOpenMs: 120000
247
+ };
248
+ 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));
251
+ return {
252
+ baseBackoffMs,
253
+ 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
260
+ };
261
+ };
262
+ const computeQueueFlushRetryDelayMs = (options)=>{
263
+ const { consecutiveFailures, policy: { baseBackoffMs, jitterRatio, maxBackoffMs } } = options;
264
+ const exponential = baseBackoffMs * 2 ** Math.max(0, consecutiveFailures - 1);
265
+ const capped = Math.min(maxBackoffMs, exponential);
266
+ const jitter = capped * jitterRatio * Math.random();
267
+ return Math.round(capped + jitter);
268
+ };
269
+ const createQueueFlushFailureWindow = (options)=>{
270
+ const { consecutiveFailures, failureTimestamp, retryDelayMs, policy: { maxConsecutiveFailures, circuitOpenMs } } = options;
271
+ if (consecutiveFailures < maxConsecutiveFailures) return {
272
+ openedCircuit: false,
273
+ retryDelayMs,
274
+ nextFlushAllowedAt: failureTimestamp + retryDelayMs,
275
+ circuitOpenUntil: 0
276
+ };
277
+ const circuitOpenUntil = failureTimestamp + circuitOpenMs;
278
+ return {
279
+ openedCircuit: true,
280
+ retryDelayMs: circuitOpenMs,
281
+ nextFlushAllowedAt: circuitOpenUntil,
282
+ circuitOpenUntil
283
+ };
284
+ };
285
+ class QueueFlushRuntime {
286
+ circuitOpenUntil = 0;
287
+ flushFailureCount = 0;
288
+ flushInFlight = false;
289
+ nextFlushAllowedAt = 0;
290
+ onCallbackError;
291
+ onRetry;
292
+ policy;
293
+ retryTimer;
294
+ constructor(options){
295
+ const { onCallbackError, onRetry, policy } = options;
296
+ this.policy = policy;
297
+ this.onRetry = onRetry;
298
+ this.onCallbackError = onCallbackError;
299
+ }
300
+ reset() {
301
+ this.clearScheduledRetry();
302
+ this.circuitOpenUntil = 0;
303
+ this.flushFailureCount = 0;
304
+ this.flushInFlight = false;
305
+ this.nextFlushAllowedAt = 0;
306
+ }
307
+ clearScheduledRetry() {
308
+ if (void 0 === this.retryTimer) return;
309
+ clearTimeout(this.retryTimer);
310
+ this.retryTimer = void 0;
311
+ }
312
+ shouldSkip(options) {
313
+ const { force, isOnline } = options;
314
+ if (this.flushInFlight) return true;
315
+ if (force) return false;
316
+ if (!isOnline) return true;
317
+ const now = Date.now();
318
+ if (this.nextFlushAllowedAt > now) return true;
319
+ if (this.circuitOpenUntil > now) return true;
320
+ return false;
321
+ }
322
+ markFlushStarted() {
323
+ this.flushInFlight = true;
324
+ }
325
+ markFlushFinished() {
326
+ this.flushInFlight = false;
327
+ }
328
+ handleFlushSuccess() {
329
+ const { flushFailureCount: previousConsecutiveFailures } = this;
330
+ this.clearScheduledRetry();
331
+ this.circuitOpenUntil = 0;
332
+ this.flushFailureCount = 0;
333
+ this.nextFlushAllowedAt = 0;
334
+ if (previousConsecutiveFailures <= 0) return;
335
+ this.safeInvoke('onFlushRecovered', {
336
+ consecutiveFailures: previousConsecutiveFailures
337
+ });
338
+ }
339
+ handleFlushFailure(options) {
340
+ const { queuedBatches, queuedEvents } = options;
341
+ this.flushFailureCount += 1;
342
+ const retryDelayMs = computeQueueFlushRetryDelayMs({
343
+ consecutiveFailures: this.flushFailureCount,
344
+ policy: this.policy
345
+ });
346
+ const failureTimestamp = Date.now();
347
+ const failureContext = {
348
+ consecutiveFailures: this.flushFailureCount,
349
+ queuedBatches,
350
+ queuedEvents,
351
+ retryDelayMs
352
+ };
353
+ this.safeInvoke('onFlushFailure', failureContext);
354
+ const failureWindow = createQueueFlushFailureWindow({
355
+ consecutiveFailures: this.flushFailureCount,
356
+ failureTimestamp,
357
+ retryDelayMs,
358
+ policy: this.policy
359
+ });
360
+ const { circuitOpenUntil, nextFlushAllowedAt, openedCircuit, retryDelayMs: scheduledRetryDelayMs } = failureWindow;
361
+ this.nextFlushAllowedAt = nextFlushAllowedAt;
362
+ if (openedCircuit) {
363
+ this.circuitOpenUntil = circuitOpenUntil;
364
+ this.safeInvoke('onCircuitOpen', {
365
+ ...failureContext,
366
+ retryDelayMs: scheduledRetryDelayMs
367
+ });
368
+ }
369
+ this.scheduleRetry(scheduledRetryDelayMs);
370
+ }
371
+ scheduleRetry(delayMs) {
372
+ this.clearScheduledRetry();
373
+ this.retryTimer = setTimeout(()=>{
374
+ this.retryTimer = void 0;
375
+ this.onRetry();
376
+ }, delayMs);
377
+ }
378
+ safeInvoke(...args) {
379
+ const [callbackName, payload] = args;
380
+ 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
+ }
355
387
  }
356
388
  }
357
- const value_presence_ValuePresence = ValuePresence;
389
+ const ProductBase_logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('ProductBase');
358
390
  const defaultAllowedEvents = [
391
+ 'identify',
359
392
  'page',
360
- 'identify'
393
+ 'screen'
361
394
  ];
362
395
  class ProductBase {
363
396
  allowedEventTypes;
364
397
  builder;
365
398
  api;
366
- duplicationDetector;
367
399
  interceptors;
400
+ onEventBlocked;
368
401
  constructor(options){
369
402
  const { api, builder, config, interceptors } = options;
370
403
  this.allowedEventTypes = config?.allowedEventTypes ?? defaultAllowedEvents;
371
404
  this.api = api;
372
405
  this.builder = builder;
373
- this.duplicationDetector = new value_presence_ValuePresence(config?.preventedComponentEvents);
374
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;
375
422
  }
376
423
  }
377
424
  const src_ProductBase = ProductBase;
@@ -673,14 +720,20 @@ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
673
720
  return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
674
721
  }
675
722
  var _dec, _dec1, _dec2, _dec3, _initProto;
676
- const AnalyticsStateful_logger = createScopedLogger('Analytics');
723
+ const AnalyticsStateful_logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('Analytics');
677
724
  const MAX_QUEUED_EVENTS = 25;
678
- _dec = guardedBy('isNotDuplicated', {
679
- onBlocked: 'onBlockedByDuplication'
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'
680
733
  }), _dec1 = guardedBy('hasConsent', {
681
734
  onBlocked: 'onBlockedByConsent'
682
- }), _dec2 = guardedBy('isNotDuplicated', {
683
- onBlocked: 'onBlockedByDuplication'
735
+ }), _dec2 = guardedBy('hasConsent', {
736
+ onBlocked: 'onBlockedByConsent'
684
737
  }), _dec3 = guardedBy('hasConsent', {
685
738
  onBlocked: 'onBlockedByConsent'
686
739
  });
@@ -688,25 +741,31 @@ class AnalyticsStateful extends analytics_AnalyticsBase {
688
741
  static{
689
742
  ({ e: [_initProto] } = _apply_decs_2203_r(this, [
690
743
  [
691
- [
692
- _dec,
693
- _dec1
694
- ],
744
+ _dec,
695
745
  2,
696
746
  "trackComponentView"
697
747
  ],
698
748
  [
699
- [
700
- _dec2,
701
- _dec3
702
- ],
749
+ _dec1,
750
+ 2,
751
+ "trackComponentClick"
752
+ ],
753
+ [
754
+ _dec2,
755
+ 2,
756
+ "trackComponentHover"
757
+ ],
758
+ [
759
+ _dec3,
703
760
  2,
704
761
  "trackFlagView"
705
762
  ]
706
763
  ], []));
707
764
  }
708
765
  queue = (_initProto(this), new Map());
766
+ flushRuntime;
709
767
  states = {
768
+ blockedEventStream: toObservable(blockedEvent),
710
769
  eventStream: toObservable(signals_event),
711
770
  profile: toObservable(signals_profile)
712
771
  };
@@ -718,47 +777,47 @@ class AnalyticsStateful extends analytics_AnalyticsBase {
718
777
  config,
719
778
  interceptors
720
779
  });
721
- const { defaults } = config ?? {};
722
- if (defaults?.profile !== void 0) {
723
- const { profile: defaultProfile } = defaults;
724
- signals_profile.value = defaultProfile;
725
- }
726
- effect(()=>{
727
- const id = signals_profile.value?.id;
728
- AnalyticsStateful_logger.info(`Analytics ${consent.value ? 'will' : 'will not'} be collected due to consent (${consent.value})`);
729
- AnalyticsStateful_logger.debug(`Profile ${id && `with ID ${id}`} has been ${id ? 'set' : 'cleared'}`);
730
- });
731
- effect(()=>{
732
- if (online.value) this.flush();
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
+ }
733
789
  });
790
+ this.initializeEffects();
734
791
  }
735
792
  reset() {
793
+ this.flushRuntime.reset();
736
794
  batch(()=>{
795
+ blockedEvent.value = void 0;
737
796
  signals_event.value = void 0;
738
797
  signals_profile.value = void 0;
739
798
  });
740
799
  }
741
800
  hasConsent(name) {
742
- return !!consent.value || (this.allowedEventTypes ?? []).includes('trackComponentView' === name || 'trackFlagView' === name ? 'component' : name);
801
+ const mappedEventType = ANALYTICS_METHOD_EVENT_TYPE_MAP[name] ?? name;
802
+ return !!consent.value || (this.allowedEventTypes ?? []).includes(mappedEventType);
743
803
  }
744
804
  onBlockedByConsent(name, payload) {
745
805
  AnalyticsStateful_logger.warn(`Event "${name}" was blocked due to lack of consent; payload: ${JSON.stringify(payload)}`);
806
+ this.reportBlockedEvent('consent', 'analytics', name, payload);
746
807
  }
747
- isNotDuplicated(_name, payload) {
748
- const [{ componentId: value }, duplicationScope] = payload;
749
- const isDuplicated = this.duplicationDetector.isPresent(duplicationScope, value);
750
- if (!isDuplicated) this.duplicationDetector.addValue(duplicationScope, value);
751
- return !isDuplicated;
752
- }
753
- onBlockedByDuplication(name, payload) {
754
- const componentType = 'trackFlagView' === name ? 'flag' : 'component';
755
- AnalyticsStateful_logger.debug(`Duplicate "${componentType} view" event detected, skipping; payload: ${JSON.stringify(payload)}`);
756
- }
757
- async trackComponentView(payload, _duplicationScope = '') {
808
+ async trackComponentView(payload) {
758
809
  AnalyticsStateful_logger.info(`Processing "component view" event for ${payload.componentId}`);
759
810
  await this.enqueueEvent(this.builder.buildComponentView(payload));
760
811
  }
761
- async trackFlagView(payload, _duplicationScope = '') {
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) {
762
821
  AnalyticsStateful_logger.debug(`Processing "flag view" event for ${payload.componentId}`);
763
822
  await this.enqueueEvent(this.builder.buildFlagView(payload));
764
823
  }
@@ -766,56 +825,128 @@ class AnalyticsStateful extends analytics_AnalyticsBase {
766
825
  const { value: profile } = signals_profile;
767
826
  if (!profile) return void AnalyticsStateful_logger.warn('Attempting to emit an event without an Optimization profile');
768
827
  const intercepted = await this.interceptors.event.run(event);
769
- const validEvent = __rspack_external__contentful_optimization_api_client_cba5a7ee.InsightsEvent.parse(intercepted);
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);
770
829
  AnalyticsStateful_logger.debug(`Queueing ${validEvent.type} event for profile ${profile.id}`, validEvent);
771
- const profileEventQueue = this.queue.get(profile);
830
+ const { id: profileId } = profile;
831
+ const queuedProfileEvents = this.queue.get(profileId);
772
832
  signals_event.value = validEvent;
773
- if (profileEventQueue) profileEventQueue.push(validEvent);
774
- else this.queue.set(profile, [
775
- validEvent
776
- ]);
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
+ });
777
842
  await this.flushMaxEvents();
778
843
  }
779
844
  async flushMaxEvents() {
780
- if (this.queue.values().toArray().flat().length >= MAX_QUEUED_EVENTS) await this.flush();
781
- }
782
- async flush() {
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;
783
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() {
784
890
  const batches = [];
785
- this.queue.forEach((events, profile)=>batches.push({
891
+ this.queue.forEach(({ profile, events })=>{
892
+ batches.push({
786
893
  profile,
787
894
  events
788
- }));
789
- if (!batches.length) return;
790
- const sendSuccess = await this.api.insights.sendBatchEvents(batches);
791
- if (sendSuccess) this.queue.clear();
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;
792
913
  }
793
914
  }
794
915
  const analytics_AnalyticsStateful = AnalyticsStateful;
795
- const AnalyticsStateless_logger = createScopedLogger('Analytics');
916
+ const AnalyticsStateless_logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('Analytics');
796
917
  class AnalyticsStateless extends analytics_AnalyticsBase {
797
918
  async trackComponentView(args) {
798
919
  AnalyticsStateless_logger.info('Processing "component view" event');
799
920
  const { profile, ...builderArgs } = args;
800
921
  const event = this.builder.buildComponentView(builderArgs);
801
- const intercepted = await this.interceptors.event.run(event);
802
- const parsed = __rspack_external__contentful_optimization_api_client_cba5a7ee.ComponentViewEvent.parse(intercepted);
803
- await this.sendBatchEvent(parsed, profile);
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);
804
935
  }
805
936
  async trackFlagView(args) {
806
937
  AnalyticsStateless_logger.debug('Processing "flag view" event');
807
938
  const { profile, ...builderArgs } = args;
808
939
  const event = this.builder.buildFlagView(builderArgs);
809
- const intercepted = await this.interceptors.event.run(event);
810
- const parsed = __rspack_external__contentful_optimization_api_client_cba5a7ee.ComponentViewEvent.parse(intercepted);
811
- await this.sendBatchEvent(parsed, profile);
940
+ await this.sendBatchEvent(event, profile);
812
941
  }
813
942
  async sendBatchEvent(event, profile) {
814
- const batchEvent = __rspack_external__contentful_optimization_api_client_cba5a7ee.BatchInsightsEventArray.parse([
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, [
815
946
  {
816
947
  profile,
817
948
  events: [
818
- event
949
+ parsed
819
950
  ]
820
951
  }
821
952
  ]);
@@ -823,16 +954,6 @@ class AnalyticsStateless extends analytics_AnalyticsBase {
823
954
  }
824
955
  }
825
956
  const analytics_AnalyticsStateless = AnalyticsStateless;
826
- const OPTIMIZATION_CORE_SDK_VERSION = "0.1.0-alpha8";
827
- const OPTIMIZATION_CORE_SDK_NAME = "@contentful/optimization-core";
828
- const ANONYMOUS_ID_COOKIE = 'ctfl-opt-aid';
829
- const ANONYMOUS_ID_KEY = '__ctfl_opt_anonymous_id__';
830
- const CONSENT_KEY = '__ctfl_opt_consent__';
831
- const CHANGES_CACHE_KEY = '__ctfl_opt_changes__';
832
- const DEBUG_FLAG_KEY = '__ctfl_opt_debug__';
833
- const PROFILE_CACHE_KEY = '__ctfl_opt_profile__';
834
- const PERSONALIZATIONS_CACHE_KEY = '__ctfl_opt_personalizations__';
835
- const ANONYMOUS_ID_KEY_LEGACY = '__nt_anonymous_id__';
836
957
  class InterceptorManager {
837
958
  interceptors = new Map();
838
959
  nextId = 0;
@@ -868,13 +989,14 @@ class CoreBase {
868
989
  };
869
990
  constructor(config){
870
991
  this.config = config;
871
- const { analytics, personalization, eventBuilder, logLevel, environment, clientId } = config;
872
- logger.addSink(new ConsoleLogSink(logLevel));
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));
873
994
  const apiConfig = {
874
- ...analytics,
875
- ...personalization,
876
995
  clientId,
877
- environment
996
+ environment,
997
+ fetchOptions,
998
+ analytics,
999
+ personalization
878
1000
  };
879
1001
  this.api = new __rspack_external__contentful_optimization_api_client_cba5a7ee.ApiClient(apiConfig);
880
1002
  this.eventBuilder = new __rspack_external__contentful_optimization_api_client_cba5a7ee.EventBuilder(eventBuilder ?? {
@@ -885,42 +1007,80 @@ class CoreBase {
885
1007
  }
886
1008
  });
887
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
+ }
888
1019
  getCustomFlag(name, changes) {
889
- return this.personalization.getCustomFlag(name, changes);
1020
+ return this._personalization.getCustomFlag(name, changes);
1021
+ }
1022
+ getCustomFlags(changes) {
1023
+ return this._personalization.getCustomFlags(changes);
890
1024
  }
891
1025
  personalizeEntry(entry, personalizations) {
892
- return this.personalization.personalizeEntry(entry, personalizations);
1026
+ return this._personalization.personalizeEntry(entry, personalizations);
893
1027
  }
894
1028
  getMergeTagValue(embeddedEntryNodeTarget, profile) {
895
- return this.personalization.getMergeTagValue(embeddedEntryNodeTarget, profile);
1029
+ return this._personalization.getMergeTagValue(embeddedEntryNodeTarget, profile);
896
1030
  }
897
1031
  async identify(payload) {
898
- return await this.personalization.identify(payload);
1032
+ return await this._personalization.identify(payload);
899
1033
  }
900
1034
  async page(payload) {
901
- return await this.personalization.page(payload);
1035
+ return await this._personalization.page(payload);
902
1036
  }
903
1037
  async screen(payload) {
904
- return await this.personalization.screen(payload);
1038
+ return await this._personalization.screen(payload);
905
1039
  }
906
1040
  async track(payload) {
907
- return await this.personalization.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);
908
1049
  }
909
- async trackComponentView(payload, duplicationScope) {
910
- if (payload.sticky) return await this.personalization.trackComponentView(payload, duplicationScope);
911
- await this.analytics.trackComponentView(payload, duplicationScope);
1050
+ async trackComponentHover(payload) {
1051
+ await this._analytics.trackComponentHover(payload);
912
1052
  }
913
- async trackFlagView(payload, duplicationScope) {
914
- await this.analytics.trackFlagView(payload, duplicationScope);
1053
+ async trackFlagView(payload) {
1054
+ await this._analytics.trackFlagView(payload);
915
1055
  }
916
1056
  }
917
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
+ };
918
1075
  class PersonalizationBase extends src_ProductBase {
919
1076
  flagsResolver = resolvers_FlagsResolver;
920
1077
  mergeTagValueResolver = resolvers_MergeTagValueResolver;
921
1078
  personalizedEntryResolver = resolvers_PersonalizedEntryResolver;
922
1079
  getCustomFlag(name, changes) {
923
- return resolvers_FlagsResolver.resolve(changes)[name];
1080
+ return this.getCustomFlags(changes)[name];
1081
+ }
1082
+ getCustomFlags(changes) {
1083
+ return resolvers_FlagsResolver.resolve(changes);
924
1084
  }
925
1085
  personalizeEntry(entry, personalizations) {
926
1086
  return resolvers_PersonalizedEntryResolver.resolve(entry, personalizations);
@@ -1224,8 +1384,14 @@ function PersonalizationStateful_applyDecs2203RFactory() {
1224
1384
  function PersonalizationStateful_apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
1225
1385
  return (PersonalizationStateful_apply_decs_2203_r = PersonalizationStateful_applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
1226
1386
  }
1227
- var PersonalizationStateful_dec, PersonalizationStateful_dec1, PersonalizationStateful_dec2, PersonalizationStateful_dec3, _dec4, _dec5, PersonalizationStateful_initProto;
1228
- const PersonalizationStateful_logger = createScopedLogger('Personalization');
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
+ });
1229
1395
  PersonalizationStateful_dec = guardedBy('hasConsent', {
1230
1396
  onBlocked: 'onBlockedByConsent'
1231
1397
  }), PersonalizationStateful_dec1 = guardedBy('hasConsent', {
@@ -1234,9 +1400,7 @@ PersonalizationStateful_dec = guardedBy('hasConsent', {
1234
1400
  onBlocked: 'onBlockedByConsent'
1235
1401
  }), PersonalizationStateful_dec3 = guardedBy('hasConsent', {
1236
1402
  onBlocked: 'onBlockedByConsent'
1237
- }), _dec4 = guardedBy('isNotDuplicated', {
1238
- onBlocked: 'onBlockedByDuplication'
1239
- }), _dec5 = guardedBy('hasConsent', {
1403
+ }), _dec4 = guardedBy('hasConsent', {
1240
1404
  onBlocked: 'onBlockedByConsent'
1241
1405
  });
1242
1406
  class PersonalizationStateful extends personalization_PersonalizationBase {
@@ -1263,17 +1427,17 @@ class PersonalizationStateful extends personalization_PersonalizationBase {
1263
1427
  "track"
1264
1428
  ],
1265
1429
  [
1266
- [
1267
- _dec4,
1268
- _dec5
1269
- ],
1430
+ _dec4,
1270
1431
  2,
1271
1432
  "trackComponentView"
1272
1433
  ]
1273
1434
  ], []));
1274
1435
  }
1275
1436
  offlineQueue = (PersonalizationStateful_initProto(this), new Set());
1437
+ queuePolicy;
1438
+ flushRuntime;
1276
1439
  states = {
1440
+ blockedEventStream: toObservable(blockedEvent),
1277
1441
  eventStream: toObservable(signals_event),
1278
1442
  flags: toObservable(flags),
1279
1443
  profile: toObservable(signals_profile),
@@ -1288,7 +1452,17 @@ class PersonalizationStateful extends personalization_PersonalizationBase {
1288
1452
  config,
1289
1453
  interceptors
1290
1454
  });
1291
- const { defaults, getAnonymousId } = config ?? {};
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
+ });
1292
1466
  if (defaults) {
1293
1467
  const { changes: defaultChanges, personalizations: defaultPersonalizations, profile: defaultProfile } = defaults;
1294
1468
  batch(()=>{
@@ -1312,12 +1486,18 @@ class PersonalizationStateful extends personalization_PersonalizationBase {
1312
1486
  PersonalizationStateful_logger.info(`Personalization ${consent.value ? 'will' : 'will not'} take effect due to consent (${consent.value})`);
1313
1487
  });
1314
1488
  effect(()=>{
1315
- if (online.value) this.flush();
1489
+ if (!online.value) return;
1490
+ this.flushRuntime.clearScheduledRetry();
1491
+ this.flush({
1492
+ force: true
1493
+ });
1316
1494
  });
1317
1495
  }
1318
1496
  reset() {
1497
+ this.flushRuntime.reset();
1319
1498
  batch(()=>{
1320
1499
  signals_changes.value = void 0;
1500
+ blockedEvent.value = void 0;
1321
1501
  signals_event.value = void 0;
1322
1502
  signals_profile.value = void 0;
1323
1503
  signals_personalizations.value = void 0;
@@ -1326,6 +1506,9 @@ class PersonalizationStateful extends personalization_PersonalizationBase {
1326
1506
  getCustomFlag(name, changes = signals_changes.value) {
1327
1507
  return super.getCustomFlag(name, changes);
1328
1508
  }
1509
+ getCustomFlags(changes = signals_changes.value) {
1510
+ return super.getCustomFlags(changes);
1511
+ }
1329
1512
  personalizeEntry(entry, personalizations = signals_personalizations.value) {
1330
1513
  return super.personalizeEntry(entry, personalizations);
1331
1514
  }
@@ -1337,15 +1520,7 @@ class PersonalizationStateful extends personalization_PersonalizationBase {
1337
1520
  }
1338
1521
  onBlockedByConsent(name, payload) {
1339
1522
  PersonalizationStateful_logger.warn(`Event "${name}" was blocked due to lack of consent; payload: ${JSON.stringify(payload)}`);
1340
- }
1341
- isNotDuplicated(_name, payload) {
1342
- const [{ componentId: value }, duplicationScope] = payload;
1343
- const isDuplicated = this.duplicationDetector.isPresent(duplicationScope, value);
1344
- if (!isDuplicated) this.duplicationDetector.addValue(duplicationScope, value);
1345
- return !isDuplicated;
1346
- }
1347
- onBlockedByDuplication(_name, payload) {
1348
- PersonalizationStateful_logger.debug(`Duplicate "component view" event detected, skipping; payload: ${JSON.stringify(payload)}`);
1523
+ this.reportBlockedEvent('consent', 'personalization', name, payload);
1349
1524
  }
1350
1525
  async identify(payload) {
1351
1526
  PersonalizationStateful_logger.info('Sending "identify" event');
@@ -1367,26 +1542,89 @@ class PersonalizationStateful extends personalization_PersonalizationBase {
1367
1542
  const event = this.builder.buildTrack(payload);
1368
1543
  return await this.sendOrEnqueueEvent(event);
1369
1544
  }
1370
- async trackComponentView(payload, _duplicationScope = '') {
1545
+ async trackComponentView(payload) {
1371
1546
  PersonalizationStateful_logger.info(`Sending "track personalization" event for ${payload.componentId}`);
1372
1547
  const event = this.builder.buildComponentView(payload);
1373
1548
  return await this.sendOrEnqueueEvent(event);
1374
1549
  }
1375
1550
  async sendOrEnqueueEvent(event) {
1376
1551
  const intercepted = await this.interceptors.event.run(event);
1377
- const validEvent = __rspack_external__contentful_optimization_api_client_cba5a7ee.ExperienceEvent.parse(intercepted);
1552
+ const validEvent = (0, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.parseWithFriendlyError)(__rspack_external__contentful_optimization_api_client_api_schemas_4192893e.ExperienceEvent, intercepted);
1378
1553
  signals_event.value = validEvent;
1379
1554
  if (online.value) return await this.upsertProfile([
1380
1555
  validEvent
1381
1556
  ]);
1382
1557
  PersonalizationStateful_logger.debug(`Queueing ${validEvent.type} event`, validEvent);
1383
- this.offlineQueue.add(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
+ });
1384
1574
  }
1385
- async flush() {
1386
- if (0 === this.offlineQueue.size) return;
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
+ }
1591
+ }
1592
+ async flush(options = {}) {
1593
+ await this.flushOfflineQueue(options);
1594
+ }
1595
+ async flushOfflineQueue(options = {}) {
1596
+ const { force = false } = options;
1597
+ if (this.flushRuntime.shouldSkip({
1598
+ force,
1599
+ isOnline: !!online.value
1600
+ })) return;
1601
+ if (0 === this.offlineQueue.size) return void this.flushRuntime.clearScheduledRetry();
1387
1602
  PersonalizationStateful_logger.debug('Flushing offline event queue');
1388
- await this.upsertProfile(Array.from(this.offlineQueue));
1389
- this.offlineQueue.clear();
1603
+ const queuedEvents = Array.from(this.offlineQueue);
1604
+ this.flushRuntime.markFlushStarted();
1605
+ try {
1606
+ const sendSuccess = await this.tryUpsertQueuedEvents(queuedEvents);
1607
+ if (sendSuccess) {
1608
+ queuedEvents.forEach((event)=>{
1609
+ this.offlineQueue.delete(event);
1610
+ });
1611
+ this.flushRuntime.handleFlushSuccess();
1612
+ } else this.flushRuntime.handleFlushFailure({
1613
+ queuedBatches: this.offlineQueue.size > 0 ? 1 : 0,
1614
+ queuedEvents: this.offlineQueue.size
1615
+ });
1616
+ } finally{
1617
+ this.flushRuntime.markFlushFinished();
1618
+ }
1619
+ }
1620
+ async tryUpsertQueuedEvents(events) {
1621
+ try {
1622
+ await this.upsertProfile(events);
1623
+ return true;
1624
+ } catch (error) {
1625
+ PersonalizationStateful_logger.warn('Personalization offline queue flush request threw an error', error);
1626
+ return false;
1627
+ }
1390
1628
  }
1391
1629
  async upsertProfile(events) {
1392
1630
  const anonymousId = this.getAnonymousId();
@@ -1409,101 +1647,142 @@ class PersonalizationStateful extends personalization_PersonalizationBase {
1409
1647
  }
1410
1648
  }
1411
1649
  const personalization_PersonalizationStateful = PersonalizationStateful;
1412
- const PersonalizationStateless_logger = createScopedLogger('Personalization');
1650
+ const PersonalizationStateless_logger = (0, __rspack_external__contentful_optimization_api_client_logger_f0d05f82.createScopedLogger)('Personalization');
1413
1651
  class PersonalizationStateless extends personalization_PersonalizationBase {
1414
1652
  async identify(payload) {
1415
1653
  PersonalizationStateless_logger.info('Sending "identify" event');
1416
1654
  const { profile, ...builderArgs } = payload;
1417
- const event = __rspack_external__contentful_optimization_api_client_cba5a7ee.IdentifyEvent.parse(this.builder.buildIdentify(builderArgs));
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));
1418
1656
  return await this.upsertProfile(event, profile);
1419
1657
  }
1420
1658
  async page(payload) {
1421
1659
  PersonalizationStateless_logger.info('Sending "page" event');
1422
1660
  const { profile, ...builderArgs } = payload;
1423
- const event = __rspack_external__contentful_optimization_api_client_cba5a7ee.PageViewEvent.parse(this.builder.buildPageView(builderArgs));
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));
1424
1662
  return await this.upsertProfile(event, profile);
1425
1663
  }
1426
1664
  async screen(payload) {
1427
1665
  PersonalizationStateless_logger.info(`Sending "screen" event for "${payload.name}"`);
1428
1666
  const { profile, ...builderArgs } = payload;
1429
- const event = __rspack_external__contentful_optimization_api_client_cba5a7ee.ScreenViewEvent.parse(this.builder.buildScreenView(builderArgs));
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));
1430
1668
  return await this.upsertProfile(event, profile);
1431
1669
  }
1432
1670
  async track(payload) {
1433
1671
  PersonalizationStateless_logger.info(`Sending "track" event "${payload.event}"`);
1434
1672
  const { profile, ...builderArgs } = payload;
1435
- const event = __rspack_external__contentful_optimization_api_client_cba5a7ee.TrackEvent.parse(this.builder.buildTrack(builderArgs));
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));
1436
1674
  return await this.upsertProfile(event, profile);
1437
1675
  }
1438
1676
  async trackComponentView(payload) {
1439
1677
  PersonalizationStateless_logger.info('Sending "track personalization" event');
1440
1678
  const { profile, ...builderArgs } = payload;
1441
- const event = __rspack_external__contentful_optimization_api_client_cba5a7ee.ComponentViewEvent.parse(this.builder.buildComponentView(builderArgs));
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));
1442
1680
  return await this.upsertProfile(event, profile);
1443
1681
  }
1444
1682
  async upsertProfile(event, profile) {
1445
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);
1446
1685
  const data = await this.api.experience.upsertProfile({
1447
1686
  profileId: profile?.id,
1448
1687
  events: [
1449
- intercepted
1688
+ validEvent
1450
1689
  ]
1451
1690
  });
1452
1691
  return data;
1453
1692
  }
1454
1693
  }
1455
1694
  const personalization_PersonalizationStateless = PersonalizationStateless;
1695
+ const splitScopedQueuePolicy = (config)=>{
1696
+ if (void 0 === config) return {
1697
+ apiConfig: void 0,
1698
+ queuePolicy: void 0
1699
+ };
1700
+ const { queuePolicy, ...apiConfig } = config;
1701
+ const resolvedApiConfig = Object.keys(apiConfig).length > 0 ? apiConfig : void 0;
1702
+ return {
1703
+ apiConfig: resolvedApiConfig,
1704
+ queuePolicy
1705
+ };
1706
+ };
1707
+ let statefulInstanceCounter = 0;
1456
1708
  class CoreStateful extends src_CoreBase {
1457
- analytics;
1458
- personalization;
1709
+ singletonOwner;
1710
+ destroyed = false;
1711
+ _analytics;
1712
+ _personalization;
1459
1713
  constructor(config){
1460
- super(config);
1461
- const { allowedEventTypes, defaults, getAnonymousId, preventedComponentEvents } = config;
1462
- if (defaults?.consent !== void 0) {
1463
- const { consent: defaultConsent } = defaults;
1464
- consent.value = defaultConsent;
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);
1722
+ this.singletonOwner = `CoreStateful#${++statefulInstanceCounter}`;
1723
+ acquireStatefulRuntimeSingleton(this.singletonOwner);
1724
+ 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
1743
+ });
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
1760
+ });
1761
+ } catch (error) {
1762
+ releaseStatefulRuntimeSingleton(this.singletonOwner);
1763
+ throw error;
1465
1764
  }
1466
- this.analytics = new analytics_AnalyticsStateful({
1467
- api: this.api,
1468
- builder: this.eventBuilder,
1469
- config: {
1470
- allowedEventTypes,
1471
- preventedComponentEvents,
1472
- defaults: {
1473
- consent: defaults?.consent,
1474
- profile: defaults?.profile
1475
- }
1476
- },
1477
- interceptors: this.interceptors
1478
- });
1479
- this.personalization = new personalization_PersonalizationStateful({
1480
- api: this.api,
1481
- builder: this.eventBuilder,
1482
- config: {
1483
- allowedEventTypes,
1484
- getAnonymousId,
1485
- preventedComponentEvents,
1486
- defaults: {
1487
- consent: defaults?.consent,
1488
- changes: defaults?.changes,
1489
- profile: defaults?.profile,
1490
- personalizations: defaults?.personalizations
1491
- }
1492
- },
1493
- interceptors: this.interceptors
1494
- });
1765
+ }
1766
+ destroy() {
1767
+ if (this.destroyed) return;
1768
+ this.destroyed = true;
1769
+ releaseStatefulRuntimeSingleton(this.singletonOwner);
1495
1770
  }
1496
1771
  get states() {
1497
1772
  return {
1773
+ blockedEventStream: toObservable(blockedEvent),
1498
1774
  consent: toObservable(consent),
1499
1775
  eventStream: toObservable(signals_event),
1500
1776
  flags: toObservable(flags),
1501
1777
  personalizations: toObservable(signals_personalizations),
1778
+ previewPanelAttached: toObservable(previewPanelAttached),
1779
+ previewPanelOpen: toObservable(previewPanelOpen),
1502
1780
  profile: toObservable(signals_profile)
1503
1781
  };
1504
1782
  }
1505
1783
  reset() {
1506
1784
  batch(()=>{
1785
+ blockedEvent.value = void 0;
1507
1786
  signals_event.value = void 0;
1508
1787
  signals_changes.value = void 0;
1509
1788
  signals_profile.value = void 0;
@@ -1511,38 +1790,35 @@ class CoreStateful extends src_CoreBase {
1511
1790
  });
1512
1791
  }
1513
1792
  async flush() {
1514
- await this.analytics.flush();
1515
- await this.personalization.flush();
1793
+ await this._analytics.flush();
1794
+ await this._personalization.flush();
1516
1795
  }
1517
1796
  consent(accept) {
1518
1797
  consent.value = accept;
1519
1798
  }
1520
- online(isOnline) {
1799
+ get online() {
1800
+ return online.value ?? false;
1801
+ }
1802
+ set online(isOnline) {
1521
1803
  online.value = isOnline;
1522
1804
  }
1523
1805
  registerPreviewPanel(previewPanel) {
1524
- if (previewPanel) {
1525
- previewPanel.signals = signals;
1526
- previewPanel.signalFns = signalFns;
1527
- }
1528
- return {
1529
- signals: signals,
1530
- signalFns: signalFns
1531
- };
1806
+ Reflect.set(previewPanel, PREVIEW_PANEL_SIGNALS_SYMBOL, signals);
1807
+ Reflect.set(previewPanel, PREVIEW_PANEL_SIGNAL_FNS_SYMBOL, signalFns);
1532
1808
  }
1533
1809
  }
1534
1810
  const src_CoreStateful = CoreStateful;
1535
1811
  class CoreStateless extends src_CoreBase {
1536
- analytics;
1537
- personalization;
1812
+ _analytics;
1813
+ _personalization;
1538
1814
  constructor(config){
1539
1815
  super(config);
1540
- this.analytics = new analytics_AnalyticsStateless({
1816
+ this._analytics = new analytics_AnalyticsStateless({
1541
1817
  api: this.api,
1542
1818
  builder: this.eventBuilder,
1543
1819
  interceptors: this.interceptors
1544
1820
  });
1545
- this.personalization = new personalization_PersonalizationStateless({
1821
+ this._personalization = new personalization_PersonalizationStateless({
1546
1822
  api: this.api,
1547
1823
  builder: this.eventBuilder,
1548
1824
  interceptors: this.interceptors
@@ -1550,8 +1826,8 @@ class CoreStateless extends src_CoreBase {
1550
1826
  }
1551
1827
  }
1552
1828
  const src_CoreStateless = CoreStateless;
1553
- var src_ANONYMOUS_ID_COOKIE_LEGACY = "ntaid";
1554
- export * from "@contentful/optimization-api-client";
1555
- export { ANONYMOUS_ID_COOKIE, ANONYMOUS_ID_KEY, ANONYMOUS_ID_KEY_LEGACY, CHANGES_CACHE_KEY, CONSENT_KEY, ConsoleLogSink, DEBUG_FLAG_KEY, InterceptorManager, Logger, OPTIMIZATION_CORE_SDK_NAME, OPTIMIZATION_CORE_SDK_VERSION, PERSONALIZATIONS_CACHE_KEY, PROFILE_CACHE_KEY, analytics_AnalyticsStateful as AnalyticsStateful, analytics_AnalyticsStateless as AnalyticsStateless, batch, createScopedLogger, effect, guardedBy, logger, personalization_PersonalizationStateful as PersonalizationStateful, personalization_PersonalizationStateless as PersonalizationStateless, resolvers_FlagsResolver as FlagsResolver, resolvers_MergeTagValueResolver as MergeTagValueResolver, resolvers_PersonalizedEntryResolver as PersonalizedEntryResolver, signalFns, signals, src_ANONYMOUS_ID_COOKIE_LEGACY as ANONYMOUS_ID_COOKIE_LEGACY, src_CoreStateful as CoreStateful, src_CoreStateless as CoreStateless, src_LogSink as LogSink, value_presence_ValuePresence as ValuePresence };
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";
1830
+ 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 };
1556
1832
 
1557
1833
  //# sourceMappingURL=index.mjs.map