@contentful/optimization-core 0.1.0-alpha11 → 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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/constants.ts","../src/symbols.ts","webpack/runtime/compat_get_default_export","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../src/signals/Observable.ts","../src/signals/signals.ts","../src/events/EventBuilder.ts","../src/lib/interceptor/InterceptorManager.ts","../src/resolvers/FlagsResolver.ts","../src/resolvers/MergeTagValueResolver.ts","../src/resolvers/OptimizedEntryResolver.ts","../src/CoreBase.ts","../src/CoreStatefulEventEmitter.ts","../src/lib/number/number.ts","../src/lib/queue/flushPolicy.ts","../src/lib/singleton/StatefulRuntimeSingleton.ts","../src/lib/queue/QueueFlushRuntime.ts","../src/queues/ExperienceQueue.ts","../src/queues/InsightsQueue.ts","../src/CoreStateful.ts","../src/CoreStatelessRequestScope.ts","../src/CoreStateless.ts","../src/lib/decorators/guardedBy.ts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/naming-convention -- Replaced at build-time\ndeclare const __OPTIMIZATION_VERSION__: string | undefined\n// eslint-disable-next-line @typescript-eslint/naming-convention -- Replaced at build-time\ndeclare const __OPTIMIZATION_PACKAGE_NAME__: string | undefined\n\n/**\n * The current version of the Optimization Core SDK, injected at build time.\n *\n * @public\n */\nexport const OPTIMIZATION_CORE_SDK_VERSION =\n typeof __OPTIMIZATION_VERSION__ === 'string' ? __OPTIMIZATION_VERSION__ : '0.0.0'\n/**\n * The package name of the Optimization Core SDK, injected at build time.\n *\n * @public\n */\nexport const OPTIMIZATION_CORE_SDK_NAME =\n typeof __OPTIMIZATION_PACKAGE_NAME__ === 'string'\n ? __OPTIMIZATION_PACKAGE_NAME__\n : '@contentful/optimization-core'\n\n/**\n * Anonymous-ID cookie name used by the Optimization Core.\n *\n * @public\n * @remarks\n * This constant represents the cookie key used by the Optimization Framework\n * to persist an anonymous identifier for tracking optimization and insights\n * events when no explicit profile is known.\n *\n * @example\n * ```ts\n * import { ANONYMOUS_ID_COOKIE } from '@contentful/optimization-core/constants'\n * const profileId = request.cookies[ANONYMOUS_ID_COOKIE]\n * ```\n */\nexport const ANONYMOUS_ID_COOKIE = 'ctfl-opt-aid'\n\n/**\n * Storage key for the anonymous identifier.\n *\n * @internal\n */\nexport const ANONYMOUS_ID_KEY = '__ctfl_opt_anonymous_id__'\n\n/**\n * Storage key for the persisted consent status.\n *\n * @internal\n */\nexport const CONSENT_KEY = '__ctfl_opt_consent__'\n\n/**\n * Storage key for cached Custom Flags.\n *\n * @internal\n */\nexport const CHANGES_CACHE_KEY = '__ctfl_opt_changes__'\n\n/**\n * Storage key for the debug flag toggle.\n *\n * @internal\n */\nexport const DEBUG_FLAG_KEY = '__ctfl_opt_debug__'\n\n/**\n * Storage key for cached profile data.\n *\n * @internal\n */\nexport const PROFILE_CACHE_KEY = '__ctfl_opt_profile__'\n\n/**\n * Storage key for cached selected optimizations.\n *\n * @internal\n */\nexport const SELECTED_OPTIMIZATIONS_CACHE_KEY = '__ctfl_opt_selected-optimizations__'\n\n/**\n * Legacy anoynmous ID cookie key for migration from experience.js\n *\n * @internal\n */\nexport const ANONYMOUS_ID_COOKIE_LEGACY = 'ntaid'\n\n/**\n * Legacy anoynmous ID storage key for migration from experience.js\n *\n * @internal\n */\nexport const ANONYMOUS_ID_KEY_LEGACY = '__nt_anonymous_id__'\n","/**\n * Well-known symbols used by the preview panel bridge.\n *\n * @public\n */\nexport const PREVIEW_PANEL_SIGNALS_SYMBOL = Symbol.for('ctfl.optimization.preview.signals')\nexport const PREVIEW_PANEL_SIGNAL_FNS_SYMBOL = Symbol.for('ctfl.optimization.preview.signalFns')\n","// getDefaultExport function for compatibility with non-ESM modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};\n","__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { effect } from '@preact/signals-core'\nimport { cloneDeep } from 'es-toolkit'\n\n/**\n * Disposable handle returned by observable subscriptions.\n *\n * @public\n */\nexport interface Subscription {\n /** Stop receiving future emissions for the subscription. */\n unsubscribe: () => void\n}\n\n/**\n * Minimal observable contract used by stateful Core signal streams.\n *\n * @typeParam T - Value type emitted by the observable.\n * @public\n */\nexport interface Observable<T> {\n /**\n * Deep-cloned snapshot of the current signal value.\n *\n * @remarks\n * A clone is returned to prevent accidental in-place mutations from leaking\n * back into internal signal state.\n */\n readonly current: T\n /**\n * Subscribe to all value updates (including the current value immediately).\n *\n * @param next - Callback invoked for each emitted value snapshot.\n * @returns A {@link Subscription} used to stop observing updates.\n *\n * @remarks\n * Values are deep-cloned before being passed to `next`.\n */\n subscribe: (next: (v: T) => void) => Subscription\n /**\n * Subscribe to the first non-nullish value, then auto-unsubscribe.\n *\n * @param next - Callback invoked exactly once with the first non-nullish value.\n * @returns A {@link Subscription} that can cancel before the first emission.\n *\n * @remarks\n * Values are deep-cloned before being passed to `next`.\n */\n subscribeOnce: (next: (v: NonNullable<T>) => void) => Subscription\n}\n\nfunction isNonNullish<TValue>(value: TValue): value is NonNullable<TValue> {\n return value !== undefined && value !== null\n}\n\nfunction toError(value: unknown): Error {\n if (value instanceof Error) return value\n return new Error(`Subscriber threw non-Error value: ${String(value)}`)\n}\n\n/**\n * Wrap a signal-like object with the local {@link Observable} contract.\n *\n * @typeParam T - Signal value type.\n * @param s - Signal-like source exposing a `value` property.\n * @returns Observable adapter for the given signal source.\n *\n * @remarks\n * All emitted values and `current` snapshots are deep-cloned to isolate\n * subscriber-side mutation from internal Core state.\n *\n * @public\n */\nexport function toObservable<T>(s: { value: T }): Observable<T> {\n return {\n get current() {\n return cloneDeep(s.value)\n },\n\n subscribe(next) {\n const dispose = effect(() => {\n next(cloneDeep(s.value))\n })\n\n return { unsubscribe: dispose }\n },\n\n subscribeOnce(next) {\n let closed = false\n let isEffectActive = false\n let dispose: () => void = () => undefined\n\n const stop = (): void => {\n if (closed) return\n closed = true\n\n if (isEffectActive) dispose()\n }\n\n dispose = effect(() => {\n if (closed) return\n\n const { value } = s\n if (!isNonNullish(value)) return\n\n closed = true\n\n let callbackError: Error | null = null\n try {\n next(cloneDeep(value))\n } catch (error) {\n callbackError = toError(error)\n }\n\n if (isEffectActive) {\n dispose()\n } else {\n queueMicrotask(dispose)\n }\n\n if (callbackError) throw callbackError\n })\n\n isEffectActive = true\n\n return { unsubscribe: stop }\n },\n }\n}\n\n/**\n * Wrap a signal-like object with an {@link Observable} that suppresses\n * duplicate emissions according to a comparator.\n *\n * @typeParam T - Signal value type.\n * @param s - Signal-like source exposing a `value` property.\n * @param isEqual - Comparator that returns `true` when values are equivalent.\n * @returns Observable adapter that only emits distinct values.\n *\n * @remarks\n * The first emission is always delivered. Subsequent emissions are skipped\n * when `isEqual(previous, current)` returns `true`.\n *\n * @public\n */\nexport function toDistinctObservable<T>(\n s: { value: T },\n isEqual: (previous: T, current: T) => boolean,\n): Observable<T> {\n const observable = toObservable(s)\n\n return {\n get current() {\n return observable.current\n },\n\n subscribe(next) {\n let hasPrevious = false\n let previous = cloneDeep(observable.current)\n\n return observable.subscribe((value) => {\n if (hasPrevious && isEqual(previous, value)) return\n\n hasPrevious = true\n previous = cloneDeep(value)\n next(value)\n })\n },\n\n subscribeOnce(next) {\n return observable.subscribeOnce(next)\n },\n }\n}\n","import type {\n InsightsEvent as AnalyticsEvent,\n ChangeArray,\n ExperienceEvent as OptimizationEvent,\n Profile,\n SelectedOptimizationArray,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { batch, computed, effect, signal, type Signal, untracked } from '@preact/signals-core'\nimport type { BlockedEvent } from '../BlockedEvent'\n\n/**\n * Latest optimization changes returned by the Experience API.\n *\n * @public\n */\nexport const changes: Signal<ChangeArray | undefined> = signal<ChangeArray | undefined>()\n\n/**\n * Most recent blocked-event metadata produced by consent/runtime guards.\n *\n * @public\n */\nexport const blockedEvent: Signal<BlockedEvent | undefined> = signal<BlockedEvent | undefined>()\n\n/**\n * Current optimization/analytics consent state.\n *\n * @public\n */\nexport const consent = signal<boolean | undefined>()\n\n/**\n * Most recent emitted optimization event.\n *\n * @public\n */\nexport const event: Signal<AnalyticsEvent | OptimizationEvent | undefined> = signal<\n AnalyticsEvent | OptimizationEvent | undefined\n>()\n\n/**\n * Runtime online/offline signal used by queue flush logic.\n *\n * @defaultValue `true`\n * @public\n */\nexport const online = signal<boolean | undefined>(true)\n\n/**\n * Indicates whether the preview panel bridge has been attached.\n *\n * @defaultValue `false`\n * @public\n */\nexport const previewPanelAttached = signal<boolean>(false)\n\n/**\n * Indicates whether the preview panel is currently open.\n *\n * @defaultValue `false`\n * @public\n */\nexport const previewPanelOpen = signal<boolean>(false)\n\n/**\n * Latest selected optimization variants.\n *\n * @public\n */\nexport const selectedOptimizations = signal<SelectedOptimizationArray | undefined>()\n\n/**\n * Whether optimization selection data is available for entry resolution.\n *\n * @public\n */\nexport const canOptimize = computed<boolean>(() => selectedOptimizations.value !== undefined)\n\n/**\n * Active profile associated with current runtime state.\n *\n * @public\n */\nexport const profile: Signal<Profile | undefined> = signal<Profile | undefined>()\n\n/**\n * Collection of shared stateful Core signals.\n *\n * @public\n */\nexport interface Signals {\n /** Most recent blocked-event metadata. */\n blockedEvent: typeof blockedEvent\n /** Latest optimization changes payload. */\n changes: typeof changes\n /** Current consent signal. */\n consent: typeof consent\n /** Most recent emitted event signal. */\n event: typeof event\n /** Runtime connectivity signal. */\n online: typeof online\n /** Preview panel attachment signal. */\n previewPanelAttached: typeof previewPanelAttached\n /** Preview panel open-state signal. */\n previewPanelOpen: typeof previewPanelOpen\n /** Selected optimization variants signal. */\n selectedOptimizations: typeof selectedOptimizations\n /** Whether optimization selection data is currently available. */\n canOptimize: typeof canOptimize\n /** Active profile signal. */\n profile: typeof profile\n}\n\n/**\n * Signal utility functions shared with preview tooling and extensions.\n *\n * @public\n */\nexport interface SignalFns {\n /** Execute multiple signal writes in one reactive batch. */\n batch: typeof batch\n /** Create a derived computed signal. */\n computed: typeof computed\n /** Register a reactive effect. */\n effect: typeof effect\n /** Read signal values without dependency tracking. */\n untracked: typeof untracked\n}\n\n/**\n * Pre-bundled reference to all shared signals.\n *\n * @public\n */\nexport const signals: Signals = {\n blockedEvent,\n changes,\n consent,\n event,\n online,\n previewPanelAttached,\n previewPanelOpen,\n selectedOptimizations,\n canOptimize,\n profile,\n}\n\n/**\n * Pre-bundled reference to shared signal helpers.\n *\n * @public\n */\nexport const signalFns: SignalFns = {\n batch,\n computed,\n effect,\n untracked,\n}\n\nexport { batch, effect, type Signal }\n","import {\n type App,\n Campaign,\n type Channel,\n type ClickEvent,\n GeoLocation,\n type HoverEvent,\n type IdentifyEvent,\n type Library,\n Page,\n PageEventContext,\n type PageViewEvent,\n parseWithFriendlyError,\n Properties,\n Screen,\n ScreenEventContext,\n type ScreenViewEvent,\n type TrackEvent,\n Traits,\n type UniversalEventProperties,\n type ViewEvent,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { merge } from 'es-toolkit/object'\nimport * as z from 'zod/mini'\n\n/**\n * Configuration options for creating an {@link EventBuilder} instance.\n *\n * @remarks\n * The configuration is typically provided by the host application to adapt\n * event payloads to the runtime environment (browser, framework, etc.).\n *\n * @example\n * ```ts\n * const builder = new EventBuilder({\n * app: { name: 'my-app', version: '1.0.0' },\n * channel: 'web',\n * library: { name: '@contentful/optimization-sdk', version: '1.2.3' },\n * getLocale: () => navigator.language,\n * getPageProperties: () => ({\n * path: window.location.pathname,\n * url: window.location.href,\n * title: document.title,\n * query: {},\n * referrer: document.referrer,\n * search: window.location.search,\n * }),\n * })\n * ```\n *\n * @public\n */\nexport interface EventBuilderConfig {\n /**\n * The application definition used to attribute events to a specific consumer app.\n *\n * @remarks\n * When not provided, events will not contain app metadata in their context.\n */\n app?: App\n\n /**\n * The channel that identifies where events originate from (e.g. web, mobile).\n *\n * @see {@link Channel}\n */\n channel: Channel\n\n /**\n * The client library metadata that is attached to all events.\n *\n * @remarks\n * This is typically used to record the library name and version.\n */\n library: Library\n\n /**\n * Function used to resolve the locale for outgoing events.\n *\n * @remarks\n * If not provided, the builder falls back to the default `'en-US'`. Locale\n * values supplied directly as arguments to event builder methods take\n * precedence.\n *\n * @returns The locale string (e.g. `'en-US'`), or `undefined` if unavailable.\n */\n getLocale?: () => string | undefined\n\n /**\n * Function that returns the current page properties.\n *\n * @remarks\n * Page properties are currently added to the context of all events, as well\n * as the `properties` of the page event. When specified, all properties of\n * the `Page` type are required, but may contain empty values.\n *\n * @returns A {@link Page} object containing information about the current page.\n * @see {@link Page}\n */\n getPageProperties?: () => Page\n\n /**\n * Function used to obtain the current user agent string when applicable.\n *\n * @returns A user agent string, or `undefined` if unavailable.\n */\n getUserAgent?: () => string | undefined\n}\n\nexport const UniversalEventBuilderArgs = z.object({\n campaign: z.optional(Campaign),\n locale: z.optional(z.string()),\n location: z.optional(GeoLocation),\n page: z.optional(Page),\n screen: z.optional(Screen),\n userAgent: z.optional(z.string()),\n})\n\n/**\n * Arguments used to construct the universal (shared) portion of all events.\n *\n * @public\n */\nexport type UniversalEventBuilderArgs = z.infer<typeof UniversalEventBuilderArgs>\n\nexport const EntryInteractionBuilderArgsBase = z.extend(UniversalEventBuilderArgs, {\n componentId: z.string(),\n experienceId: z.optional(z.string()),\n variantIndex: z.optional(z.number()),\n})\n\n/**\n * Arguments shared by entry view, click, and hover events.\n *\n * @public\n */\nexport type EntryInteractionBuilderArgsBase = z.infer<typeof EntryInteractionBuilderArgsBase>\n\nexport const ViewBuilderArgs = z.extend(EntryInteractionBuilderArgsBase, {\n sticky: z.optional(z.boolean()),\n viewId: z.string(),\n viewDurationMs: z.number(),\n})\n\n/**\n * Arguments for constructing entry view events.\n *\n * @public\n */\nexport type ViewBuilderArgs = z.infer<typeof ViewBuilderArgs>\n\nexport const FlagViewBuilderArgs = z.extend(EntryInteractionBuilderArgsBase, {\n viewId: z.optional(z.string()),\n viewDurationMs: z.optional(z.number()),\n})\n\n/**\n * Arguments for constructing Custom Flag view events.\n *\n * @public\n */\nexport type FlagViewBuilderArgs = z.infer<typeof FlagViewBuilderArgs>\n\nexport const ClickBuilderArgs = EntryInteractionBuilderArgsBase\n\n/**\n * Arguments for constructing entry click events.\n *\n * @public\n */\nexport type ClickBuilderArgs = z.infer<typeof ClickBuilderArgs>\n\nexport const HoverBuilderArgs = z.extend(EntryInteractionBuilderArgsBase, {\n hoverId: z.string(),\n hoverDurationMs: z.number(),\n})\n\n/**\n * Arguments for constructing entry hover events.\n *\n * @public\n */\nexport type HoverBuilderArgs = z.infer<typeof HoverBuilderArgs>\n\nexport const IdentifyBuilderArgs = z.extend(UniversalEventBuilderArgs, {\n traits: z.optional(Traits),\n userId: z.string(),\n})\n\n/**\n * Arguments for constructing identify events.\n *\n * @remarks\n * Traits are merged by the API; only specified properties may be overwritten.\n *\n * @public\n */\nexport type IdentifyBuilderArgs = z.infer<typeof IdentifyBuilderArgs>\n\nexport const PageViewBuilderArgs = z.extend(UniversalEventBuilderArgs, {\n properties: z.optional(z.partial(Page)),\n})\n\n/**\n * Arguments for constructing page view events.\n *\n * @remarks\n * Any properties passed here are merged with the base page properties from\n * {@link EventBuilderConfig.getPageProperties}.\n *\n * @public\n */\nexport type PageViewBuilderArgs = z.infer<typeof PageViewBuilderArgs>\n\nexport const ScreenViewBuilderArgs = z.extend(UniversalEventBuilderArgs, {\n name: z.string(),\n properties: Properties,\n})\n\n/**\n * Arguments for constructing screen view events.\n *\n * @remarks\n * Any properties passed here are merged with the base screen properties supplied\n * by the runtime.\n *\n * @public\n */\nexport type ScreenViewBuilderArgs = z.infer<typeof ScreenViewBuilderArgs>\n\nexport const TrackBuilderArgs = z.extend(UniversalEventBuilderArgs, {\n event: z.string(),\n properties: z.optional(z.prefault(Properties, {})),\n})\n\n/**\n * Arguments for constructing track events.\n *\n * @public\n */\nexport type TrackBuilderArgs = z.infer<typeof TrackBuilderArgs>\n\n/**\n * Default page properties used when no explicit page information is available.\n *\n * @defaultValue\n * ```ts\n * {\n * path: '',\n * query: {},\n * referrer: '',\n * search: '',\n * title: '',\n * url: '',\n * }\n * ```\n *\n * @remarks\n * Values are required by the API; values may not be `undefined`. Empty values are valid.\n *\n * @public\n */\nexport const DEFAULT_PAGE_PROPERTIES = {\n path: '',\n query: {},\n referrer: '',\n search: '',\n title: '',\n url: '',\n}\n\n/**\n * Helper class for building optimization events.\n *\n * @remarks\n * This class coordinates configuration and argument validation to produce\n * strongly-typed event payloads compatible with\n * `@contentful/optimization-api-schemas`.\n *\n * @see {@link EventBuilderConfig}\n *\n * @public\n */\nclass EventBuilder {\n /**\n * Application metadata attached to each event.\n *\n * @internal\n */\n app?: App\n\n /**\n * Channel value attached to each event.\n *\n * @internal\n */\n channel: Channel\n\n /**\n * Library metadata attached to each event.\n *\n * @internal\n */\n library: Library\n\n /**\n * Function that provides the locale when available.\n *\n * @internal\n */\n getLocale: () => string | undefined\n\n /**\n * Function that provides baseline page properties.\n *\n * @internal\n */\n getPageProperties: () => Page\n\n /**\n * Function that provides the user agent string when available.\n *\n * @internal\n */\n getUserAgent: () => string | undefined\n\n /**\n * Creates a new {@link EventBuilder} instance.\n *\n * @param config - Configuration used to customize event payloads.\n *\n * @remarks\n * Callers are expected to reuse a single instance when possible to avoid\n * repeatedly reconfiguring the builder.\n *\n * @example\n * ```ts\n * const builder = new EventBuilder({\n * channel: 'web',\n * library: { name: '@contentful/optimization-sdk', version: '1.0.0' },\n * })\n * ```\n */\n constructor(config: EventBuilderConfig) {\n const { app, channel, library, getLocale, getPageProperties, getUserAgent } = config\n this.app = app\n this.channel = channel\n this.library = library\n this.getLocale = getLocale ?? (() => 'en-US')\n this.getPageProperties = getPageProperties ?? (() => DEFAULT_PAGE_PROPERTIES)\n this.getUserAgent = getUserAgent ?? (() => undefined)\n }\n\n /**\n * Builds the universal event properties shared across all event types.\n *\n * @param args - Arguments overriding the default context values.\n * @returns A fully populated {@link UniversalEventProperties} object.\n *\n * @remarks\n * This method is used internally by the specific event-builder methods\n * (e.g. {@link EventBuilder.buildPageView}).\n */\n protected buildUniversalEventProperties({\n campaign = {},\n locale,\n location,\n page,\n screen,\n userAgent,\n }: UniversalEventBuilderArgs): UniversalEventProperties {\n const timestamp = new Date().toISOString()\n\n return {\n channel: this.channel,\n context: {\n app: this.app,\n campaign,\n gdpr: { isConsentGiven: true },\n library: this.library,\n locale: locale ?? this.getLocale() ?? 'en-US',\n location,\n page: page ?? this.getPageProperties(),\n screen,\n userAgent: userAgent ?? this.getUserAgent(),\n },\n messageId: crypto.randomUUID(),\n originalTimestamp: timestamp,\n sentAt: timestamp,\n timestamp,\n }\n }\n\n private buildEntryInteractionBase(\n universal: UniversalEventBuilderArgs,\n componentId: string,\n experienceId: string | undefined,\n variantIndex: number | undefined,\n ): UniversalEventProperties & {\n componentType: 'Entry'\n componentId: string\n experienceId?: string\n variantIndex: number\n } {\n return {\n ...this.buildUniversalEventProperties(universal),\n componentType: 'Entry',\n componentId,\n experienceId,\n variantIndex: variantIndex ?? 0,\n }\n }\n\n /**\n * Builds a `component` view event payload for entry exposure tracking.\n *\n * @param args - {@link ViewBuilderArgs} arguments describing the entry view.\n * @returns A {@link ViewEvent} describing the view.\n *\n * @example\n * ```ts\n * const event = builder.buildView({\n * componentId: 'entry-123',\n * viewId: crypto.randomUUID(),\n * experienceId: 'experience-123',\n * variantIndex: 1,\n * viewDurationMs: 1_000,\n * })\n * ```\n *\n * @public\n */\n buildView(args: ViewBuilderArgs): ViewEvent {\n const { componentId, viewId, experienceId, variantIndex, viewDurationMs, ...universal } =\n parseWithFriendlyError(ViewBuilderArgs, args)\n\n return {\n ...this.buildEntryInteractionBase(universal, componentId, experienceId, variantIndex),\n type: 'component',\n viewId,\n viewDurationMs,\n }\n }\n\n /**\n * Builds a `component_click` payload for entry click tracking.\n *\n * @param args - {@link ClickBuilderArgs} arguments describing the entry click.\n * @returns A {@link ClickEvent} describing the click.\n *\n * @example\n * ```ts\n * const event = builder.buildClick({\n * componentId: 'entry-123',\n * experienceId: 'experience-123',\n * variantIndex: 1,\n * })\n * ```\n *\n * @public\n */\n buildClick(args: ClickBuilderArgs): ClickEvent {\n const { componentId, experienceId, variantIndex, ...universal } = parseWithFriendlyError(\n ClickBuilderArgs,\n args,\n )\n\n return {\n ...this.buildEntryInteractionBase(universal, componentId, experienceId, variantIndex),\n type: 'component_click',\n }\n }\n\n /**\n * Builds a `component_hover` payload for entry hover tracking.\n *\n * @param args - {@link HoverBuilderArgs} arguments describing the entry hover.\n * @returns A {@link HoverEvent} describing the hover.\n *\n * @example\n * ```ts\n * const event = builder.buildHover({\n * componentId: 'entry-123',\n * hoverId: crypto.randomUUID(),\n * experienceId: 'experience-123',\n * hoverDurationMs: 1_000,\n * variantIndex: 1,\n * })\n * ```\n *\n * @public\n */\n buildHover(args: HoverBuilderArgs): HoverEvent {\n const { hoverId, componentId, experienceId, hoverDurationMs, variantIndex, ...universal } =\n parseWithFriendlyError(HoverBuilderArgs, args)\n\n return {\n ...this.buildEntryInteractionBase(universal, componentId, experienceId, variantIndex),\n type: 'component_hover',\n hoverId,\n hoverDurationMs,\n }\n }\n\n /**\n * Builds a `component` view event payload for Custom Flag exposure tracking.\n *\n * @param args - {@link FlagViewBuilderArgs} arguments describing the Custom Flag view.\n * @returns A {@link ViewEvent} describing the view.\n *\n * @remarks\n * This is a specialized variant of {@link EventBuilder.buildView}\n * that sets `componentType` to `'Variable'`.\n *\n * @example\n * ```ts\n * const event = builder.buildFlagView({\n * componentId: 'feature-flag-key',\n * viewId: crypto.randomUUID(),\n * experienceId: 'experience-123',\n * viewDurationMs: 1_000,\n * })\n * ```\n *\n * @public\n */\n buildFlagView(args: FlagViewBuilderArgs): ViewEvent {\n const { componentId, experienceId, variantIndex, viewId, viewDurationMs, ...universal } =\n parseWithFriendlyError(FlagViewBuilderArgs, args)\n\n return {\n ...this.buildEntryInteractionBase(universal, componentId, experienceId, variantIndex),\n ...(viewDurationMs === undefined ? {} : { viewDurationMs }),\n ...(viewId === undefined ? {} : { viewId }),\n type: 'component',\n componentType: 'Variable',\n }\n }\n\n /**\n * Builds an identify event payload to associate a user ID with traits.\n *\n * @param args - {@link IdentifyBuilderArgs} arguments describing the identified user.\n * @returns An {@link IdentifyEvent} payload.\n *\n * @remarks\n * - Traits are merged by the API; only specified properties may be overwritten.\n * - The User ID is consumer-specified and should not contain the value of any\n * ID generated by the Experience API.\n *\n * @example\n * ```ts\n * const event = builder.buildIdentify({\n * userId: 'user-123',\n * traits: { plan: 'pro' },\n * })\n * ```\n *\n * @public\n */\n buildIdentify(args: IdentifyBuilderArgs): IdentifyEvent {\n const { traits = {}, userId, ...universal } = parseWithFriendlyError(IdentifyBuilderArgs, args)\n\n return {\n ...this.buildUniversalEventProperties(universal),\n type: 'identify',\n traits,\n userId,\n }\n }\n\n /**\n * Builds a page view event payload.\n *\n * @param args - Optional {@link PageViewBuilderArgs} overrides for the page view event.\n * @returns A {@link PageViewEvent} payload.\n *\n * @remarks\n * Page properties are created by merging:\n * 1. The base page properties from {@link EventBuilderConfig.getPageProperties}, and\n * 2. The partial `properties` argument passed in.\n *\n * The title always falls back to {@link DEFAULT_PAGE_PROPERTIES}.title when undefined.\n *\n * @example\n * ```ts\n * const event = builder.buildPageView({\n * properties: {\n * title: 'Homepage',\n * },\n * })\n * ```\n *\n * @public\n */\n buildPageView(args: PageViewBuilderArgs = {}): PageViewEvent {\n const { properties = {}, ...universal } = parseWithFriendlyError(PageViewBuilderArgs, args)\n\n const pageProperties = this.getPageProperties()\n\n const merged = merge(\n {\n ...pageProperties,\n title: pageProperties.title ?? DEFAULT_PAGE_PROPERTIES.title,\n },\n properties,\n )\n\n const {\n context: { screen: _, ...universalContext },\n ...universalProperties\n } = this.buildUniversalEventProperties(universal)\n\n const context = parseWithFriendlyError(PageEventContext, universalContext)\n\n return {\n ...universalProperties,\n context,\n type: 'page',\n properties: merged,\n }\n }\n\n /**\n * Builds a screen view event payload.\n *\n * @param args - {@link ScreenViewBuilderArgs} arguments for the screen view event.\n * @returns A {@link ScreenViewEvent} payload.\n *\n * @example\n * ```ts\n * const event = builder.buildScreenView({\n * name: 'home',\n * properties: {\n * title: 'Home Screen',\n * },\n * })\n * ```\n *\n * @public\n */\n buildScreenView(args: ScreenViewBuilderArgs): ScreenViewEvent {\n const { name, properties, ...universal } = parseWithFriendlyError(ScreenViewBuilderArgs, args)\n\n const {\n context: { page: _, ...universalContext },\n ...universalProperties\n } = this.buildUniversalEventProperties(universal)\n\n const context = parseWithFriendlyError(ScreenEventContext, universalContext)\n\n return {\n ...universalProperties,\n context,\n type: 'screen',\n name,\n properties,\n }\n }\n\n /**\n * Builds a track event payload for arbitrary user actions.\n *\n * @param args - {@link TrackBuilderArgs} arguments describing the tracked event.\n * @returns A {@link TrackEvent} payload.\n *\n * @example\n * ```ts\n * const event = builder.buildTrack({\n * event: 'button_clicked',\n * properties: { id: 'primary-cta', location: 'hero' },\n * })\n * ```\n *\n * @public\n */\n buildTrack(args: TrackBuilderArgs): TrackEvent {\n const { event, properties = {}, ...universal } = parseWithFriendlyError(TrackBuilderArgs, args)\n\n return {\n ...this.buildUniversalEventProperties(universal),\n type: 'track',\n event,\n properties,\n }\n }\n}\n\nexport default EventBuilder\n","import { cloneDeep } from 'es-toolkit'\n\n/**\n * A utility type representing a value that may be synchronously available or\n * produced asynchronously.\n *\n * @typeParam T - The resolved value type.\n * @public\n */\nexport type MaybePromise<T> = T | Promise<T>\n\n/**\n * A function that receives a value of type `T` and returns a (possibly async)\n * value of the same type `T`. The input is marked as `readonly` to discourage\n * mutation of the original object.\n *\n * @typeParam T - The value type intercepted and returned.\n * @param value - The current (readonly) value in the interception chain.\n * @returns The next value for the chain, either directly or via a promise.\n * @remarks Implementations SHOULD avoid mutating `value` and instead return a\n * new or safely-updated instance.\n * @see {@link InterceptorManager}\n * @public\n */\nexport type Interceptor<T> = (value: Readonly<T>) => MaybePromise<T>\n\n/**\n * Manages a list of interceptors and provides a way to run them in sequence.\n *\n * Interceptors are executed in insertion order. Each interceptor receives the\n * result of the previous interceptor (or the initial input for the first one)\n * and may return a new value synchronously or asynchronously.\n *\n * @typeParam T - The value type processed by the interceptors.\n * @remarks This class snapshots the current interceptor list at invocation time\n * so additions/removals during `run` do not affect the in-flight execution.\n * @example\n * ```ts\n * const mgr = new InterceptorManager<number>();\n * const id = mgr.add((n) => n + 1);\n * const final = await mgr.run(1); // 2\n * mgr.remove(id);\n * ```\n * @public\n */\nexport class InterceptorManager<T> {\n /**\n * The registry of interceptors keyed by their insertion id.\n *\n * @privateRemarks Internal storage; use {@link add}, {@link remove}, and\n * {@link clear} to manage contents.\n * @readonly\n * @defaultValue `new Map()`\n */\n private readonly interceptors = new Map<number, Interceptor<T>>()\n\n /**\n * The next numeric id to assign to an added interceptor.\n *\n * @privateRemarks Used only to generate unique, monotonically increasing ids.\n * @defaultValue `0`\n */\n private nextId = 0\n\n /**\n * Add an interceptor and return its identifier.\n *\n * @param interceptor - The interceptor function to register.\n * @returns The numeric id that can later be used with {@link remove}.\n * @remarks Interceptors are executed in the order they are added.\n * @example\n * ```ts\n * const id = manager.add(async (value) => transform(value));\n * ```\n * @public\n */\n add(interceptor: Interceptor<T>): number {\n const { nextId: id } = this\n this.nextId += 1\n this.interceptors.set(id, interceptor)\n return id\n }\n\n /**\n * Remove an interceptor by its identifier.\n *\n * @param id - The id previously returned by {@link add}.\n * @returns `true` if an interceptor was removed; otherwise `false`.\n * @example\n * ```ts\n * const removed = manager.remove(id);\n * ```\n * @public\n */\n remove(id: number): boolean {\n return this.interceptors.delete(id)\n }\n\n /**\n * Remove all registered interceptors.\n *\n * @returns Nothing.\n * @remarks After calling this, {@link count} will return `0`.\n * @example\n * ```ts\n * manager.clear();\n * ```\n * @public\n */\n clear(): void {\n this.interceptors.clear()\n }\n\n /**\n * Get the number of currently registered interceptors.\n *\n * @returns The count of interceptors.\n * @example\n * ```ts\n * if (manager.count() === 0) { /* ... *\\/ }\n * ```\n * @public\n */\n count(): number {\n return this.interceptors.size\n }\n\n /**\n * Run all interceptors in sequence on an input value and return the final result.\n *\n * Supports both sync and async interceptors; the return type is always `Promise<T>`\n * for consistency.\n *\n * @param input - The initial value to pass to the first interceptor.\n * @returns A promise resolving to the final value after all interceptors have run.\n * @throws May rethrow any error thrown by an interceptor. <!-- Intentionally vague: error type depends on interceptor implementation -->\n * @remarks The interceptor list is snapshotted at invocation time; changes to\n * the registry during execution do not affect the running sequence.\n * @example\n * ```ts\n * const result = await manager.run(initial);\n * ```\n * @public\n */\n async run(input: T): Promise<T> {\n // Snapshot to avoid issues if interceptors are added/removed during execution.\n const fns: ReadonlyArray<Interceptor<T>> = Array.from(this.interceptors.values())\n\n let acc: T = input\n\n for (const fn of fns) {\n // Pass a deep-cloned readonly view to prevent in-place interceptor\n // mutations from affecting references held outside the interceptor chain.\n acc = await fn(cloneDeep(acc))\n }\n\n return acc\n }\n}\n","import type { ChangeArray, Flags } from '@contentful/optimization-api-client/api-schemas'\n\n/**\n * Resolves a {@link Flags} map from a list of optimization changes.\n *\n * @public\n * @remarks\n * Given an Optimization {@link ChangeArray}, this utility flattens the list into a\n * simple key–value object suitable for quick lookups in client code. When `changes`\n * is `undefined`, an empty object is returned. If a change value is wrapped in an\n * object like `{ value: { ... } }`, this resolver unwraps it to the underlying object.\n */\nconst FlagsResolver = {\n /**\n * Build a flattened map of flag keys to values from a change list.\n *\n * @param changes - The change list returned by the optimization service.\n * @returns A map of flag keys to their resolved values.\n * @example\n * ```ts\n * const flags = FlagsResolver.resolve(data.changes)\n * if (flags['theme'] === 'dark') enableDarkMode()\n * ```\n * @example\n * // Handles wrapped values produced by the API\n * ```ts\n * const flags = FlagsResolver.resolve([\n * { type: 'Variable', key: 'price', value: { value: { amount: 10, currency: 'USD' } } }\n * ])\n * console.log(flags.price.amount) // 10\n * ```\n */\n resolve(changes?: ChangeArray): Flags {\n if (!changes) return {}\n\n return changes.reduce<Flags>((acc, { key, value }) => {\n const actualValue =\n typeof value === 'object' &&\n value !== null &&\n 'value' in value &&\n typeof value.value === 'object'\n ? value.value\n : value\n\n acc[key] = actualValue\n\n return acc\n }, {})\n },\n}\n\nexport default FlagsResolver\n","import type { MergeTagEntry } from '@contentful/optimization-api-client/api-schemas'\nimport { Profile, isMergeTagEntry } from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger } from '@contentful/optimization-api-client/logger'\n\nconst logger = createScopedLogger('Optimization')\n\n/**\n * Base string for log messages when merge-tag resolution fails.\n *\n * @internal\n */\nconst RESOLUTION_WARNING_BASE = 'Could not resolve Merge Tag value:'\n\nconst getAtPath = (value: unknown, path: string): unknown => {\n if (!value || typeof value !== 'object') return undefined\n if (!path) return value\n\n let current: unknown = value\n const segments = path.split('.').filter(Boolean)\n\n for (const segment of segments) {\n if (!current || (typeof current !== 'object' && typeof current !== 'function')) return undefined\n current = Reflect.get(current, segment)\n }\n\n return current\n}\n\n/**\n * Resolves merge tag values from a {@link Profile}.\n *\n * @public\n * @remarks\n * *Merge tags* are references to user profile data that may be embedded in content\n * and expanded at runtime. This resolver normalizes the merge-tag identifier into\n * a set of candidate selectors and searches the profile for a matching value.\n * Result values are returned as strings; numeric/boolean primitives are stringified.\n */\nconst MergeTagValueResolver = {\n /**\n * Generate a list of candidate selectors for a merge-tag ID.\n *\n * @param id - Merge-tag identifier (segments separated by `_`).\n * @returns Array of dot-path selectors to try against a profile.\n * @example\n * ```ts\n * // \"profile_name_first\" -> [\n * // 'profile',\n * // 'profile.name',\n * // 'profile.name.first'\n * // ]\n * const selectors = MergeTagValueResolver.normalizeSelectors('profile_name_first')\n * ```\n */\n normalizeSelectors(id: string): string[] {\n return id.split('_').map((_path, index, paths) => {\n const dotPath = paths.slice(0, index).join('.')\n const underScorePath = paths.slice(index).join('_')\n\n return [dotPath, underScorePath].filter((path) => path !== '').join('.')\n })\n },\n\n /**\n * Look up a merge-tag value from a profile using normalized selectors.\n *\n * @param id - Merge-tag identifier.\n * @param profile - Profile from which to resolve the value.\n * @returns A stringified primitive if found; otherwise `undefined`.\n * @remarks\n * Only string/number/boolean primitives are returned; objects/arrays are ignored.\n * @example\n * ```ts\n * const value = MergeTagValueResolver.getValueFromProfile('user_email', profile)\n * if (value) sendEmailTo(value)\n * ```\n */\n getValueFromProfile(id: string, profile?: Profile): string | undefined {\n const selectors = MergeTagValueResolver.normalizeSelectors(id)\n const matchingSelector = selectors.find((selector) => getAtPath(profile, selector))\n\n if (!matchingSelector) return undefined\n\n const value = getAtPath(profile, matchingSelector)\n\n if (\n !value ||\n (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean')\n )\n return undefined\n\n return `${value}`\n },\n\n /**\n * Resolve the display value for a merge-tag entry using the provided profile,\n * falling back to the entry's configured `nt_fallback` when necessary.\n *\n * @param mergeTagEntry - The merge-tag entry to resolve.\n * @param profile - Optional profile used for lookup.\n * @returns The resolved string, or `undefined` if the entry is invalid and no\n * fallback is available.\n * @example\n * ```ts\n * const text = MergeTagValueResolver.resolve(entry, profile)\n * render(text ?? 'Guest')\n * ```\n */\n resolve(mergeTagEntry: MergeTagEntry | undefined, profile?: Profile): string | undefined {\n if (!isMergeTagEntry(mergeTagEntry)) {\n logger.warn(`${RESOLUTION_WARNING_BASE} supplied entry is not a Merge Tag entry`)\n return\n }\n\n const {\n fields: { nt_fallback: fallback },\n } = mergeTagEntry\n\n if (!Profile.safeParse(profile).success) {\n logger.warn(`${RESOLUTION_WARNING_BASE} no valid profile`)\n return fallback\n }\n\n return (\n MergeTagValueResolver.getValueFromProfile(mergeTagEntry.fields.nt_mergetag_id, profile) ??\n fallback\n )\n },\n}\n\nexport default MergeTagValueResolver\n","import {\n type EntryReplacementComponent,\n type EntryReplacementVariant,\n isEntry,\n isEntryReplacementComponent,\n isEntryReplacementVariant,\n isOptimizationEntry,\n isOptimizedEntry,\n normalizeOptimizationConfig,\n type OptimizationEntry,\n type OptimizedEntry,\n type SelectedOptimization,\n type SelectedOptimizationArray,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger } from '@contentful/optimization-api-client/logger'\nimport type { ChainModifiers, Entry, EntrySkeletonType, LocaleCode } from 'contentful'\n\nconst logger = createScopedLogger('Optimization')\n\n/**\n * Result returned by {@link OptimizedEntryResolver.resolve}.\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam M - Chain modifiers.\n * @typeParam L - Locale code.\n * @public\n */\nexport interface ResolvedData<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n> {\n /** The baseline or resolved variant entry. */\n entry: Entry<S, M, L>\n /** The selected optimization metadata, if a non-baseline variant was chosen. */\n selectedOptimization?: SelectedOptimization\n}\n\n/**\n * Base string for resolver warning messages.\n *\n * @internal\n */\nconst RESOLUTION_WARNING_BASE = 'Could not resolve optimized entry variant:'\n\n/**\n * Resolve the selected entry (baseline or variant) for an optimized entry\n * and optional selected optimizations, returning both the entry and the\n * optimization metadata.\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam L - Locale code.\n * @typeParam M - Chain modifiers for advanced/non-default Contentful clients.\n * @param entry - The baseline optimized entry.\n * @param selectedOptimizations - Optional selections for the current profile.\n * @returns An object containing the resolved entry and (if chosen) the selection.\n * @example\n * ```ts\n * const { entry: optimizedEntry, selectedOptimization } = OptimizedEntryResolver.resolve(\n * entry,\n * selections,\n * )\n * if (selectedOptimization) {\n * console.log('Variant index', selectedOptimization.variantIndex)\n * }\n * ```\n */\nfunction resolve<\n S extends EntrySkeletonType = EntrySkeletonType,\n L extends LocaleCode = LocaleCode,\n>(\n entry: Entry<S, undefined, L>,\n selectedOptimizations?: SelectedOptimizationArray,\n): ResolvedData<S, undefined, L>\nfunction resolve<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n>(entry: Entry<S, M, L>, selectedOptimizations?: SelectedOptimizationArray): ResolvedData<S, M, L>\nfunction resolve<\n S extends EntrySkeletonType,\n M extends ChainModifiers,\n L extends LocaleCode = LocaleCode,\n>(entry: Entry<S, M, L>, selectedOptimizations?: SelectedOptimizationArray): ResolvedData<S, M, L> {\n logger.debug(`Resolving optimized entry for baseline entry ${entry.sys.id}`)\n\n if (!selectedOptimizations?.length) {\n logger.warn(`${RESOLUTION_WARNING_BASE} no selectedOptimizations exist for the current profile`)\n return { entry }\n }\n\n if (!isOptimizedEntry(entry)) {\n logger.warn(`${RESOLUTION_WARNING_BASE} entry ${entry.sys.id} is not optimized`)\n return { entry }\n }\n\n const optimizationEntry = OptimizedEntryResolver.getOptimizationEntry(\n {\n optimizedEntry: entry,\n selectedOptimizations,\n },\n true,\n )\n\n if (!optimizationEntry) {\n logger.warn(\n `${RESOLUTION_WARNING_BASE} could not find an optimization entry for ${entry.sys.id}`,\n )\n return { entry }\n }\n\n const selectedOptimization = OptimizedEntryResolver.getSelectedOptimization(\n {\n optimizationEntry,\n selectedOptimizations,\n },\n true,\n )\n\n const selectedVariantIndex = selectedOptimization?.variantIndex ?? 0\n\n if (selectedVariantIndex === 0) {\n logger.debug(`Resolved optimization entry for entry ${entry.sys.id} is baseline`)\n\n return { entry }\n }\n\n const selectedVariant = OptimizedEntryResolver.getSelectedVariant(\n {\n optimizedEntry: entry,\n optimizationEntry,\n selectedVariantIndex,\n },\n true,\n )\n\n if (!selectedVariant) {\n logger.warn(\n `${RESOLUTION_WARNING_BASE} could not find a valid replacement variant entry for ${entry.sys.id}`,\n )\n return { entry }\n }\n\n const selectedVariantEntry = OptimizedEntryResolver.getSelectedVariantEntry<S, M, L>(\n {\n optimizationEntry,\n selectedVariant,\n },\n true,\n )\n\n if (!selectedVariantEntry) {\n logger.warn(\n `${RESOLUTION_WARNING_BASE} could not find a valid replacement variant entry for ${entry.sys.id}`,\n )\n return { entry }\n } else {\n logger.debug(\n `Entry ${entry.sys.id} has been resolved to variant entry ${selectedVariantEntry.sys.id}`,\n )\n }\n\n return { entry: selectedVariantEntry, selectedOptimization }\n}\n\n/**\n * Resolve an optimized Contentful entry to the correct variant for the current\n * selections.\n *\n * @public\n * @remarks\n * Given a baseline {@link OptimizedEntry} and a set of selected optimizations\n * (variants per experience), this resolver finds the matching replacement variant\n * for the component configured against the baseline entry.\n *\n * **Variant indexing**: `variantIndex` in {@link SelectedOptimization} is treated as\n * 1‑based (index 1 = first variant). A value of `0` indicates baseline.\n */\nconst OptimizedEntryResolver = {\n /**\n * Find the optimization entry corresponding to one of the selected experiences.\n *\n * @param params - Object containing the baseline optimized entry and the selections.\n * @param skipValidation - When `true`, skip type/shape validation for perf.\n * @returns The matching {@link OptimizationEntry}, or `undefined` if not found/invalid.\n * @remarks\n * An optimization entry is an optimization configuration object supplied in an\n * `OptimizedEntry.nt_experiences` array. An optimized entry may relate to\n * multiple optimizations.\n * @example\n * ```ts\n * const optimizationEntry = OptimizedEntryResolver.getOptimizationEntry({\n * optimizedEntry: entry,\n * selectedOptimizations\n * })\n * ```\n */\n getOptimizationEntry(\n {\n optimizedEntry,\n selectedOptimizations,\n }: {\n optimizedEntry: OptimizedEntry\n selectedOptimizations: SelectedOptimizationArray\n },\n skipValidation = false,\n ): OptimizationEntry | undefined {\n if (!skipValidation && (!selectedOptimizations.length || !isOptimizedEntry(optimizedEntry)))\n return\n\n const optimizationEntry = optimizedEntry.fields.nt_experiences\n .filter((maybeOptimization) => isOptimizationEntry(maybeOptimization))\n .find((optimizationEntry) =>\n selectedOptimizations.some(\n ({ experienceId }) => experienceId === optimizationEntry.fields.nt_experience_id,\n ),\n )\n\n return optimizationEntry\n },\n\n /**\n * Look up the selection metadata for a specific optimization entry.\n *\n * @param params - Object with the target optimization entry and selections.\n * @param skipValidation - When `true`, skip type checks.\n * @returns The matching {@link SelectedOptimization}, if present.\n * @remarks\n * Selected optimizations are supplied by the Experience API in the\n * `experiences` response data property.\n * @example\n * ```ts\n * const selectedOptimization = OptimizedEntryResolver.getSelectedOptimization({\n * optimizationEntry,\n * selectedOptimizations\n * })\n * ```\n */\n getSelectedOptimization(\n {\n optimizationEntry,\n selectedOptimizations,\n }: {\n optimizationEntry: OptimizationEntry\n selectedOptimizations: SelectedOptimizationArray\n },\n skipValidation = false,\n ): SelectedOptimization | undefined {\n if (\n !skipValidation &&\n (!selectedOptimizations.length || !isOptimizationEntry(optimizationEntry))\n )\n return\n\n const selectedOptimization = selectedOptimizations.find(\n ({ experienceId }) => experienceId === optimizationEntry.fields.nt_experience_id,\n )\n\n return selectedOptimization\n },\n\n /**\n * Get the replacement variant config for the given selection index.\n *\n * @param params - Baseline entry, optimization entry, and 1‑based variant index.\n * @param skipValidation - When `true`, skip type checks.\n * @returns The {@link EntryReplacementVariant} for the component, if any.\n * @remarks\n * Entry replacement variants are variant configurations specified in a\n * optimization configuration component's `variants` array supplied by the\n * optimized entry via its `nt_config` field.\n * @example\n * ```ts\n * const selectedVariant = OptimizedEntryResolver.getSelectedVariant({\n * optimizedEntry: entry,\n * optimizationEntry,\n * selectedVariantIndex: 2 // second variant (1‑based)\n * })\n * ```\n */\n getSelectedVariant(\n {\n optimizedEntry,\n optimizationEntry,\n selectedVariantIndex,\n }: {\n optimizedEntry: OptimizedEntry\n optimizationEntry: OptimizationEntry\n selectedVariantIndex: number\n },\n skipValidation = false,\n ): EntryReplacementVariant | undefined {\n if (\n !skipValidation &&\n (!isOptimizedEntry(optimizedEntry) || !isOptimizationEntry(optimizationEntry))\n )\n return\n\n const relevantVariants = normalizeOptimizationConfig(optimizationEntry.fields.nt_config)\n .components.filter(\n (component): component is EntryReplacementComponent =>\n isEntryReplacementComponent(component) && !component.baseline.hidden,\n )\n .find((component) => component.baseline.id === optimizedEntry.sys.id)?.variants\n\n if (!relevantVariants?.length) return\n\n return relevantVariants.at(selectedVariantIndex - 1)\n },\n\n /**\n * Resolve the concrete Contentful entry that corresponds to a selected variant.\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam M - Chain modifiers.\n * @typeParam L - Locale code.\n * @param params - Optimization entry and selected variant.\n * @param skipValidation - When `true`, skip type checks.\n * @returns The resolved entry typed as {@link Entry} or `undefined`.\n * @remarks\n * An optimized entry will resolve either to the baseline (the entry\n * supplied as `optimizedEntry`) or the selected variant.\n * @example\n * ```ts\n * const selectedVariantEntry = OptimizedEntryResolver.getSelectedVariantEntry<{ fields: unknown }>({\n * optimizationEntry,\n * selectedVariant\n * })\n * ```\n */\n getSelectedVariantEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(\n {\n optimizationEntry,\n selectedVariant,\n }: {\n optimizationEntry: OptimizationEntry\n selectedVariant: EntryReplacementVariant\n },\n skipValidation = false,\n ): Entry<S, M, L> | undefined {\n if (\n !skipValidation &&\n (!isOptimizationEntry(optimizationEntry) || !isEntryReplacementVariant(selectedVariant))\n )\n return\n\n const selectedVariantEntry = optimizationEntry.fields.nt_variants?.find(\n (variant) => variant.sys.id === selectedVariant.id,\n )\n\n return isEntry<S, M, L>(selectedVariantEntry) ? selectedVariantEntry : undefined\n },\n\n resolve,\n}\n\nexport default OptimizedEntryResolver\n","import {\n ApiClient,\n type ApiClientConfig,\n type GlobalApiConfigProperties,\n} from '@contentful/optimization-api-client'\nimport type {\n ChangeArray,\n ExperienceEvent as ExperienceEventPayload,\n InsightsEvent as InsightsEventPayload,\n Json,\n MergeTagEntry,\n OptimizationData,\n Profile,\n SelectedOptimizationArray,\n} from '@contentful/optimization-api-client/api-schemas'\nimport type { LogLevels } from '@contentful/optimization-api-client/logger'\nimport { ConsoleLogSink, logger } from '@contentful/optimization-api-client/logger'\nimport type { ChainModifiers, Entry, EntrySkeletonType, LocaleCode } from 'contentful'\nimport { OPTIMIZATION_CORE_SDK_NAME, OPTIMIZATION_CORE_SDK_VERSION } from './constants'\nimport { EventBuilder, type EventBuilderConfig } from './events'\nimport { InterceptorManager } from './lib/interceptor'\nimport type { ResolvedData } from './resolvers'\nimport { FlagsResolver, MergeTagValueResolver, OptimizedEntryResolver } from './resolvers'\n\n/**\n * Lifecycle container for event and state interceptors.\n *\n * @public\n */\nexport interface LifecycleInterceptors {\n /** Interceptors invoked for individual events prior to validation/sending. */\n event: InterceptorManager<InsightsEventPayload | ExperienceEventPayload>\n /** Interceptors invoked before optimization state updates. */\n state: InterceptorManager<OptimizationData>\n}\n\n/**\n * Options for configuring the `CoreBase` runtime and underlying clients.\n *\n * @public\n */\nexport interface CoreConfig extends Pick<ApiClientConfig, GlobalApiConfigProperties> {\n /**\n * Event builder configuration (channel/library metadata, etc.).\n */\n eventBuilder?: EventBuilderConfig\n\n /** Minimum log level for the default console sink. */\n logLevel?: LogLevels\n}\n\ninterface CoreBaseApiClientConfig {\n experience?: ApiClientConfig['experience']\n insights?: ApiClientConfig['insights']\n}\n\n/**\n * Internal base that wires the API client, event builder, and logging.\n *\n * @internal\n */\nabstract class CoreBase<TConfig extends CoreConfig = CoreConfig> {\n /** Shared Optimization API client instance. */\n readonly api: ApiClient\n /** Shared event builder instance. */\n readonly eventBuilder: EventBuilder\n /** Resolved core configuration. */\n readonly config: TConfig\n /** Static resolver for evaluating optimized custom flags. */\n readonly flagsResolver = FlagsResolver\n /** Static resolver for merge-tag lookups against profile data. */\n readonly mergeTagValueResolver = MergeTagValueResolver\n /** Static resolver for optimized Contentful entries. */\n readonly optimizedEntryResolver = OptimizedEntryResolver\n\n /** Lifecycle interceptors for events and state updates. */\n readonly interceptors: LifecycleInterceptors = {\n event: new InterceptorManager<InsightsEventPayload | ExperienceEventPayload>(),\n state: new InterceptorManager<OptimizationData>(),\n }\n\n /**\n * Create the core with API client and logging preconfigured.\n *\n * @param config - Core configuration including API and builder options.\n * @example\n * ```ts\n * const sdk = new CoreStateless({ clientId: 'abc123', environment: 'prod' })\n * ```\n */\n constructor(config: TConfig, api: CoreBaseApiClientConfig = {}) {\n this.config = config\n\n const { eventBuilder, logLevel, environment, clientId, fetchOptions } = config\n\n logger.addSink(new ConsoleLogSink(logLevel))\n\n const apiConfig: ApiClientConfig = {\n clientId,\n environment,\n fetchOptions,\n experience: api.experience,\n insights: api.insights,\n }\n\n this.api = new ApiClient(apiConfig)\n\n this.eventBuilder = new EventBuilder(\n eventBuilder ?? {\n channel: 'server',\n library: { name: OPTIMIZATION_CORE_SDK_NAME, version: OPTIMIZATION_CORE_SDK_VERSION },\n },\n )\n }\n\n /**\n * Get the value of a custom flag derived from a set of optimization changes.\n *\n * @param name - The flag key to resolve.\n * @param changes - Optional change list to resolve from.\n * @returns The resolved JSON value for the flag if available.\n * @remarks\n * This is a convenience wrapper around Core's shared flag resolution.\n * @example\n * ```ts\n * const darkMode = core.getFlag('dark-mode', data.changes)\n * ```\n */\n getFlag(name: string, changes?: ChangeArray): Json {\n return this.flagsResolver.resolve(changes)[name]\n }\n\n /**\n * Resolve a Contentful entry to the appropriate optimized variant (or\n * return the baseline entry if no matching variant is selected).\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam M - Chain modifiers.\n * @typeParam L - Locale code.\n * @param entry - The baseline entry to resolve.\n * @param selectedOptimizations - Optional selected optimization array for the current profile.\n * @returns {@link ResolvedData} containing the resolved entry and\n * selected optimization metadata (if any).\n * @example\n * ```ts\n * const { entry, selectedOptimization } = core.resolveOptimizedEntry(\n * baselineEntry,\n * data.selectedOptimizations,\n * )\n * ```\n */\n resolveOptimizedEntry<\n S extends EntrySkeletonType = EntrySkeletonType,\n L extends LocaleCode = LocaleCode,\n >(\n entry: Entry<S, undefined, L>,\n selectedOptimizations?: SelectedOptimizationArray,\n ): ResolvedData<S, undefined, L>\n resolveOptimizedEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(entry: Entry<S, M, L>, selectedOptimizations?: SelectedOptimizationArray): ResolvedData<S, M, L>\n resolveOptimizedEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(\n entry: Entry<S, M, L>,\n selectedOptimizations?: SelectedOptimizationArray,\n ): ResolvedData<S, M, L> {\n return this.optimizedEntryResolver.resolve<S, M, L>(entry, selectedOptimizations)\n }\n\n /**\n * Resolve a merge-tag value from the given entry node and profile.\n *\n * @param embeddedEntryNodeTarget - The merge-tag entry node to resolve.\n * @param profile - Optional profile used for value lookup.\n * @returns The resolved value (typically a string) or `undefined` if not found.\n * @example\n * ```ts\n * const name = core.getMergeTagValue(mergeTagNode, profile)\n * ```\n */\n getMergeTagValue(embeddedEntryNodeTarget: MergeTagEntry, profile?: Profile): string | undefined {\n return this.mergeTagValueResolver.resolve(embeddedEntryNodeTarget, profile)\n }\n}\n\nexport default CoreBase\n","import type {\n ChangeArray,\n ExperienceEvent as ExperienceEventPayload,\n InsightsEvent as InsightsEventPayload,\n Json,\n MergeTagEntry,\n OptimizationData,\n PartialProfile,\n Profile,\n SelectedOptimizationArray,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger, logger } from '@contentful/optimization-api-client/logger'\nimport type { ChainModifiers, Entry, EntrySkeletonType, LocaleCode } from 'contentful'\nimport { isEqual } from 'es-toolkit/predicate'\nimport type { BlockedEvent } from './BlockedEvent'\nimport type { ConsentGuard } from './Consent'\nimport CoreBase from './CoreBase'\nimport type { CoreStatefulConfig, EventType } from './CoreStateful'\nimport type {\n ClickBuilderArgs,\n FlagViewBuilderArgs,\n HoverBuilderArgs,\n IdentifyBuilderArgs,\n PageViewBuilderArgs,\n ScreenViewBuilderArgs,\n TrackBuilderArgs,\n ViewBuilderArgs,\n} from './events'\nimport type { ExperienceQueue } from './queues/ExperienceQueue'\nimport type { InsightsQueue } from './queues/InsightsQueue'\nimport type { ResolvedData } from './resolvers'\nimport {\n blockedEvent as blockedEventSignal,\n changes as changesSignal,\n consent as consentSignal,\n type Observable,\n profile as profileSignal,\n selectedOptimizations as selectedOptimizationsSignal,\n signalFns,\n toDistinctObservable,\n} from './signals'\n\nconst coreLogger = createScopedLogger('CoreStateful')\n\nconst CONSENT_EVENT_TYPE_MAP: Readonly<Partial<Record<string, EventType>>> = {\n trackView: 'component',\n trackFlagView: 'component',\n trackClick: 'component_click',\n trackHover: 'component_hover',\n}\n\n/**\n * Shared stateful event-emission surface extracted to keep `CoreStateful.ts`\n * below the local max-lines limit while preserving the public API.\n *\n * @internal\n */\nabstract class CoreStatefulEventEmitter\n extends CoreBase<CoreStatefulConfig>\n implements ConsentGuard\n{\n protected readonly flagObservables = new Map<string, Observable<Json>>()\n\n protected abstract readonly allowedEventTypes: EventType[]\n protected abstract readonly experienceQueue: ExperienceQueue\n protected abstract readonly insightsQueue: InsightsQueue\n protected abstract readonly onEventBlocked?: CoreStatefulConfig['onEventBlocked']\n\n override getFlag(name: string, changes: ChangeArray | undefined = changesSignal.value): Json {\n const value = super.getFlag(name, changes)\n const payload = this.buildFlagViewBuilderArgs(name, changes)\n\n void this.trackFlagView(payload).catch((error: unknown) => {\n logger.warn(`Failed to emit \"flag view\" event for \"${name}\"`, String(error))\n })\n\n return value\n }\n\n override resolveOptimizedEntry<\n S extends EntrySkeletonType = EntrySkeletonType,\n L extends LocaleCode = LocaleCode,\n >(\n entry: Entry<S, undefined, L>,\n selectedOptimizations?: SelectedOptimizationArray,\n ): ResolvedData<S, undefined, L>\n override resolveOptimizedEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(entry: Entry<S, M, L>, selectedOptimizations?: SelectedOptimizationArray): ResolvedData<S, M, L>\n override resolveOptimizedEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(\n entry: Entry<S, M, L>,\n selectedOptimizations:\n | SelectedOptimizationArray\n | undefined = selectedOptimizationsSignal.value,\n ): ResolvedData<S, M, L> {\n return super.resolveOptimizedEntry(entry, selectedOptimizations)\n }\n\n override getMergeTagValue(\n embeddedEntryNodeTarget: MergeTagEntry,\n profile: Profile | undefined = profileSignal.value,\n ): string | undefined {\n return super.getMergeTagValue(embeddedEntryNodeTarget, profile)\n }\n\n /**\n * Convenience wrapper for sending an `identify` event through the Experience path.\n *\n * @param payload - Identify builder arguments.\n * @returns The resulting {@link OptimizationData} for the identified user.\n * @example\n * ```ts\n * const data = await core.identify({ userId: 'user-123', traits: { plan: 'pro' } })\n * ```\n */\n async identify(\n payload: IdentifyBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData | undefined> {\n const { profile, ...builderArgs } = payload\n return await this.sendExperienceEvent(\n 'identify',\n [payload],\n this.eventBuilder.buildIdentify(builderArgs),\n profile,\n )\n }\n\n /**\n * Convenience wrapper for sending a `page` event through the Experience path.\n *\n * @param payload - Page view builder arguments.\n * @returns The evaluated {@link OptimizationData} for this page view.\n * @example\n * ```ts\n * const data = await core.page({ properties: { title: 'Home' } })\n * ```\n */\n async page(\n payload: PageViewBuilderArgs & { profile?: PartialProfile } = {},\n ): Promise<OptimizationData | undefined> {\n const { profile, ...builderArgs } = payload\n return await this.sendExperienceEvent(\n 'page',\n [payload],\n this.eventBuilder.buildPageView(builderArgs),\n profile,\n )\n }\n\n /**\n * Convenience wrapper for sending a `screen` event through the Experience path.\n *\n * @param payload - Screen view builder arguments.\n * @returns The evaluated {@link OptimizationData} for this screen view.\n * @example\n * ```ts\n * const data = await core.screen({ name: 'HomeScreen' })\n * ```\n */\n async screen(\n payload: ScreenViewBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData | undefined> {\n const { profile, ...builderArgs } = payload\n return await this.sendExperienceEvent(\n 'screen',\n [payload],\n this.eventBuilder.buildScreenView(builderArgs),\n profile,\n )\n }\n\n /**\n * Convenience wrapper for sending a custom `track` event through the Experience path.\n *\n * @param payload - Track builder arguments.\n * @returns The evaluated {@link OptimizationData} for this event.\n * @example\n * ```ts\n * const data = await core.track({ event: 'button_click', properties: { label: 'Buy' } })\n * ```\n */\n async track(\n payload: TrackBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData | undefined> {\n const { profile, ...builderArgs } = payload\n return await this.sendExperienceEvent(\n 'track',\n [payload],\n this.eventBuilder.buildTrack(builderArgs),\n profile,\n )\n }\n\n /**\n * Track an entry view through Insights and, when sticky, Experience.\n *\n * @param payload - Entry view builder arguments. When `payload.sticky` is\n * `true`, the event will also be sent through Experience as a sticky\n * entry view.\n * @returns A promise that resolves when all delegated calls complete.\n * @remarks\n * Experience receives sticky entry views only; Insights is always invoked\n * regardless of `sticky`.\n * @example\n * ```ts\n * await core.trackView({ componentId: 'entry-123', sticky: true })\n * ```\n */\n async trackView(\n payload: ViewBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData | undefined> {\n const { profile, ...builderArgs } = payload\n let result: OptimizationData | undefined = undefined\n\n if (payload.sticky) {\n result = await this.sendExperienceEvent(\n 'trackView',\n [payload],\n this.eventBuilder.buildView(builderArgs),\n profile,\n )\n }\n await this.sendInsightsEvent(\n 'trackView',\n [payload],\n this.eventBuilder.buildView(builderArgs),\n profile,\n )\n\n return result\n }\n\n /**\n * Track an entry click through Insights.\n *\n * @param payload - Entry click builder arguments.\n * @returns A promise that resolves when processing completes.\n * @example\n * ```ts\n * await core.trackClick({ componentId: 'entry-123' })\n * ```\n */\n async trackClick(payload: ClickBuilderArgs): Promise<void> {\n await this.sendInsightsEvent('trackClick', [payload], this.eventBuilder.buildClick(payload))\n }\n\n /**\n * Track an entry hover through Insights.\n *\n * @param payload - Entry hover builder arguments.\n * @returns A promise that resolves when processing completes.\n * @example\n * ```ts\n * await core.trackHover({ componentId: 'entry-123' })\n * ```\n */\n async trackHover(payload: HoverBuilderArgs): Promise<void> {\n await this.sendInsightsEvent('trackHover', [payload], this.eventBuilder.buildHover(payload))\n }\n\n /**\n * Track a feature flag view through Insights.\n *\n * @param payload - Flag view builder arguments used to build the flag view event.\n * @returns A promise that resolves when processing completes.\n * @example\n * ```ts\n * await core.trackFlagView({ componentId: 'feature-flag-123' })\n * ```\n */\n async trackFlagView(payload: FlagViewBuilderArgs): Promise<void> {\n await this.sendInsightsEvent(\n 'trackFlagView',\n [payload],\n this.eventBuilder.buildFlagView(payload),\n )\n }\n\n hasConsent(name: string): boolean {\n const { [name]: mappedEventType } = CONSENT_EVENT_TYPE_MAP\n const isAllowed =\n mappedEventType !== undefined\n ? this.allowedEventTypes.includes(mappedEventType)\n : this.allowedEventTypes.some((eventType) => eventType === name)\n\n return !!consentSignal.value || isAllowed\n }\n\n onBlockedByConsent(name: string, args: readonly unknown[]): void {\n coreLogger.warn(\n `Event \"${name}\" was blocked due to lack of consent; payload: ${JSON.stringify(args)}`,\n )\n this.reportBlockedEvent('consent', name, args)\n }\n\n protected async sendExperienceEvent(\n method: string,\n args: readonly unknown[],\n event: ExperienceEventPayload,\n _profile?: PartialProfile,\n ): Promise<OptimizationData | undefined> {\n if (!this.hasConsent(method)) {\n this.onBlockedByConsent(method, args)\n return undefined\n }\n\n return await this.experienceQueue.send(event)\n }\n\n protected async sendInsightsEvent(\n method: string,\n args: readonly unknown[],\n event: InsightsEventPayload,\n _profile?: PartialProfile,\n ): Promise<void> {\n if (!this.hasConsent(method)) {\n this.onBlockedByConsent(method, args)\n return\n }\n\n await this.insightsQueue.send(event)\n }\n\n private buildFlagViewBuilderArgs(\n name: string,\n changes: ChangeArray | undefined = changesSignal.value,\n ): FlagViewBuilderArgs {\n const change = changes?.find((candidate) => candidate.key === name)\n\n return {\n componentId: name,\n experienceId: change?.meta.experienceId,\n variantIndex: change?.meta.variantIndex,\n }\n }\n\n protected getFlagObservable(name: string): Observable<Json> {\n const existingObservable = this.flagObservables.get(name)\n if (existingObservable) return existingObservable\n\n const trackFlagView = this.trackFlagView.bind(this)\n const buildFlagViewBuilderArgs = this.buildFlagViewBuilderArgs.bind(this)\n const valueSignal = signalFns.computed<Json>(() => super.getFlag(name, changesSignal.value))\n const distinctObservable = toDistinctObservable(valueSignal, isEqual)\n\n const trackedObservable: Observable<Json> = {\n get current() {\n const { current: value } = distinctObservable\n const payload = buildFlagViewBuilderArgs(name, changesSignal.value)\n\n void trackFlagView(payload).catch((error: unknown) => {\n logger.warn(`Failed to emit \"flag view\" event for \"${name}\"`, String(error))\n })\n\n return value\n },\n\n subscribe: (next) =>\n distinctObservable.subscribe((value) => {\n const payload = buildFlagViewBuilderArgs(name, changesSignal.value)\n\n void trackFlagView(payload).catch((error: unknown) => {\n logger.warn(`Failed to emit \"flag view\" event for \"${name}\"`, String(error))\n })\n next(value)\n }),\n\n subscribeOnce: (next) =>\n distinctObservable.subscribeOnce((value) => {\n const payload = buildFlagViewBuilderArgs(name, changesSignal.value)\n\n void trackFlagView(payload).catch((error: unknown) => {\n logger.warn(`Failed to emit \"flag view\" event for \"${name}\"`, String(error))\n })\n next(value)\n }),\n }\n\n this.flagObservables.set(name, trackedObservable)\n\n return trackedObservable\n }\n\n private reportBlockedEvent(\n reason: BlockedEvent['reason'],\n method: string,\n args: readonly unknown[],\n ): void {\n const event: BlockedEvent = { reason, method, args }\n\n try {\n this.onEventBlocked?.(event)\n } catch (error) {\n coreLogger.warn(`onEventBlocked callback failed for method \"${method}\"`, error)\n }\n\n blockedEventSignal.value = event\n }\n}\n\nexport default CoreStatefulEventEmitter\n","/**\n * Normalize a candidate positive integer value with fallback.\n *\n * @param value - Incoming numeric value.\n * @param fallback - Fallback when value is invalid.\n * @returns Normalized positive integer.\n *\n * @internal\n */\nexport const toPositiveInt = (value: number | undefined, fallback: number): number => {\n if (!Number.isFinite(value) || value === undefined || value < 1) return fallback\n\n return Math.floor(value)\n}\n\n/**\n * Normalize a candidate ratio to the `[0, 1]` interval.\n *\n * @param value - Incoming ratio value.\n * @param fallback - Fallback when value is invalid.\n * @returns Normalized ratio.\n *\n * @internal\n */\nexport const toRatio = (value: number | undefined, fallback: number): number => {\n if (!Number.isFinite(value) || value === undefined) return fallback\n\n return Math.min(1, Math.max(0, value))\n}\n","import { toPositiveInt, toRatio } from '../number'\n\n/**\n * Context payload emitted when a queue flush fails.\n *\n * @public\n */\nexport interface QueueFlushFailureContext {\n /** Number of consecutive failed flush attempts. */\n consecutiveFailures: number\n /** Number of queued batches at the time of the failed attempt. */\n queuedBatches: number\n /** Number of queued events at the time of the failed attempt. */\n queuedEvents: number\n /** Delay before the next retry attempt is scheduled. */\n retryDelayMs: number\n}\n\n/**\n * Context payload emitted when a failed queue flush sequence recovers.\n *\n * @public\n */\nexport interface QueueFlushRecoveredContext {\n /** Consecutive failure count that existed immediately before recovery. */\n consecutiveFailures: number\n}\n\n/**\n * Policy options for controlling queue flush retry behavior.\n *\n * @public\n */\nexport interface QueueFlushPolicy {\n /**\n * Periodic flush interval in milliseconds while events remain queued.\n *\n * @defaultValue `30000`\n */\n flushIntervalMs?: number\n\n /**\n * Base retry backoff delay in milliseconds.\n *\n * @defaultValue `500`\n */\n baseBackoffMs?: number\n\n /**\n * Maximum retry backoff delay in milliseconds.\n *\n * @defaultValue `30000`\n */\n maxBackoffMs?: number\n\n /**\n * Jitter ratio applied to retry delay to avoid synchronized retries.\n *\n * @remarks\n * Value is clamped to `[0, 1]`.\n *\n * @defaultValue `0.2`\n */\n jitterRatio?: number\n\n /**\n * Consecutive failures threshold before opening the circuit window.\n *\n * @defaultValue `8`\n */\n maxConsecutiveFailures?: number\n\n /**\n * Duration in milliseconds to wait before retrying after circuit opens.\n *\n * @defaultValue `120000`\n */\n circuitOpenMs?: number\n\n /**\n * Callback invoked after each failed flush attempt.\n */\n onFlushFailure?: (context: QueueFlushFailureContext) => void\n\n /**\n * Callback invoked when the circuit opens after consecutive failures.\n */\n onCircuitOpen?: (context: QueueFlushFailureContext) => void\n\n /**\n * Callback invoked when a flush succeeds after previous failures.\n */\n onFlushRecovered?: (context: QueueFlushRecoveredContext) => void\n}\n\ninterface QueueFlushDefaults {\n flushIntervalMs: number\n baseBackoffMs: number\n maxBackoffMs: number\n jitterRatio: number\n maxConsecutiveFailures: number\n circuitOpenMs: number\n}\n\n/**\n * Default queue flush policy values.\n *\n * @internal\n */\nexport const DEFAULT_QUEUE_FLUSH_POLICY: QueueFlushDefaults = {\n flushIntervalMs: 30_000,\n baseBackoffMs: 500,\n maxBackoffMs: 30_000,\n jitterRatio: 0.2,\n maxConsecutiveFailures: 8,\n circuitOpenMs: 120_000,\n}\n\n/**\n * Internal normalized shape of queue flush policy values.\n *\n * @internal\n */\nexport interface ResolvedQueueFlushPolicy {\n flushIntervalMs: number\n baseBackoffMs: number\n maxBackoffMs: number\n jitterRatio: number\n maxConsecutiveFailures: number\n circuitOpenMs: number\n onCircuitOpen?: QueueFlushPolicy['onCircuitOpen']\n onFlushFailure?: QueueFlushPolicy['onFlushFailure']\n onFlushRecovered?: QueueFlushPolicy['onFlushRecovered']\n}\n\n/**\n * Resolve and normalize queue flush policy values.\n *\n * @param policy - Candidate queue flush policy configuration.\n * @param defaults - Optional fallback defaults.\n * @returns Normalized queue flush policy.\n *\n * @internal\n */\nexport const resolveQueueFlushPolicy = (\n policy: QueueFlushPolicy | undefined,\n defaults: QueueFlushDefaults = DEFAULT_QUEUE_FLUSH_POLICY,\n): ResolvedQueueFlushPolicy => {\n const configuredPolicy: QueueFlushPolicy = policy ?? {}\n const baseBackoffMs = toPositiveInt(configuredPolicy.baseBackoffMs, defaults.baseBackoffMs)\n const maxBackoffMs = Math.max(\n baseBackoffMs,\n toPositiveInt(configuredPolicy.maxBackoffMs, defaults.maxBackoffMs),\n )\n\n return {\n flushIntervalMs: toPositiveInt(configuredPolicy.flushIntervalMs, defaults.flushIntervalMs),\n baseBackoffMs,\n maxBackoffMs,\n jitterRatio: toRatio(configuredPolicy.jitterRatio, defaults.jitterRatio),\n maxConsecutiveFailures: toPositiveInt(\n configuredPolicy.maxConsecutiveFailures,\n defaults.maxConsecutiveFailures,\n ),\n circuitOpenMs: toPositiveInt(configuredPolicy.circuitOpenMs, defaults.circuitOpenMs),\n onCircuitOpen: configuredPolicy.onCircuitOpen,\n onFlushFailure: configuredPolicy.onFlushFailure,\n onFlushRecovered: configuredPolicy.onFlushRecovered,\n }\n}\n\n/**\n * Compute retry delay in milliseconds using exponential backoff plus jitter.\n *\n * @param options - Retry delay inputs.\n * @returns Backoff delay in milliseconds.\n *\n * @internal\n */\nexport const computeQueueFlushRetryDelayMs = (options: {\n consecutiveFailures: number\n policy: Pick<ResolvedQueueFlushPolicy, 'baseBackoffMs' | 'maxBackoffMs' | 'jitterRatio'>\n}): number => {\n const {\n consecutiveFailures,\n policy: { baseBackoffMs, jitterRatio, maxBackoffMs },\n } = options\n const exponential = baseBackoffMs * 2 ** Math.max(0, consecutiveFailures - 1)\n const capped = Math.min(maxBackoffMs, exponential)\n const jitter = capped * jitterRatio * Math.random()\n\n return Math.round(capped + jitter)\n}\n\n/**\n * Derived retry scheduling state after a failed flush attempt.\n *\n * @internal\n */\nexport interface QueueFlushFailureWindow {\n openedCircuit: boolean\n retryDelayMs: number\n nextFlushAllowedAt: number\n circuitOpenUntil: number\n}\n\n/**\n * Create the next retry scheduling window from a failed flush attempt.\n *\n * @param options - Failure window inputs.\n * @returns Derived retry scheduling state.\n *\n * @internal\n */\nexport const createQueueFlushFailureWindow = (options: {\n consecutiveFailures: number\n failureTimestamp: number\n retryDelayMs: number\n policy: Pick<ResolvedQueueFlushPolicy, 'maxConsecutiveFailures' | 'circuitOpenMs'>\n}): QueueFlushFailureWindow => {\n const {\n consecutiveFailures,\n failureTimestamp,\n retryDelayMs,\n policy: { maxConsecutiveFailures, circuitOpenMs },\n } = options\n\n if (consecutiveFailures < maxConsecutiveFailures) {\n return {\n openedCircuit: false,\n retryDelayMs,\n nextFlushAllowedAt: failureTimestamp + retryDelayMs,\n circuitOpenUntil: 0,\n }\n }\n\n const circuitOpenUntil = failureTimestamp + circuitOpenMs\n\n return {\n openedCircuit: true,\n retryDelayMs: circuitOpenMs,\n nextFlushAllowedAt: circuitOpenUntil,\n circuitOpenUntil,\n }\n}\n","const STATEFUL_RUNTIME_LOCK_KEY = '__ctfl_optimization_stateful_runtime_lock__'\n\ninterface StatefulRuntimeLockState {\n owner: string | undefined\n}\n\ntype SingletonGlobal = typeof globalThis & {\n __ctfl_optimization_stateful_runtime_lock__?: StatefulRuntimeLockState\n}\n\nconst getStatefulRuntimeLock = (): StatefulRuntimeLockState => {\n const singletonGlobal = globalThis as SingletonGlobal\n\n singletonGlobal[STATEFUL_RUNTIME_LOCK_KEY] ??= { owner: undefined }\n\n return singletonGlobal[STATEFUL_RUNTIME_LOCK_KEY]\n}\n\nexport const acquireStatefulRuntimeSingleton = (owner: string): void => {\n const lock = getStatefulRuntimeLock()\n\n if (lock.owner) {\n throw new Error(\n `Stateful Optimization SDK already initialized (${lock.owner}). Only one stateful instance is supported per runtime.`,\n )\n }\n\n lock.owner = owner\n}\n\nexport const releaseStatefulRuntimeSingleton = (owner: string): void => {\n const lock = getStatefulRuntimeLock()\n\n if (lock.owner === owner) {\n lock.owner = undefined\n }\n}\n","import {\n computeQueueFlushRetryDelayMs,\n createQueueFlushFailureWindow,\n type QueueFlushFailureContext,\n type QueueFlushRecoveredContext,\n type ResolvedQueueFlushPolicy,\n} from './flushPolicy'\n\n/**\n * Callback names for queue flush policy hooks.\n *\n * @internal\n */\nexport type QueueFlushCallbackName = 'onCircuitOpen' | 'onFlushFailure' | 'onFlushRecovered'\n\n/**\n * Construction options for {@link QueueFlushRuntime}.\n *\n * @internal\n */\ninterface QueueFlushRuntimeOptions {\n onCallbackError?: (callbackName: QueueFlushCallbackName, error: unknown) => void\n onRetry: () => void\n policy: ResolvedQueueFlushPolicy\n}\n\n/**\n * Shared runtime state machine for queue flush retry, backoff, and circuit behavior.\n *\n * @internal\n */\nexport class QueueFlushRuntime {\n private circuitOpenUntil = 0\n private flushFailureCount = 0\n private flushInFlight = false\n private nextFlushAllowedAt = 0\n private readonly onCallbackError?: QueueFlushRuntimeOptions['onCallbackError']\n private readonly onRetry: QueueFlushRuntimeOptions['onRetry']\n private readonly policy: QueueFlushRuntimeOptions['policy']\n private retryTimer: ReturnType<typeof setTimeout> | undefined\n\n constructor(options: QueueFlushRuntimeOptions) {\n const { onCallbackError, onRetry, policy } = options\n\n this.policy = policy\n this.onRetry = onRetry\n this.onCallbackError = onCallbackError\n }\n\n /**\n * Reset runtime state and clear any scheduled retry.\n */\n reset(): void {\n this.clearScheduledRetry()\n\n this.circuitOpenUntil = 0\n this.flushFailureCount = 0\n this.flushInFlight = false\n this.nextFlushAllowedAt = 0\n }\n\n /**\n * Clear the currently scheduled retry timer, if any.\n */\n clearScheduledRetry(): void {\n if (this.retryTimer === undefined) return\n\n clearTimeout(this.retryTimer)\n this.retryTimer = undefined\n }\n\n /**\n * Determine whether flush should be skipped due to current state gates.\n *\n * @param options - Flush gate options.\n * @param options.force - When true, bypass online/backoff/circuit gates.\n * @param options.isOnline - Whether connectivity gates permit flushing.\n * @returns `true` when flush should be skipped.\n */\n shouldSkip(options: { force: boolean; isOnline: boolean }): boolean {\n const { force, isOnline } = options\n\n if (this.flushInFlight) return true\n if (force) return false\n if (!isOnline) return true\n\n const now = Date.now()\n\n if (this.nextFlushAllowedAt > now) return true\n if (this.circuitOpenUntil > now) return true\n\n return false\n }\n\n /**\n * Mark a flush attempt as in flight.\n */\n markFlushStarted(): void {\n this.flushInFlight = true\n }\n\n /**\n * Mark a flush attempt as finished.\n */\n markFlushFinished(): void {\n this.flushInFlight = false\n }\n\n /**\n * Apply successful flush state transitions and invoke recovery callback as needed.\n */\n handleFlushSuccess(): void {\n const { flushFailureCount: previousConsecutiveFailures } = this\n\n this.clearScheduledRetry()\n\n this.circuitOpenUntil = 0\n this.flushFailureCount = 0\n this.nextFlushAllowedAt = 0\n\n if (previousConsecutiveFailures <= 0) return\n\n this.safeInvoke('onFlushRecovered', {\n consecutiveFailures: previousConsecutiveFailures,\n })\n }\n\n /**\n * Apply failed flush state transitions, invoke callbacks, and schedule retry.\n *\n * @param options - Failure inputs.\n * @param options.queuedBatches - Number of failed queued batches.\n * @param options.queuedEvents - Number of failed queued events.\n */\n handleFlushFailure(options: { queuedBatches: number; queuedEvents: number }): void {\n const { queuedBatches, queuedEvents } = options\n\n this.flushFailureCount += 1\n\n const retryDelayMs = computeQueueFlushRetryDelayMs({\n consecutiveFailures: this.flushFailureCount,\n policy: this.policy,\n })\n const failureTimestamp = Date.now()\n const failureContext: QueueFlushFailureContext = {\n consecutiveFailures: this.flushFailureCount,\n queuedBatches,\n queuedEvents,\n retryDelayMs,\n }\n\n this.safeInvoke('onFlushFailure', failureContext)\n\n const failureWindow = createQueueFlushFailureWindow({\n consecutiveFailures: this.flushFailureCount,\n failureTimestamp,\n retryDelayMs,\n policy: this.policy,\n })\n const {\n circuitOpenUntil,\n nextFlushAllowedAt,\n openedCircuit,\n retryDelayMs: scheduledRetryDelayMs,\n } = failureWindow\n\n this.nextFlushAllowedAt = nextFlushAllowedAt\n\n if (openedCircuit) {\n this.circuitOpenUntil = circuitOpenUntil\n this.safeInvoke('onCircuitOpen', {\n ...failureContext,\n retryDelayMs: scheduledRetryDelayMs,\n })\n }\n\n this.scheduleRetry(scheduledRetryDelayMs)\n }\n\n /**\n * Schedule a future flush attempt.\n *\n * @param delayMs - Delay in milliseconds before next attempt.\n */\n private scheduleRetry(delayMs: number): void {\n this.clearScheduledRetry()\n\n this.retryTimer = setTimeout(() => {\n this.retryTimer = undefined\n this.onRetry()\n }, delayMs)\n }\n\n /**\n * Invoke a policy callback in a fault-tolerant manner.\n *\n * @param callbackName - Callback key.\n * @param payload - Callback payload.\n */\n private safeInvoke(\n ...args:\n | ['onFlushRecovered', QueueFlushRecoveredContext]\n | ['onCircuitOpen' | 'onFlushFailure', QueueFlushFailureContext]\n ): void {\n const [callbackName, payload] = args\n\n try {\n if (callbackName === 'onFlushRecovered') {\n this.policy.onFlushRecovered?.(payload)\n return\n }\n\n if (callbackName === 'onCircuitOpen') {\n this.policy.onCircuitOpen?.(payload)\n return\n }\n\n this.policy.onFlushFailure?.(payload)\n } catch (error) {\n this.onCallbackError?.(callbackName, error)\n }\n }\n}\n","import {\n ExperienceEvent as ExperienceEventSchema,\n parseWithFriendlyError,\n type ExperienceEventArray,\n type ExperienceEvent as ExperienceEventPayload,\n type OptimizationData,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger } from '@contentful/optimization-api-client/logger'\nimport { isEqual } from 'es-toolkit/predicate'\nimport type { LifecycleInterceptors } from '../CoreBase'\nimport { QueueFlushRuntime, type ResolvedQueueFlushPolicy } from '../lib/queue'\nimport {\n batch,\n changes as changesSignal,\n event as eventSignal,\n online as onlineSignal,\n profile as profileSignal,\n selectedOptimizations as selectedOptimizationsSignal,\n} from '../signals'\n\nconst coreLogger = createScopedLogger('CoreStateful')\n\n/**\n * Context payload emitted when offline Experience events are dropped.\n *\n * @public\n */\nexport interface ExperienceQueueDropContext {\n /** Number of dropped events. */\n droppedCount: number\n /** Dropped events in oldest-first order. */\n droppedEvents: ExperienceEventArray\n /** Configured queue max size. */\n maxEvents: number\n /** Queue size after enqueueing the current event. */\n queuedEvents: number\n}\n\ninterface ExperienceQueueOptions {\n experienceApi: {\n upsertProfile: (payload: {\n profileId?: string\n events: ExperienceEventArray\n }) => Promise<OptimizationData>\n }\n eventInterceptors: LifecycleInterceptors['event']\n flushPolicy: ResolvedQueueFlushPolicy\n getAnonymousId: () => string | undefined\n offlineMaxEvents: number\n onOfflineDrop?: (context: ExperienceQueueDropContext) => void\n stateInterceptors: LifecycleInterceptors['state']\n}\n\n/**\n * Internal Experience send/offline runtime used by {@link CoreStateful}.\n *\n * @internal\n */\nexport class ExperienceQueue {\n private readonly experienceApi: ExperienceQueueOptions['experienceApi']\n private readonly eventInterceptors: ExperienceQueueOptions['eventInterceptors']\n private readonly flushRuntime: QueueFlushRuntime\n private readonly getAnonymousId: ExperienceQueueOptions['getAnonymousId']\n private readonly offlineMaxEvents: number\n private readonly onOfflineDrop?: ExperienceQueueOptions['onOfflineDrop']\n private readonly queuedExperienceEvents = new Set<ExperienceEventPayload>()\n private readonly stateInterceptors: ExperienceQueueOptions['stateInterceptors']\n\n constructor(options: ExperienceQueueOptions) {\n const {\n experienceApi,\n eventInterceptors,\n flushPolicy,\n getAnonymousId,\n offlineMaxEvents,\n onOfflineDrop,\n stateInterceptors,\n } = options\n\n this.experienceApi = experienceApi\n this.eventInterceptors = eventInterceptors\n this.getAnonymousId = getAnonymousId\n this.offlineMaxEvents = offlineMaxEvents\n this.onOfflineDrop = onOfflineDrop\n this.stateInterceptors = stateInterceptors\n this.flushRuntime = new QueueFlushRuntime({\n policy: flushPolicy,\n onRetry: () => {\n void this.flush()\n },\n onCallbackError: (callbackName, error) => {\n coreLogger.warn(`Experience flush policy callback \"${callbackName}\" failed`, error)\n },\n })\n }\n\n clearScheduledRetry(): void {\n this.flushRuntime.clearScheduledRetry()\n }\n\n async send(event: ExperienceEventPayload): Promise<OptimizationData | undefined> {\n const intercepted = await this.eventInterceptors.run(event)\n const validEvent = parseWithFriendlyError(ExperienceEventSchema, intercepted)\n\n eventSignal.value = validEvent\n\n if (onlineSignal.value) return await this.upsertProfile([validEvent])\n\n coreLogger.debug(`Queueing ${validEvent.type} event`, validEvent)\n this.enqueueEvent(validEvent)\n\n return undefined\n }\n\n async flush(options: { force?: boolean } = {}): Promise<void> {\n const { force = false } = options\n\n if (this.flushRuntime.shouldSkip({ force, isOnline: !!onlineSignal.value })) return\n\n if (this.queuedExperienceEvents.size === 0) {\n this.flushRuntime.clearScheduledRetry()\n return\n }\n\n coreLogger.debug('Flushing offline Experience event queue')\n\n const queuedEvents = Array.from(this.queuedExperienceEvents)\n this.flushRuntime.markFlushStarted()\n\n try {\n const sendSuccess = await this.tryUpsertQueuedEvents(queuedEvents)\n\n if (sendSuccess) {\n queuedEvents.forEach((queuedEvent) => {\n this.queuedExperienceEvents.delete(queuedEvent)\n })\n this.flushRuntime.handleFlushSuccess()\n } else {\n this.flushRuntime.handleFlushFailure({\n queuedBatches: this.queuedExperienceEvents.size > 0 ? 1 : 0,\n queuedEvents: this.queuedExperienceEvents.size,\n })\n }\n } finally {\n this.flushRuntime.markFlushFinished()\n }\n }\n\n private enqueueEvent(event: ExperienceEventPayload): void {\n let droppedEvents: ExperienceEventArray = []\n\n if (this.queuedExperienceEvents.size >= this.offlineMaxEvents) {\n const dropCount = this.queuedExperienceEvents.size - this.offlineMaxEvents + 1\n droppedEvents = this.dropOldestEvents(dropCount)\n\n if (droppedEvents.length > 0) {\n coreLogger.warn(\n `Dropped ${droppedEvents.length} oldest offline event(s) due to queue limit (${this.offlineMaxEvents})`,\n )\n }\n }\n\n this.queuedExperienceEvents.add(event)\n\n if (droppedEvents.length > 0) {\n this.invokeOfflineDropCallback({\n droppedCount: droppedEvents.length,\n droppedEvents,\n maxEvents: this.offlineMaxEvents,\n queuedEvents: this.queuedExperienceEvents.size,\n })\n }\n }\n\n private dropOldestEvents(count: number): ExperienceEventArray {\n const droppedEvents: ExperienceEventArray = []\n\n for (let index = 0; index < count; index += 1) {\n const oldestEvent = this.queuedExperienceEvents.values().next()\n if (oldestEvent.done) break\n\n this.queuedExperienceEvents.delete(oldestEvent.value)\n droppedEvents.push(oldestEvent.value)\n }\n\n return droppedEvents\n }\n\n private invokeOfflineDropCallback(context: ExperienceQueueDropContext): void {\n try {\n this.onOfflineDrop?.(context)\n } catch (error) {\n coreLogger.warn('Offline queue drop callback failed', error)\n }\n }\n\n private async tryUpsertQueuedEvents(events: ExperienceEventArray): Promise<boolean> {\n try {\n await this.upsertProfile(events)\n return true\n } catch (error) {\n coreLogger.warn('Experience queue flush request threw an error', error)\n return false\n }\n }\n\n private async upsertProfile(events: ExperienceEventArray): Promise<OptimizationData> {\n const anonymousId = this.getAnonymousId()\n if (anonymousId) coreLogger.debug(`Anonymous ID found: ${anonymousId}`)\n\n const data = await this.experienceApi.upsertProfile({\n profileId: anonymousId ?? profileSignal.value?.id,\n events,\n })\n\n await this.updateOutputSignals(data)\n\n return data\n }\n\n private async updateOutputSignals(data: OptimizationData): Promise<void> {\n const intercepted = await this.stateInterceptors.run(data)\n const { changes, profile, selectedOptimizations } = intercepted\n\n batch(() => {\n if (!isEqual(changesSignal.value, changes)) changesSignal.value = changes\n if (!isEqual(profileSignal.value, profile)) profileSignal.value = profile\n if (!isEqual(selectedOptimizationsSignal.value, selectedOptimizations)) {\n selectedOptimizationsSignal.value = selectedOptimizations\n }\n })\n }\n}\n","import {\n InsightsEvent as InsightsEventSchema,\n parseWithFriendlyError,\n type BatchInsightsEventArray,\n type InsightsEventArray,\n type InsightsEvent as InsightsEventPayload,\n type Profile,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger } from '@contentful/optimization-api-client/logger'\nimport type { LifecycleInterceptors } from '../CoreBase'\nimport { QueueFlushRuntime, type ResolvedQueueFlushPolicy } from '../lib/queue'\nimport { event as eventSignal, online as onlineSignal, profile as profileSignal } from '../signals'\n\nconst coreLogger = createScopedLogger('CoreStateful')\n\nconst MAX_QUEUED_INSIGHTS_EVENTS = 25\n\ninterface QueuedProfileEvents {\n profile: Profile\n events: InsightsEventArray\n}\n\ninterface InsightsQueueOptions {\n eventInterceptors: LifecycleInterceptors['event']\n flushPolicy: ResolvedQueueFlushPolicy\n insightsApi: {\n sendBatchEvents: (batches: BatchInsightsEventArray) => Promise<boolean>\n }\n}\n\n/**\n * Internal Insights queueing and flush runtime used by {@link CoreStateful}.\n *\n * @internal\n */\nexport class InsightsQueue {\n private readonly eventInterceptors: InsightsQueueOptions['eventInterceptors']\n private readonly flushIntervalMs: number\n private readonly flushRuntime: QueueFlushRuntime\n private readonly insightsApi: InsightsQueueOptions['insightsApi']\n private readonly queuedInsightsByProfile = new Map<Profile['id'], QueuedProfileEvents>()\n private insightsPeriodicFlushTimer: ReturnType<typeof setInterval> | undefined\n\n constructor(options: InsightsQueueOptions) {\n const { eventInterceptors, flushPolicy, insightsApi } = options\n const { flushIntervalMs } = flushPolicy\n\n this.eventInterceptors = eventInterceptors\n this.flushIntervalMs = flushIntervalMs\n this.insightsApi = insightsApi\n this.flushRuntime = new QueueFlushRuntime({\n policy: flushPolicy,\n onRetry: () => {\n void this.flush()\n },\n onCallbackError: (callbackName, error) => {\n coreLogger.warn(`Insights flush policy callback \"${callbackName}\" failed`, error)\n },\n })\n }\n\n clearScheduledRetry(): void {\n this.flushRuntime.clearScheduledRetry()\n }\n\n clearPeriodicFlushTimer(): void {\n if (this.insightsPeriodicFlushTimer === undefined) return\n\n clearInterval(this.insightsPeriodicFlushTimer)\n this.insightsPeriodicFlushTimer = undefined\n }\n\n async send(event: InsightsEventPayload): Promise<void> {\n const { value: profile } = profileSignal\n\n if (!profile) {\n coreLogger.warn('Attempting to emit an event without an Optimization profile')\n return\n }\n\n const intercepted = await this.eventInterceptors.run(event)\n const validEvent = parseWithFriendlyError(InsightsEventSchema, intercepted)\n\n coreLogger.debug(`Queueing ${validEvent.type} event for profile ${profile.id}`, validEvent)\n\n const queuedProfileEvents = this.queuedInsightsByProfile.get(profile.id)\n\n eventSignal.value = validEvent\n\n if (queuedProfileEvents) {\n queuedProfileEvents.profile = profile\n queuedProfileEvents.events.push(validEvent)\n } else {\n this.queuedInsightsByProfile.set(profile.id, { profile, events: [validEvent] })\n }\n\n this.ensurePeriodicFlushTimer()\n if (this.getQueuedEventCount() >= MAX_QUEUED_INSIGHTS_EVENTS) {\n await this.flush()\n }\n this.reconcilePeriodicFlushTimer()\n }\n\n async flush(options: { force?: boolean } = {}): Promise<void> {\n const { force = false } = options\n\n if (this.flushRuntime.shouldSkip({ force, isOnline: !!onlineSignal.value })) return\n\n coreLogger.debug('Flushing insights event queue')\n\n const batches = this.createBatches()\n\n if (!batches.length) {\n this.flushRuntime.clearScheduledRetry()\n this.reconcilePeriodicFlushTimer()\n return\n }\n\n this.flushRuntime.markFlushStarted()\n\n try {\n const sendSuccess = await this.trySendBatches(batches)\n\n if (sendSuccess) {\n this.queuedInsightsByProfile.clear()\n this.flushRuntime.handleFlushSuccess()\n } else {\n this.flushRuntime.handleFlushFailure({\n queuedBatches: batches.length,\n queuedEvents: this.getQueuedEventCount(),\n })\n }\n } finally {\n this.flushRuntime.markFlushFinished()\n this.reconcilePeriodicFlushTimer()\n }\n }\n\n private createBatches(): BatchInsightsEventArray {\n const batches: BatchInsightsEventArray = []\n\n this.queuedInsightsByProfile.forEach(({ profile, events }) => {\n batches.push({ profile, events })\n })\n\n return batches\n }\n\n private async trySendBatches(batches: BatchInsightsEventArray): Promise<boolean> {\n try {\n return await this.insightsApi.sendBatchEvents(batches)\n } catch (error) {\n coreLogger.warn('Insights queue flush request threw an error', error)\n return false\n }\n }\n\n private getQueuedEventCount(): number {\n let queuedCount = 0\n\n this.queuedInsightsByProfile.forEach(({ events }) => {\n queuedCount += events.length\n })\n\n return queuedCount\n }\n\n private ensurePeriodicFlushTimer(): void {\n if (this.insightsPeriodicFlushTimer !== undefined) return\n if (this.getQueuedEventCount() === 0) return\n\n this.insightsPeriodicFlushTimer = setInterval(() => {\n void this.flush()\n }, this.flushIntervalMs)\n }\n\n private reconcilePeriodicFlushTimer(): void {\n if (this.getQueuedEventCount() > 0) {\n this.ensurePeriodicFlushTimer()\n return\n }\n\n this.clearPeriodicFlushTimer()\n }\n}\n","import type { ApiClientConfig } from '@contentful/optimization-api-client'\nimport type {\n ChangeArray,\n ExperienceEvent as ExperienceEventPayload,\n ExperienceEventType,\n InsightsEvent as InsightsEventPayload,\n InsightsEventType,\n Json,\n Profile,\n SelectedOptimizationArray,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger, logger } from '@contentful/optimization-api-client/logger'\nimport type { BlockedEvent } from './BlockedEvent'\nimport type { ConsentController, ConsentGuard } from './Consent'\nimport type { CoreStatefulApiConfig } from './CoreApiConfig'\nimport type { CoreConfig } from './CoreBase'\nimport CoreStatefulEventEmitter from './CoreStatefulEventEmitter'\nimport { toPositiveInt } from './lib/number'\nimport { type QueueFlushPolicy, resolveQueueFlushPolicy } from './lib/queue'\nimport {\n acquireStatefulRuntimeSingleton,\n releaseStatefulRuntimeSingleton,\n} from './lib/singleton/StatefulRuntimeSingleton'\nimport { ExperienceQueue, type ExperienceQueueDropContext } from './queues/ExperienceQueue'\nimport { InsightsQueue } from './queues/InsightsQueue'\nimport {\n batch,\n blockedEvent as blockedEventSignal,\n canOptimize as canOptimizeSignal,\n changes as changesSignal,\n consent as consentSignal,\n effect,\n event as eventSignal,\n type Observable,\n online as onlineSignal,\n previewPanelAttached as previewPanelAttachedSignal,\n previewPanelOpen as previewPanelOpenSignal,\n profile as profileSignal,\n selectedOptimizations as selectedOptimizationsSignal,\n signalFns,\n type SignalFns,\n type Signals,\n signals,\n toObservable,\n} from './signals'\nimport { PREVIEW_PANEL_SIGNAL_FNS_SYMBOL, PREVIEW_PANEL_SIGNALS_SYMBOL } from './symbols'\n\nconst coreLogger = createScopedLogger('CoreStateful')\n\n/**\n * Union of all event type keys that stateful Core may emit.\n *\n * @public\n */\nexport type EventType = InsightsEventType | ExperienceEventType\n\nconst DEFAULT_ALLOWED_EVENT_TYPES: EventType[] = ['identify', 'page', 'screen']\nconst OFFLINE_QUEUE_MAX_EVENTS = 100\nexport type { ExperienceQueueDropContext } from './queues/ExperienceQueue'\n\nconst hasDefinedValues = (record: Record<string, unknown>): boolean =>\n Object.values(record).some((value) => value !== undefined)\n\nconst createStatefulExperienceApiConfig = (\n api: CoreStatefulApiConfig | undefined,\n): ApiClientConfig['experience'] => {\n if (api === undefined) return undefined\n\n const experienceConfig = {\n baseUrl: api.experienceBaseUrl,\n enabledFeatures: api.enabledFeatures,\n ip: api.ip,\n locale: api.locale,\n plainText: api.plainText,\n preflight: api.preflight,\n }\n\n return hasDefinedValues(experienceConfig) ? experienceConfig : undefined\n}\n\nconst createStatefulInsightsApiConfig = (\n api: CoreStatefulApiConfig | undefined,\n): ApiClientConfig['insights'] => {\n if (api === undefined) return undefined\n\n const insightsConfig = {\n baseUrl: api.insightsBaseUrl,\n beaconHandler: api.beaconHandler,\n }\n\n return hasDefinedValues(insightsConfig) ? insightsConfig : undefined\n}\n\n/**\n * Unified queue policy for stateful Core.\n *\n * @public\n */\nexport interface QueuePolicy {\n /** Shared retry/backoff/circuit policy for queued flushes. */\n flush?: QueueFlushPolicy\n /** Maximum number of offline Experience events retained. */\n offlineMaxEvents?: number\n /** Callback invoked when oldest offline Experience events are dropped. */\n onOfflineDrop?: (context: ExperienceQueueDropContext) => void\n}\n\ninterface ResolvedQueuePolicy {\n flush: ReturnType<typeof resolveQueueFlushPolicy>\n offlineMaxEvents: number\n onOfflineDrop?: QueuePolicy['onOfflineDrop']\n}\n\nconst resolveQueuePolicy = (policy: QueuePolicy | undefined): ResolvedQueuePolicy => ({\n flush: resolveQueueFlushPolicy(policy?.flush),\n offlineMaxEvents: toPositiveInt(policy?.offlineMaxEvents, OFFLINE_QUEUE_MAX_EVENTS),\n onOfflineDrop: policy?.onOfflineDrop,\n})\n\n/**\n * Symbol-keyed signal bridge shared between core and first-party preview tooling.\n *\n * @public\n */\nexport interface PreviewPanelSignalObject {\n /** Signals instance populated by {@link CoreStateful.registerPreviewPanel}. */\n [PREVIEW_PANEL_SIGNALS_SYMBOL]?: Signals | null | undefined\n /** Signal helper functions populated by {@link CoreStateful.registerPreviewPanel}. */\n [PREVIEW_PANEL_SIGNAL_FNS_SYMBOL]?: SignalFns | null | undefined\n}\n\n/**\n * Combined observable state exposed by the stateful core.\n *\n * @public\n */\nexport interface CoreStates {\n /** Current consent value (if any). */\n consent: Observable<boolean | undefined>\n /** Whether the preview panel has been attached to the host runtime. */\n previewPanelAttached: Observable<boolean>\n /** Whether the preview panel is currently open in the host runtime. */\n previewPanelOpen: Observable<boolean>\n /** Stream of the most recent blocked event payload. */\n blockedEventStream: Observable<BlockedEvent | undefined>\n /** Stream of the most recent event emitted. */\n eventStream: Observable<InsightsEventPayload | ExperienceEventPayload | undefined>\n /** Key-scoped observable for a single Custom Flag value. */\n flag: (name: string) => Observable<Json>\n /** Live view of the current profile. */\n profile: Observable<Profile | undefined>\n /** Live view of selected optimizations (variants). */\n selectedOptimizations: Observable<SelectedOptimizationArray | undefined>\n /** Whether optimization data is currently available. */\n canOptimize: Observable<boolean>\n}\n\n/**\n * Default values used to preconfigure the stateful core.\n *\n * @public\n */\nexport interface CoreConfigDefaults {\n /** Global consent default applied at construction time. */\n consent?: boolean\n /** Default active profile used for optimization and insights. */\n profile?: Profile\n /** Initial diff of changes produced by the service. */\n changes?: ChangeArray\n /** Preselected optimization variants (e.g., winning treatments). */\n selectedOptimizations?: SelectedOptimizationArray\n}\n\n/**\n * Configuration for {@link CoreStateful}.\n *\n * @public\n */\nexport interface CoreStatefulConfig extends CoreConfig {\n /**\n * Unified API configuration for stateful environments.\n */\n api?: CoreStatefulApiConfig\n\n /**\n * Allow-listed event type strings permitted when consent is not set.\n */\n allowedEventTypes?: EventType[]\n\n /** Optional set of default values applied on initialization. */\n defaults?: CoreConfigDefaults\n\n /** Function used to obtain an anonymous user identifier. */\n getAnonymousId?: () => string | undefined\n\n /**\n * Callback invoked whenever an event call is blocked by checks.\n */\n onEventBlocked?: (event: BlockedEvent) => void\n\n /** Unified queue policy for queued stateful work. */\n queuePolicy?: QueuePolicy\n}\n\nlet statefulInstanceCounter = 0\n\n/**\n * Core runtime that owns stateful event delivery, consent, and shared signals.\n *\n * @public\n */\nclass CoreStateful extends CoreStatefulEventEmitter implements ConsentController, ConsentGuard {\n private readonly singletonOwner: string\n private destroyed = false\n protected readonly allowedEventTypes: EventType[]\n protected readonly experienceQueue: ExperienceQueue\n protected readonly insightsQueue: InsightsQueue\n protected readonly onEventBlocked?: CoreStatefulConfig['onEventBlocked']\n\n /**\n * Expose merged observable state for consumers.\n */\n readonly states: CoreStates = {\n blockedEventStream: toObservable(blockedEventSignal),\n flag: (name: string): Observable<Json> => this.getFlagObservable(name),\n consent: toObservable(consentSignal),\n eventStream: toObservable(eventSignal),\n canOptimize: toObservable(canOptimizeSignal),\n selectedOptimizations: toObservable(selectedOptimizationsSignal),\n previewPanelAttached: toObservable(previewPanelAttachedSignal),\n previewPanelOpen: toObservable(previewPanelOpenSignal),\n profile: toObservable(profileSignal),\n }\n\n constructor(config: CoreStatefulConfig) {\n super(config, {\n experience: createStatefulExperienceApiConfig(config.api),\n insights: createStatefulInsightsApiConfig(config.api),\n })\n\n this.singletonOwner = `CoreStateful#${++statefulInstanceCounter}`\n acquireStatefulRuntimeSingleton(this.singletonOwner)\n\n try {\n const { allowedEventTypes, defaults, getAnonymousId, onEventBlocked, queuePolicy } = config\n const {\n changes: defaultChanges,\n consent: defaultConsent,\n selectedOptimizations: defaultSelectedOptimizations,\n profile: defaultProfile,\n } = defaults ?? {}\n const resolvedQueuePolicy = resolveQueuePolicy(queuePolicy)\n\n this.allowedEventTypes = allowedEventTypes ?? DEFAULT_ALLOWED_EVENT_TYPES\n this.onEventBlocked = onEventBlocked\n this.insightsQueue = new InsightsQueue({\n eventInterceptors: this.interceptors.event,\n flushPolicy: resolvedQueuePolicy.flush,\n insightsApi: this.api.insights,\n })\n this.experienceQueue = new ExperienceQueue({\n experienceApi: this.api.experience,\n eventInterceptors: this.interceptors.event,\n flushPolicy: resolvedQueuePolicy.flush,\n getAnonymousId: getAnonymousId ?? (() => undefined),\n offlineMaxEvents: resolvedQueuePolicy.offlineMaxEvents,\n onOfflineDrop: resolvedQueuePolicy.onOfflineDrop,\n stateInterceptors: this.interceptors.state,\n })\n\n if (defaultConsent !== undefined) consentSignal.value = defaultConsent\n\n batch(() => {\n if (defaultChanges !== undefined) changesSignal.value = defaultChanges\n if (defaultSelectedOptimizations !== undefined) {\n selectedOptimizationsSignal.value = defaultSelectedOptimizations\n }\n if (defaultProfile !== undefined) profileSignal.value = defaultProfile\n })\n\n this.initializeEffects()\n } catch (error) {\n releaseStatefulRuntimeSingleton(this.singletonOwner)\n throw error\n }\n }\n\n private initializeEffects(): void {\n effect(() => {\n coreLogger.debug(\n `Profile ${profileSignal.value && `with ID ${profileSignal.value.id}`} has been ${profileSignal.value ? 'set' : 'cleared'}`,\n )\n })\n\n effect(() => {\n coreLogger.debug(\n `Variants have been ${selectedOptimizationsSignal.value?.length ? 'populated' : 'cleared'}`,\n )\n })\n\n effect(() => {\n coreLogger.info(\n `Core ${consentSignal.value ? 'will' : 'will not'} emit gated events due to consent (${consentSignal.value})`,\n )\n })\n\n effect(() => {\n if (!onlineSignal.value) return\n\n this.insightsQueue.clearScheduledRetry()\n this.experienceQueue.clearScheduledRetry()\n void this.flushQueues({ force: true })\n })\n }\n\n private async flushQueues(options: { force?: boolean } = {}): Promise<void> {\n await this.insightsQueue.flush(options)\n await this.experienceQueue.flush(options)\n }\n\n destroy(): void {\n if (this.destroyed) return\n\n this.destroyed = true\n void this.insightsQueue.flush({ force: true }).catch((error: unknown) => {\n logger.warn('Failed to flush insights queue during destroy()', String(error))\n })\n void this.experienceQueue.flush({ force: true }).catch((error: unknown) => {\n logger.warn('Failed to flush Experience queue during destroy()', String(error))\n })\n this.insightsQueue.clearPeriodicFlushTimer()\n\n releaseStatefulRuntimeSingleton(this.singletonOwner)\n }\n\n reset(): void {\n batch(() => {\n blockedEventSignal.value = undefined\n eventSignal.value = undefined\n changesSignal.value = undefined\n profileSignal.value = undefined\n selectedOptimizationsSignal.value = undefined\n })\n }\n\n async flush(): Promise<void> {\n await this.flushQueues()\n }\n\n consent(accept: boolean): void {\n consentSignal.value = accept\n }\n\n protected get online(): boolean {\n return onlineSignal.value ?? false\n }\n\n protected set online(isOnline: boolean) {\n onlineSignal.value = isOnline\n }\n\n registerPreviewPanel(previewPanel: PreviewPanelSignalObject): void {\n Reflect.set(previewPanel, PREVIEW_PANEL_SIGNALS_SYMBOL, signals)\n Reflect.set(previewPanel, PREVIEW_PANEL_SIGNAL_FNS_SYMBOL, signalFns)\n }\n}\n\nexport default CoreStateful\n","import {\n BatchInsightsEventArray,\n ExperienceEvent as ExperienceEventSchema,\n InsightsEvent as InsightsEventSchema,\n parseWithFriendlyError,\n type ExperienceEvent as ExperienceEventPayload,\n type InsightsEvent as InsightsEventPayload,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { PartialProfile, type OptimizationData } from './api-schemas'\nimport type CoreStateless from './CoreStateless'\nimport type { CoreStatelessRequestOptions } from './CoreStateless'\nimport type {\n ClickBuilderArgs,\n FlagViewBuilderArgs,\n HoverBuilderArgs,\n IdentifyBuilderArgs,\n PageViewBuilderArgs,\n ScreenViewBuilderArgs,\n TrackBuilderArgs,\n ViewBuilderArgs,\n} from './events'\n\ntype StatelessExperiencePayload<TPayload> = TPayload & { profile?: PartialProfile }\ntype StatelessInsightsPayload<TPayload> = TPayload & { profile: PartialProfile }\ntype StatelessStickyTrackViewPayload = ViewBuilderArgs & {\n profile?: PartialProfile\n sticky: true\n}\ntype StatelessNonStickyTrackViewPayload = Omit<ViewBuilderArgs, 'sticky'> & {\n profile: PartialProfile\n sticky?: false | undefined\n}\n\nconst TRACK_CLICK_PROFILE_ERROR =\n 'CoreStateless.forRequest().trackClick() requires `payload.profile.id` for Insights delivery.'\nconst TRACK_HOVER_PROFILE_ERROR =\n 'CoreStateless.forRequest().trackHover() requires `payload.profile.id` for Insights delivery.'\nconst TRACK_FLAG_VIEW_PROFILE_ERROR =\n 'CoreStateless.forRequest().trackFlagView() requires `payload.profile.id` for Insights delivery.'\nconst NON_STICKY_TRACK_VIEW_PROFILE_ERROR =\n 'CoreStateless.forRequest().trackView() requires `payload.profile.id` when `payload.sticky` is not `true`.'\nconst STICKY_TRACK_VIEW_PROFILE_ERROR =\n 'CoreStateless.forRequest().trackView() could not derive a profile from the sticky Experience response. Pass `payload.profile.id` explicitly if you need a fallback.'\n\nconst requireInsightsProfile = (\n profile: PartialProfile | undefined,\n errorMessage: string,\n): PartialProfile => {\n if (profile !== undefined) return profile\n\n throw new Error(errorMessage)\n}\n\n/**\n * Stateless request scope created by {@link CoreStateless.forRequest}.\n *\n * @public\n */\nexport class CoreStatelessRequestScope {\n private readonly core: CoreStateless\n private readonly options: Readonly<CoreStatelessRequestOptions>\n\n constructor(core: CoreStateless, options: CoreStatelessRequestOptions = {}) {\n this.core = core\n this.options = Object.freeze({ ...options })\n }\n\n async identify(\n payload: StatelessExperiencePayload<IdentifyBuilderArgs>,\n ): Promise<OptimizationData> {\n const { profile, ...builderArgs } = payload\n\n return await this.sendExperienceEvent(\n this.core.eventBuilder.buildIdentify(builderArgs),\n profile,\n )\n }\n\n async page(\n payload: StatelessExperiencePayload<PageViewBuilderArgs> = {},\n ): Promise<OptimizationData> {\n const { profile, ...builderArgs } = payload\n\n return await this.sendExperienceEvent(\n this.core.eventBuilder.buildPageView(builderArgs),\n profile,\n )\n }\n\n async screen(\n payload: StatelessExperiencePayload<ScreenViewBuilderArgs>,\n ): Promise<OptimizationData> {\n const { profile, ...builderArgs } = payload\n\n return await this.sendExperienceEvent(\n this.core.eventBuilder.buildScreenView(builderArgs),\n profile,\n )\n }\n\n async track(payload: StatelessExperiencePayload<TrackBuilderArgs>): Promise<OptimizationData> {\n const { profile, ...builderArgs } = payload\n\n return await this.sendExperienceEvent(this.core.eventBuilder.buildTrack(builderArgs), profile)\n }\n\n /**\n * Record an entry view in a stateless runtime.\n *\n * @remarks\n * Non-sticky entry views require `payload.profile.id` for Insights delivery.\n * Sticky entry views may omit `profile`, because the returned Experience\n * profile is reused for the paired Insights event.\n */\n async trackView(\n payload: StatelessStickyTrackViewPayload | StatelessNonStickyTrackViewPayload,\n ): Promise<OptimizationData | undefined> {\n const { profile, ...builderArgs } = payload\n let result: OptimizationData | undefined = undefined\n let insightsProfile: PartialProfile | undefined = profile\n\n if (payload.sticky) {\n result = await this.sendExperienceEvent(\n this.core.eventBuilder.buildView(builderArgs),\n profile,\n )\n const { profile: responseProfile } = result\n insightsProfile = responseProfile\n }\n\n await this.sendInsightsEvent(\n this.core.eventBuilder.buildView(builderArgs),\n requireInsightsProfile(\n insightsProfile,\n payload.sticky ? STICKY_TRACK_VIEW_PROFILE_ERROR : NON_STICKY_TRACK_VIEW_PROFILE_ERROR,\n ),\n )\n\n return result\n }\n\n /**\n * Record an entry click in a stateless runtime.\n *\n * @remarks\n * Stateless Insights delivery requires `payload.profile.id`.\n */\n async trackClick(payload: StatelessInsightsPayload<ClickBuilderArgs>): Promise<void> {\n const { profile, ...builderArgs } = payload\n\n await this.sendInsightsEvent(\n this.core.eventBuilder.buildClick(builderArgs),\n requireInsightsProfile(profile, TRACK_CLICK_PROFILE_ERROR),\n )\n }\n\n /**\n * Record an entry hover in a stateless runtime.\n *\n * @remarks\n * Stateless Insights delivery requires `payload.profile.id`.\n */\n async trackHover(payload: StatelessInsightsPayload<HoverBuilderArgs>): Promise<void> {\n const { profile, ...builderArgs } = payload\n\n await this.sendInsightsEvent(\n this.core.eventBuilder.buildHover(builderArgs),\n requireInsightsProfile(profile, TRACK_HOVER_PROFILE_ERROR),\n )\n }\n\n /**\n * Record a Custom Flag view in a stateless runtime.\n *\n * @remarks\n * Stateless Insights delivery requires `payload.profile.id`.\n */\n async trackFlagView(payload: StatelessInsightsPayload<FlagViewBuilderArgs>): Promise<void> {\n const { profile, ...builderArgs } = payload\n\n await this.sendInsightsEvent(\n this.core.eventBuilder.buildFlagView(builderArgs),\n requireInsightsProfile(profile, TRACK_FLAG_VIEW_PROFILE_ERROR),\n )\n }\n\n private async sendExperienceEvent(\n event: ExperienceEventPayload,\n profile?: PartialProfile,\n ): Promise<OptimizationData> {\n const intercepted = await this.core.interceptors.event.run(event)\n const validEvent = parseWithFriendlyError(ExperienceEventSchema, intercepted)\n\n return await this.core.api.experience.upsertProfile(\n {\n profileId: profile?.id,\n events: [validEvent],\n },\n this.options,\n )\n }\n\n private async sendInsightsEvent(\n event: InsightsEventPayload,\n profile: PartialProfile,\n ): Promise<void> {\n const intercepted = await this.core.interceptors.event.run(event)\n const validEvent = parseWithFriendlyError(InsightsEventSchema, intercepted)\n const batchEvent: BatchInsightsEventArray = parseWithFriendlyError(BatchInsightsEventArray, [\n { profile: parseWithFriendlyError(PartialProfile, profile), events: [validEvent] },\n ])\n\n await this.core.api.insights.sendBatchEvents(batchEvent)\n }\n}\n","import type {\n ApiClientConfig,\n ExperienceApiClientRequestOptions,\n} from '@contentful/optimization-api-client'\nimport type { CoreStatelessApiConfig } from './CoreApiConfig'\nimport CoreBase, { type CoreConfig } from './CoreBase'\nimport { CoreStatelessRequestScope } from './CoreStatelessRequestScope'\nimport type { EventBuilderConfig } from './events'\n\n/**\n * Request-bound Experience API options for stateless runtimes.\n *\n * @public\n */\nexport interface CoreStatelessRequestOptions extends Pick<\n ExperienceApiClientRequestOptions,\n 'ip' | 'locale' | 'plainText' | 'preflight'\n> {}\n\n/**\n * Configuration for stateless Optimization Core runtimes.\n *\n * @public\n * @remarks\n * This configuration extends {@link CoreConfig} but allows partial overrides\n * of the event-builder configuration. SDKs commonly inject their own library\n * metadata or channel definitions.\n */\nexport interface CoreStatelessConfig extends CoreConfig {\n /**\n * Unified API configuration for stateless environments.\n */\n api?: CoreStatelessApiConfig\n\n /**\n * Overrides for the event builder configuration. Omits methods that are only\n * useful in stateful environments.\n */\n eventBuilder?: Omit<EventBuilderConfig, 'getLocale' | 'getPageProperties' | 'getUserAgent'>\n}\n\nconst hasDefinedValues = (record: Record<string, unknown>): boolean =>\n Object.values(record).some((value) => value !== undefined)\n\nconst createStatelessExperienceApiConfig = (\n api: CoreStatelessConfig['api'] | undefined,\n): ApiClientConfig['experience'] => {\n if (api === undefined) return undefined\n\n const experienceConfig = {\n baseUrl: api.experienceBaseUrl,\n enabledFeatures: api.enabledFeatures,\n }\n\n return hasDefinedValues(experienceConfig) ? experienceConfig : undefined\n}\n\nconst createStatelessInsightsApiConfig = (\n api: CoreStatelessConfig['api'] | undefined,\n): ApiClientConfig['insights'] => {\n if (api?.insightsBaseUrl === undefined) return undefined\n\n return {\n baseUrl: api.insightsBaseUrl,\n }\n}\n\n/**\n * Core runtime for stateless environments.\n *\n * @public\n * Built on top of `CoreBase`. Request-emitting methods are exposed through\n * {@link CoreStateless.forRequest}.\n */\nclass CoreStateless extends CoreBase<CoreStatelessConfig> {\n constructor(config: CoreStatelessConfig) {\n super(config, {\n experience: createStatelessExperienceApiConfig(config.api),\n insights: createStatelessInsightsApiConfig(config.api),\n })\n }\n\n /**\n * Bind request-scoped Experience API options for a single stateless request.\n *\n * @param options - Request-scoped Experience API options.\n * @returns A lightweight request scope for stateless event emission.\n */\n forRequest(options: CoreStatelessRequestOptions = {}): CoreStatelessRequestScope {\n return new CoreStatelessRequestScope(this, options)\n }\n}\n\nexport { CoreStatelessRequestScope }\n\nexport default CoreStateless\n","/**\n * A callback invoked when a method call is blocked by {@link guardedBy}.\n *\n * @param methodName - The name of the method that was attempted.\n * @param args - The readonly array of arguments supplied to the blocked call.\n * @returns Nothing.\n *\n * @public\n */\nexport type BlockHandler = (methodName: string, args: readonly unknown[]) => void\n\n/**\n * The original method implementation.\n *\n * @typeParam A - The parameter tuple of the original method.\n * @typeParam R - The return type of the original method.\n * @param value - The method being decorated.\n * @param context - The Stage-3 decorator context for a class method.\n * @returns Nothing.\n *\n * @remarks\n * Users do not call this directly; it's returned by {@link guardedBy}.\n *\n * @internal\n */\nexport type GuardedByFunction<T extends object> = <A extends readonly unknown[], R>(\n value: (...args: A) => R,\n context: ClassMethodDecoratorContext<T, (...args: A) => R>,\n) => void\n\n/**\n * Options that tweak the behavior of {@link guardedBy}.\n *\n * @typeParam T - The instance type on which the decorator is applied.\n *\n * @public\n */\nexport interface GuardedByOptions<T extends object> {\n /**\n * Inverts the predicate result.\n *\n * When `true`, a truthy predicate result **blocks** the method.\n * When `false` (default) or omitted, a truthy predicate result **allows** the method.\n *\n * @defaultValue `false`\n * @remarks\n * This option is useful when the predicate expresses a *forbid* condition\n * (e.g. \"isLocked\" or \"isDestroyed\") rather than an *allow* condition.\n */\n readonly invert?: boolean\n\n /**\n * Either a function to call when a method is blocked, or the name/symbol of\n * an instance method on `this` to call when blocked.\n *\n * Both forms are **synchronous** and receive `(methodName, argsArray)`.\n * If omitted, blocked calls fail silently (i.e., return `undefined` or\n * `Promise<undefined>` for async methods).\n *\n * @remarks\n * - If a property key is supplied and the instance does not have a callable at that key,\n * the hook is ignored.\n * - The hook **must not** be `async`; any async work should be scheduled manually.\n */\n readonly onBlocked?: BlockHandler | (keyof T & (string | symbol))\n}\n\n/**\n * Type guard for functions.\n *\n * @internal\n */\nconst isFunction = (v: unknown): v is (...args: readonly unknown[]) => unknown =>\n typeof v === 'function'\n\n/**\n * Converts a property key to a readable string for logs and messages.\n *\n * @param name - The property key to stringify.\n * @returns A human-friendly name.\n *\n * @internal\n */\nconst nameToString = (name: PropertyKey): string =>\n typeof name === 'string'\n ? name\n : typeof name === 'symbol'\n ? (name.description ?? String(name))\n : String(name)\n\n/**\n * True when the `onBlocked` option is a property key (string or symbol).\n *\n * @typeParam T - The instance type.\n * @param v - The `onBlocked` option value.\n * @returns Whether `v` is a property key.\n *\n * @internal\n */\nconst isOnBlockedKey = <T extends object>(\n v: GuardedByOptions<T>['onBlocked'],\n): v is keyof T & (string | symbol) => typeof v === 'string' || typeof v === 'symbol'\n\n/**\n * Detects declared `async` functions.\n *\n * @param fn - The candidate to test.\n * @returns `true` if `fn` is an async function, else `false`.\n *\n * @internal\n */\nconst isAsyncFunction = (fn: (...args: readonly unknown[]) => unknown): boolean =>\n Object.prototype.toString.call(fn) === '[object AsyncFunction]'\n\n/**\n * Decorator factory that **guards** class methods behind a synchronous predicate.\n *\n * When a decorated method is invoked:\n * - If the predicate returns a value that evaluates to **allowed** (see `invert`), the original\n * method is executed and its result is returned.\n * - If the call is **blocked**, the optional `onBlocked` hook is invoked (if configured) and:\n * - `undefined` is returned for sync methods; or\n * - `Promise<undefined>` is returned for async methods (to preserve `await` compatibility).\n *\n * @typeParam T - The instance type that owns both the predicate and the decorated method.\n *\n * @param predicateName - The name (string or symbol) of a **synchronous** instance method on `this`\n * that acts as the predicate. It is called as `this[predicateName](methodName, argsArray)`.\n * @param opts - Optional `GuardedByOptions` to configure inversion and `onBlocked`.\n *\n * @returns A methods-only class decorator compatible with Stage-3 decorators that wraps the method.\n *\n * @throws TypeError\n * Thrown at initialization time (first instance construction) if `predicateName` does not resolve\n * to a **synchronous function** on the instance.\n *\n * @remarks\n * - This is a **methods-only** decorator; applying it to accessors/fields is a no-op.\n * - The decorator preserves the original method's sync/async shape.\n * - The predicate is invoked with `(decoratedMethodName, argsArray)` to support context-aware checks.\n *\n * @example\n * Here, `canRun` allows the call when it returns truthy:\n * ```ts\n * class Runner {\n * canRun(method: string, _args: readonly unknown[]) { return method !== 'stop'; }\n *\n * @guardedBy<Runner>('canRun')\n * go() { console.log('running'); }\n * }\n * ```\n *\n * @example\n * Invert the predicate and call a handler on block:\n * ```ts\n * class Door {\n * isLocked() { return true } // truthy means \"locked\"\n * onBlocked(method: string) { console.warn(`${method} blocked`) }\n *\n * @guardedBy<Door>('isLocked', { invert: true, onBlocked: 'onBlocked' })\n * open() { /* ... *\\/ }\n * }\n * ```\n *\n * @public\n */\nexport function guardedBy<T extends object>(\n predicateName: keyof T & (string | symbol),\n opts?: GuardedByOptions<T>,\n): GuardedByFunction<T> {\n return function <A extends readonly unknown[], R>(\n _value: (...args: A) => R,\n context: ClassMethodDecoratorContext<T, (...args: A) => R>,\n ): void {\n const decoratedName = nameToString(context.name)\n\n context.addInitializer(function init(this: T): void {\n // Original method on the instance\n const originalUnknown: unknown = Reflect.get(this, context.name)\n if (!isFunction(originalUnknown)) {\n return // defensive: nothing to wrap\n }\n const original = originalUnknown\n const originalIsAsync = isAsyncFunction(original)\n\n const resolvePredicate = (self: T): ((...args: readonly unknown[]) => unknown) => {\n const { [predicateName]: cand } = self\n if (!isFunction(cand)) {\n throw new TypeError(\n `@guardedBy expects predicate \"${String(predicateName)}\" to be a synchronous function.`,\n )\n }\n return cand\n }\n\n const computeAllowed = (self: T, args: readonly unknown[]): boolean => {\n const pred = resolvePredicate(self)\n const ok = Boolean(pred.call(self, decoratedName, args))\n return opts?.invert === true ? !ok : ok\n }\n\n const runOnBlocked = (self: T, args: readonly unknown[]): void => {\n const { onBlocked } = opts ?? {}\n if (onBlocked === undefined) {\n return\n }\n if (isFunction(onBlocked)) {\n onBlocked.call(self, decoratedName, args)\n return\n }\n if (isOnBlockedKey<T>(onBlocked)) {\n const { [onBlocked]: handlerCandidate } = self\n if (isFunction(handlerCandidate)) {\n handlerCandidate.call(self, decoratedName, args)\n }\n }\n }\n\n const blockedReturn = (): unknown =>\n originalIsAsync ? Promise.resolve(undefined) : undefined\n\n const wrapped = function (this: T, ...args: readonly unknown[]): unknown {\n if (!computeAllowed(this, args)) {\n runOnBlocked(this, args)\n return blockedReturn()\n }\n return original.call(this, ...args)\n }\n\n // Replace the instance method with our wrapper\n Reflect.set(this, context.name, wrapped)\n })\n }\n}\n"],"names":["OPTIMIZATION_CORE_SDK_VERSION","__OPTIMIZATION_VERSION__","OPTIMIZATION_CORE_SDK_NAME","__OPTIMIZATION_PACKAGE_NAME__","ANONYMOUS_ID_COOKIE","ANONYMOUS_ID_KEY","CONSENT_KEY","CHANGES_CACHE_KEY","DEBUG_FLAG_KEY","PROFILE_CACHE_KEY","SELECTED_OPTIMIZATIONS_CACHE_KEY","ANONYMOUS_ID_COOKIE_LEGACY","ANONYMOUS_ID_KEY_LEGACY","PREVIEW_PANEL_SIGNALS_SYMBOL","Symbol","PREVIEW_PANEL_SIGNAL_FNS_SYMBOL","__webpack_require__","module","getter","definition","key","Object","obj","prop","isNonNullish","value","toError","Error","String","toObservable","s","cloneDeep","next","dispose","effect","closed","isEffectActive","undefined","stop","callbackError","error","queueMicrotask","toDistinctObservable","isEqual","observable","hasPrevious","previous","changes","signal","blockedEvent","consent","event","online","previewPanelAttached","previewPanelOpen","selectedOptimizations","canOptimize","computed","profile","signals","signalFns","batch","untracked","UniversalEventBuilderArgs","z","Campaign","GeoLocation","Page","Screen","EntryInteractionBuilderArgsBase","ViewBuilderArgs","FlagViewBuilderArgs","ClickBuilderArgs","HoverBuilderArgs","IdentifyBuilderArgs","Traits","PageViewBuilderArgs","ScreenViewBuilderArgs","Properties","TrackBuilderArgs","DEFAULT_PAGE_PROPERTIES","EventBuilder","config","app","channel","library","getLocale","getPageProperties","getUserAgent","campaign","locale","location","page","screen","userAgent","timestamp","Date","crypto","universal","componentId","experienceId","variantIndex","args","viewId","viewDurationMs","parseWithFriendlyError","hoverId","hoverDurationMs","traits","userId","properties","pageProperties","merged","merge","_","universalContext","universalProperties","context","PageEventContext","name","ScreenEventContext","InterceptorManager","Map","interceptor","id","input","fns","Array","acc","fn","FlagsResolver","actualValue","logger","createScopedLogger","RESOLUTION_WARNING_BASE","getAtPath","path","current","segments","Boolean","segment","Reflect","MergeTagValueResolver","_path","index","paths","dotPath","underScorePath","selectors","matchingSelector","selector","mergeTagEntry","isMergeTagEntry","fallback","Profile","resolve","entry","isOptimizedEntry","optimizationEntry","OptimizedEntryResolver","selectedOptimization","selectedVariantIndex","selectedVariant","selectedVariantEntry","optimizedEntry","skipValidation","maybeOptimization","isOptimizationEntry","relevantVariants","normalizeOptimizationConfig","component","isEntryReplacementComponent","isEntryReplacementVariant","variant","isEntry","CoreBase","api","eventBuilder","logLevel","environment","clientId","fetchOptions","ConsoleLogSink","apiConfig","ApiClient","embeddedEntryNodeTarget","coreLogger","CONSENT_EVENT_TYPE_MAP","CoreStatefulEventEmitter","changesSignal","payload","selectedOptimizationsSignal","profileSignal","builderArgs","result","mappedEventType","isAllowed","eventType","consentSignal","JSON","method","_profile","change","candidate","existingObservable","trackFlagView","buildFlagViewBuilderArgs","valueSignal","distinctObservable","trackedObservable","reason","blockedEventSignal","toPositiveInt","Number","Math","toRatio","DEFAULT_QUEUE_FLUSH_POLICY","resolveQueueFlushPolicy","policy","defaults","configuredPolicy","baseBackoffMs","maxBackoffMs","computeQueueFlushRetryDelayMs","options","consecutiveFailures","jitterRatio","exponential","capped","jitter","createQueueFlushFailureWindow","failureTimestamp","retryDelayMs","maxConsecutiveFailures","circuitOpenMs","circuitOpenUntil","STATEFUL_RUNTIME_LOCK_KEY","getStatefulRuntimeLock","singletonGlobal","globalThis","acquireStatefulRuntimeSingleton","owner","lock","releaseStatefulRuntimeSingleton","QueueFlushRuntime","onCallbackError","onRetry","clearTimeout","force","isOnline","now","previousConsecutiveFailures","queuedBatches","queuedEvents","failureContext","failureWindow","nextFlushAllowedAt","openedCircuit","scheduledRetryDelayMs","delayMs","setTimeout","callbackName","ExperienceQueue","Set","experienceApi","eventInterceptors","flushPolicy","getAnonymousId","offlineMaxEvents","onOfflineDrop","stateInterceptors","intercepted","validEvent","ExperienceEventSchema","eventSignal","onlineSignal","sendSuccess","queuedEvent","droppedEvents","dropCount","count","oldestEvent","events","anonymousId","data","MAX_QUEUED_INSIGHTS_EVENTS","InsightsQueue","insightsApi","flushIntervalMs","clearInterval","InsightsEventSchema","queuedProfileEvents","batches","queuedCount","setInterval","DEFAULT_ALLOWED_EVENT_TYPES","OFFLINE_QUEUE_MAX_EVENTS","hasDefinedValues","record","createStatefulExperienceApiConfig","experienceConfig","createStatefulInsightsApiConfig","insightsConfig","resolveQueuePolicy","statefulInstanceCounter","CoreStateful","canOptimizeSignal","previewPanelAttachedSignal","previewPanelOpenSignal","allowedEventTypes","onEventBlocked","queuePolicy","defaultChanges","defaultConsent","defaultSelectedOptimizations","defaultProfile","resolvedQueuePolicy","accept","previewPanel","TRACK_CLICK_PROFILE_ERROR","TRACK_HOVER_PROFILE_ERROR","TRACK_FLAG_VIEW_PROFILE_ERROR","NON_STICKY_TRACK_VIEW_PROFILE_ERROR","STICKY_TRACK_VIEW_PROFILE_ERROR","requireInsightsProfile","errorMessage","CoreStatelessRequestScope","core","insightsProfile","responseProfile","batchEvent","BatchInsightsEventArray","PartialProfile","createStatelessExperienceApiConfig","createStatelessInsightsApiConfig","CoreStateless","isFunction","v","nameToString","isOnBlockedKey","isAsyncFunction","guardedBy","predicateName","opts","_value","decoratedName","originalUnknown","original","originalIsAsync","resolvePredicate","self","cand","TypeError","computeAllowed","pred","ok","runOnBlocked","onBlocked","handlerCandidate","blockedReturn","Promise","wrapped"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/constants.ts","../src/symbols.ts","webpack/runtime/compat_get_default_export","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../src/signals/Observable.ts","../src/signals/signals.ts","../src/events/EventBuilder.ts","../src/lib/interceptor/InterceptorManager.ts","../src/resolvers/FlagsResolver.ts","../src/resolvers/MergeTagValueResolver.ts","../src/resolvers/OptimizedEntryResolver.ts","../src/CoreBase.ts","../src/CoreStatefulEventEmitter.ts","../src/lib/number/number.ts","../src/lib/queue/flushPolicy.ts","../src/lib/singleton/StatefulRuntimeSingleton.ts","../src/lib/queue/QueueFlushRuntime.ts","../src/queues/ExperienceQueue.ts","../src/queues/InsightsQueue.ts","../src/CoreStateful.ts","../src/CoreStateless.ts","../src/lib/decorators/guardedBy.ts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/naming-convention -- Replaced at build-time\ndeclare const __OPTIMIZATION_VERSION__: string | undefined\n// eslint-disable-next-line @typescript-eslint/naming-convention -- Replaced at build-time\ndeclare const __OPTIMIZATION_PACKAGE_NAME__: string | undefined\n\n/**\n * The current version of the Optimization Core SDK, injected at build time.\n *\n * @public\n */\nexport const OPTIMIZATION_CORE_SDK_VERSION =\n typeof __OPTIMIZATION_VERSION__ === 'string' ? __OPTIMIZATION_VERSION__ : '0.0.0'\n/**\n * The package name of the Optimization Core SDK, injected at build time.\n *\n * @public\n */\nexport const OPTIMIZATION_CORE_SDK_NAME =\n typeof __OPTIMIZATION_PACKAGE_NAME__ === 'string'\n ? __OPTIMIZATION_PACKAGE_NAME__\n : '@contentful/optimization-core'\n\n/**\n * Anonymous-ID cookie name used by the Optimization Core.\n *\n * @public\n * @remarks\n * This constant represents the cookie key used by the Optimization Framework\n * to persist an anonymous identifier for tracking optimization and insights\n * events when no explicit profile is known.\n *\n * @example\n * ```ts\n * import { ANONYMOUS_ID_COOKIE } from '@contentful/optimization-core/constants'\n * const profileId = request.cookies[ANONYMOUS_ID_COOKIE]\n * ```\n */\nexport const ANONYMOUS_ID_COOKIE = 'ctfl-opt-aid'\n\n/**\n * Storage key for the anonymous identifier.\n *\n * @internal\n */\nexport const ANONYMOUS_ID_KEY = '__ctfl_opt_anonymous_id__'\n\n/**\n * Storage key for the persisted consent status.\n *\n * @internal\n */\nexport const CONSENT_KEY = '__ctfl_opt_consent__'\n\n/**\n * Storage key for cached Custom Flags.\n *\n * @internal\n */\nexport const CHANGES_CACHE_KEY = '__ctfl_opt_changes__'\n\n/**\n * Storage key for the debug flag toggle.\n *\n * @internal\n */\nexport const DEBUG_FLAG_KEY = '__ctfl_opt_debug__'\n\n/**\n * Storage key for cached profile data.\n *\n * @internal\n */\nexport const PROFILE_CACHE_KEY = '__ctfl_opt_profile__'\n\n/**\n * Storage key for cached selected optimizations.\n *\n * @internal\n */\nexport const SELECTED_OPTIMIZATIONS_CACHE_KEY = '__ctfl_opt_selected-optimizations__'\n\n/**\n * Legacy anoynmous ID cookie key for migration from experience.js\n *\n * @internal\n */\nexport const ANONYMOUS_ID_COOKIE_LEGACY = 'ntaid'\n\n/**\n * Legacy anoynmous ID storage key for migration from experience.js\n *\n * @internal\n */\nexport const ANONYMOUS_ID_KEY_LEGACY = '__nt_anonymous_id__'\n","/**\n * Well-known symbols used by the preview panel bridge.\n *\n * @public\n */\nexport const PREVIEW_PANEL_SIGNALS_SYMBOL = Symbol.for('ctfl.optimization.preview.signals')\nexport const PREVIEW_PANEL_SIGNAL_FNS_SYMBOL = Symbol.for('ctfl.optimization.preview.signalFns')\n","// getDefaultExport function for compatibility with non-ESM modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};\n","__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { effect } from '@preact/signals-core'\nimport { cloneDeep } from 'es-toolkit'\n\n/**\n * Disposable handle returned by observable subscriptions.\n *\n * @public\n */\nexport interface Subscription {\n /** Stop receiving future emissions for the subscription. */\n unsubscribe: () => void\n}\n\n/**\n * Minimal observable contract used by stateful Core signal streams.\n *\n * @typeParam T - Value type emitted by the observable.\n * @public\n */\nexport interface Observable<T> {\n /**\n * Deep-cloned snapshot of the current signal value.\n *\n * @remarks\n * A clone is returned to prevent accidental in-place mutations from leaking\n * back into internal signal state.\n */\n readonly current: T\n /**\n * Subscribe to all value updates (including the current value immediately).\n *\n * @param next - Callback invoked for each emitted value snapshot.\n * @returns A {@link Subscription} used to stop observing updates.\n *\n * @remarks\n * Values are deep-cloned before being passed to `next`.\n */\n subscribe: (next: (v: T) => void) => Subscription\n /**\n * Subscribe to the first non-nullish value, then auto-unsubscribe.\n *\n * @param next - Callback invoked exactly once with the first non-nullish value.\n * @returns A {@link Subscription} that can cancel before the first emission.\n *\n * @remarks\n * Values are deep-cloned before being passed to `next`.\n */\n subscribeOnce: (next: (v: NonNullable<T>) => void) => Subscription\n}\n\nfunction isNonNullish<TValue>(value: TValue): value is NonNullable<TValue> {\n return value !== undefined && value !== null\n}\n\nfunction toError(value: unknown): Error {\n if (value instanceof Error) return value\n return new Error(`Subscriber threw non-Error value: ${String(value)}`)\n}\n\n/**\n * Wrap a signal-like object with the local {@link Observable} contract.\n *\n * @typeParam T - Signal value type.\n * @param s - Signal-like source exposing a `value` property.\n * @returns Observable adapter for the given signal source.\n *\n * @remarks\n * All emitted values and `current` snapshots are deep-cloned to isolate\n * subscriber-side mutation from internal Core state.\n *\n * @public\n */\nexport function toObservable<T>(s: { value: T }): Observable<T> {\n return {\n get current() {\n return cloneDeep(s.value)\n },\n\n subscribe(next) {\n const dispose = effect(() => {\n next(cloneDeep(s.value))\n })\n\n return { unsubscribe: dispose }\n },\n\n subscribeOnce(next) {\n let closed = false\n let isEffectActive = false\n let dispose: () => void = () => undefined\n\n const stop = (): void => {\n if (closed) return\n closed = true\n\n if (isEffectActive) dispose()\n }\n\n dispose = effect(() => {\n if (closed) return\n\n const { value } = s\n if (!isNonNullish(value)) return\n\n closed = true\n\n let callbackError: Error | null = null\n try {\n next(cloneDeep(value))\n } catch (error) {\n callbackError = toError(error)\n }\n\n if (isEffectActive) {\n dispose()\n } else {\n queueMicrotask(dispose)\n }\n\n if (callbackError) throw callbackError\n })\n\n isEffectActive = true\n\n return { unsubscribe: stop }\n },\n }\n}\n\n/**\n * Wrap a signal-like object with an {@link Observable} that suppresses\n * duplicate emissions according to a comparator.\n *\n * @typeParam T - Signal value type.\n * @param s - Signal-like source exposing a `value` property.\n * @param isEqual - Comparator that returns `true` when values are equivalent.\n * @returns Observable adapter that only emits distinct values.\n *\n * @remarks\n * The first emission is always delivered. Subsequent emissions are skipped\n * when `isEqual(previous, current)` returns `true`.\n *\n * @public\n */\nexport function toDistinctObservable<T>(\n s: { value: T },\n isEqual: (previous: T, current: T) => boolean,\n): Observable<T> {\n const observable = toObservable(s)\n\n return {\n get current() {\n return observable.current\n },\n\n subscribe(next) {\n let hasPrevious = false\n let previous = cloneDeep(observable.current)\n\n return observable.subscribe((value) => {\n if (hasPrevious && isEqual(previous, value)) return\n\n hasPrevious = true\n previous = cloneDeep(value)\n next(value)\n })\n },\n\n subscribeOnce(next) {\n return observable.subscribeOnce(next)\n },\n }\n}\n","import type {\n InsightsEvent as AnalyticsEvent,\n ChangeArray,\n ExperienceEvent as OptimizationEvent,\n Profile,\n SelectedOptimizationArray,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { batch, computed, effect, signal, type Signal, untracked } from '@preact/signals-core'\nimport type { BlockedEvent } from '../BlockedEvent'\n\n/**\n * Latest optimization changes returned by the Experience API.\n *\n * @public\n */\nexport const changes: Signal<ChangeArray | undefined> = signal<ChangeArray | undefined>()\n\n/**\n * Most recent blocked-event metadata produced by consent/runtime guards.\n *\n * @public\n */\nexport const blockedEvent: Signal<BlockedEvent | undefined> = signal<BlockedEvent | undefined>()\n\n/**\n * Current optimization/analytics consent state.\n *\n * @public\n */\nexport const consent = signal<boolean | undefined>()\n\n/**\n * Most recent emitted optimization event.\n *\n * @public\n */\nexport const event: Signal<AnalyticsEvent | OptimizationEvent | undefined> = signal<\n AnalyticsEvent | OptimizationEvent | undefined\n>()\n\n/**\n * Runtime online/offline signal used by queue flush logic.\n *\n * @defaultValue `true`\n * @public\n */\nexport const online = signal<boolean | undefined>(true)\n\n/**\n * Indicates whether the preview panel bridge has been attached.\n *\n * @defaultValue `false`\n * @public\n */\nexport const previewPanelAttached = signal<boolean>(false)\n\n/**\n * Indicates whether the preview panel is currently open.\n *\n * @defaultValue `false`\n * @public\n */\nexport const previewPanelOpen = signal<boolean>(false)\n\n/**\n * Latest selected optimization variants.\n *\n * @public\n */\nexport const selectedOptimizations = signal<SelectedOptimizationArray | undefined>()\n\n/**\n * Whether optimization selection data is available for entry resolution.\n *\n * @public\n */\nexport const canOptimize = computed<boolean>(() => selectedOptimizations.value !== undefined)\n\n/**\n * Active profile associated with current runtime state.\n *\n * @public\n */\nexport const profile: Signal<Profile | undefined> = signal<Profile | undefined>()\n\n/**\n * Collection of shared stateful Core signals.\n *\n * @public\n */\nexport interface Signals {\n /** Most recent blocked-event metadata. */\n blockedEvent: typeof blockedEvent\n /** Latest optimization changes payload. */\n changes: typeof changes\n /** Current consent signal. */\n consent: typeof consent\n /** Most recent emitted event signal. */\n event: typeof event\n /** Runtime connectivity signal. */\n online: typeof online\n /** Preview panel attachment signal. */\n previewPanelAttached: typeof previewPanelAttached\n /** Preview panel open-state signal. */\n previewPanelOpen: typeof previewPanelOpen\n /** Selected optimization variants signal. */\n selectedOptimizations: typeof selectedOptimizations\n /** Whether optimization selection data is currently available. */\n canOptimize: typeof canOptimize\n /** Active profile signal. */\n profile: typeof profile\n}\n\n/**\n * Signal utility functions shared with preview tooling and extensions.\n *\n * @public\n */\nexport interface SignalFns {\n /** Execute multiple signal writes in one reactive batch. */\n batch: typeof batch\n /** Create a derived computed signal. */\n computed: typeof computed\n /** Register a reactive effect. */\n effect: typeof effect\n /** Read signal values without dependency tracking. */\n untracked: typeof untracked\n}\n\n/**\n * Pre-bundled reference to all shared signals.\n *\n * @public\n */\nexport const signals: Signals = {\n blockedEvent,\n changes,\n consent,\n event,\n online,\n previewPanelAttached,\n previewPanelOpen,\n selectedOptimizations,\n canOptimize,\n profile,\n}\n\n/**\n * Pre-bundled reference to shared signal helpers.\n *\n * @public\n */\nexport const signalFns: SignalFns = {\n batch,\n computed,\n effect,\n untracked,\n}\n\nexport { batch, effect, type Signal }\n","import {\n type App,\n Campaign,\n type Channel,\n type ClickEvent,\n GeoLocation,\n type HoverEvent,\n type IdentifyEvent,\n type Library,\n Page,\n PageEventContext,\n type PageViewEvent,\n parseWithFriendlyError,\n Properties,\n Screen,\n ScreenEventContext,\n type ScreenViewEvent,\n type TrackEvent,\n Traits,\n type UniversalEventProperties,\n type ViewEvent,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { merge } from 'es-toolkit/object'\nimport * as z from 'zod/mini'\n\n/**\n * Configuration options for creating an {@link EventBuilder} instance.\n *\n * @remarks\n * The configuration is typically provided by the host application to adapt\n * event payloads to the runtime environment (browser, framework, etc.).\n *\n * @example\n * ```ts\n * const builder = new EventBuilder({\n * app: { name: 'my-app', version: '1.0.0' },\n * channel: 'web',\n * library: { name: '@contentful/optimization-sdk', version: '1.2.3' },\n * getLocale: () => navigator.language,\n * getPageProperties: () => ({\n * path: window.location.pathname,\n * url: window.location.href,\n * title: document.title,\n * query: {},\n * referrer: document.referrer,\n * search: window.location.search,\n * }),\n * })\n * ```\n *\n * @public\n */\nexport interface EventBuilderConfig {\n /**\n * The application definition used to attribute events to a specific consumer app.\n *\n * @remarks\n * When not provided, events will not contain app metadata in their context.\n */\n app?: App\n\n /**\n * The channel that identifies where events originate from (e.g. web, mobile).\n *\n * @see {@link Channel}\n */\n channel: Channel\n\n /**\n * The client library metadata that is attached to all events.\n *\n * @remarks\n * This is typically used to record the library name and version.\n */\n library: Library\n\n /**\n * Function used to resolve the locale for outgoing events.\n *\n * @remarks\n * If not provided, the builder falls back to the default `'en-US'`. Locale\n * values supplied directly as arguments to event builder methods take\n * precedence.\n *\n * @returns The locale string (e.g. `'en-US'`), or `undefined` if unavailable.\n */\n getLocale?: () => string | undefined\n\n /**\n * Function that returns the current page properties.\n *\n * @remarks\n * Page properties are currently added to the context of all events, as well\n * as the `properties` of the page event. When specified, all properties of\n * the `Page` type are required, but may contain empty values.\n *\n * @returns A {@link Page} object containing information about the current page.\n * @see {@link Page}\n */\n getPageProperties?: () => Page\n\n /**\n * Function used to obtain the current user agent string when applicable.\n *\n * @returns A user agent string, or `undefined` if unavailable.\n */\n getUserAgent?: () => string | undefined\n}\n\nexport const UniversalEventBuilderArgs = z.object({\n campaign: z.optional(Campaign),\n locale: z.optional(z.string()),\n location: z.optional(GeoLocation),\n page: z.optional(Page),\n screen: z.optional(Screen),\n userAgent: z.optional(z.string()),\n})\n\n/**\n * Arguments used to construct the universal (shared) portion of all events.\n *\n * @public\n */\nexport type UniversalEventBuilderArgs = z.infer<typeof UniversalEventBuilderArgs>\n\nexport const EntryInteractionBuilderArgsBase = z.extend(UniversalEventBuilderArgs, {\n componentId: z.string(),\n experienceId: z.optional(z.string()),\n variantIndex: z.optional(z.number()),\n})\n\n/**\n * Arguments shared by entry view, click, and hover events.\n *\n * @public\n */\nexport type EntryInteractionBuilderArgsBase = z.infer<typeof EntryInteractionBuilderArgsBase>\n\nexport const ViewBuilderArgs = z.extend(EntryInteractionBuilderArgsBase, {\n sticky: z.optional(z.boolean()),\n viewId: z.string(),\n viewDurationMs: z.number(),\n})\n\n/**\n * Arguments for constructing entry view events.\n *\n * @public\n */\nexport type ViewBuilderArgs = z.infer<typeof ViewBuilderArgs>\n\nexport const FlagViewBuilderArgs = z.extend(EntryInteractionBuilderArgsBase, {\n viewId: z.optional(z.string()),\n viewDurationMs: z.optional(z.number()),\n})\n\n/**\n * Arguments for constructing Custom Flag view events.\n *\n * @public\n */\nexport type FlagViewBuilderArgs = z.infer<typeof FlagViewBuilderArgs>\n\nexport const ClickBuilderArgs = EntryInteractionBuilderArgsBase\n\n/**\n * Arguments for constructing entry click events.\n *\n * @public\n */\nexport type ClickBuilderArgs = z.infer<typeof ClickBuilderArgs>\n\nexport const HoverBuilderArgs = z.extend(EntryInteractionBuilderArgsBase, {\n hoverId: z.string(),\n hoverDurationMs: z.number(),\n})\n\n/**\n * Arguments for constructing entry hover events.\n *\n * @public\n */\nexport type HoverBuilderArgs = z.infer<typeof HoverBuilderArgs>\n\nexport const IdentifyBuilderArgs = z.extend(UniversalEventBuilderArgs, {\n traits: z.optional(Traits),\n userId: z.string(),\n})\n\n/**\n * Arguments for constructing identify events.\n *\n * @remarks\n * Traits are merged by the API; only specified properties may be overwritten.\n *\n * @public\n */\nexport type IdentifyBuilderArgs = z.infer<typeof IdentifyBuilderArgs>\n\nexport const PageViewBuilderArgs = z.extend(UniversalEventBuilderArgs, {\n properties: z.optional(z.partial(Page)),\n})\n\n/**\n * Arguments for constructing page view events.\n *\n * @remarks\n * Any properties passed here are merged with the base page properties from\n * {@link EventBuilderConfig.getPageProperties}.\n *\n * @public\n */\nexport type PageViewBuilderArgs = z.infer<typeof PageViewBuilderArgs>\n\nexport const ScreenViewBuilderArgs = z.extend(UniversalEventBuilderArgs, {\n name: z.string(),\n properties: Properties,\n})\n\n/**\n * Arguments for constructing screen view events.\n *\n * @remarks\n * Any properties passed here are merged with the base screen properties supplied\n * by the runtime.\n *\n * @public\n */\nexport type ScreenViewBuilderArgs = z.infer<typeof ScreenViewBuilderArgs>\n\nexport const TrackBuilderArgs = z.extend(UniversalEventBuilderArgs, {\n event: z.string(),\n properties: z.optional(z.prefault(Properties, {})),\n})\n\n/**\n * Arguments for constructing track events.\n *\n * @public\n */\nexport type TrackBuilderArgs = z.infer<typeof TrackBuilderArgs>\n\n/**\n * Default page properties used when no explicit page information is available.\n *\n * @defaultValue\n * ```ts\n * {\n * path: '',\n * query: {},\n * referrer: '',\n * search: '',\n * title: '',\n * url: '',\n * }\n * ```\n *\n * @remarks\n * Values are required by the API; values may not be `undefined`. Empty values are valid.\n *\n * @public\n */\nexport const DEFAULT_PAGE_PROPERTIES = {\n path: '',\n query: {},\n referrer: '',\n search: '',\n title: '',\n url: '',\n}\n\n/**\n * Helper class for building optimization events.\n *\n * @remarks\n * This class coordinates configuration and argument validation to produce\n * strongly-typed event payloads compatible with\n * `@contentful/optimization-api-schemas`.\n *\n * @see {@link EventBuilderConfig}\n *\n * @public\n */\nclass EventBuilder {\n /**\n * Application metadata attached to each event.\n *\n * @internal\n */\n app?: App\n\n /**\n * Channel value attached to each event.\n *\n * @internal\n */\n channel: Channel\n\n /**\n * Library metadata attached to each event.\n *\n * @internal\n */\n library: Library\n\n /**\n * Function that provides the locale when available.\n *\n * @internal\n */\n getLocale: () => string | undefined\n\n /**\n * Function that provides baseline page properties.\n *\n * @internal\n */\n getPageProperties: () => Page\n\n /**\n * Function that provides the user agent string when available.\n *\n * @internal\n */\n getUserAgent: () => string | undefined\n\n /**\n * Creates a new {@link EventBuilder} instance.\n *\n * @param config - Configuration used to customize event payloads.\n *\n * @remarks\n * Callers are expected to reuse a single instance when possible to avoid\n * repeatedly reconfiguring the builder.\n *\n * @example\n * ```ts\n * const builder = new EventBuilder({\n * channel: 'web',\n * library: { name: '@contentful/optimization-sdk', version: '1.0.0' },\n * })\n * ```\n */\n constructor(config: EventBuilderConfig) {\n const { app, channel, library, getLocale, getPageProperties, getUserAgent } = config\n this.app = app\n this.channel = channel\n this.library = library\n this.getLocale = getLocale ?? (() => 'en-US')\n this.getPageProperties = getPageProperties ?? (() => DEFAULT_PAGE_PROPERTIES)\n this.getUserAgent = getUserAgent ?? (() => undefined)\n }\n\n /**\n * Builds the universal event properties shared across all event types.\n *\n * @param args - Arguments overriding the default context values.\n * @returns A fully populated {@link UniversalEventProperties} object.\n *\n * @remarks\n * This method is used internally by the specific event-builder methods\n * (e.g. {@link EventBuilder.buildPageView}).\n */\n protected buildUniversalEventProperties({\n campaign = {},\n locale,\n location,\n page,\n screen,\n userAgent,\n }: UniversalEventBuilderArgs): UniversalEventProperties {\n const timestamp = new Date().toISOString()\n\n return {\n channel: this.channel,\n context: {\n app: this.app,\n campaign,\n gdpr: { isConsentGiven: true },\n library: this.library,\n locale: locale ?? this.getLocale() ?? 'en-US',\n location,\n page: page ?? this.getPageProperties(),\n screen,\n userAgent: userAgent ?? this.getUserAgent(),\n },\n messageId: crypto.randomUUID(),\n originalTimestamp: timestamp,\n sentAt: timestamp,\n timestamp,\n }\n }\n\n private buildEntryInteractionBase(\n universal: UniversalEventBuilderArgs,\n componentId: string,\n experienceId: string | undefined,\n variantIndex: number | undefined,\n ): UniversalEventProperties & {\n componentType: 'Entry'\n componentId: string\n experienceId?: string\n variantIndex: number\n } {\n return {\n ...this.buildUniversalEventProperties(universal),\n componentType: 'Entry',\n componentId,\n experienceId,\n variantIndex: variantIndex ?? 0,\n }\n }\n\n /**\n * Builds a `component` view event payload for entry exposure tracking.\n *\n * @param args - {@link ViewBuilderArgs} arguments describing the entry view.\n * @returns A {@link ViewEvent} describing the view.\n *\n * @example\n * ```ts\n * const event = builder.buildView({\n * componentId: 'entry-123',\n * viewId: crypto.randomUUID(),\n * experienceId: 'experience-123',\n * variantIndex: 1,\n * viewDurationMs: 1_000,\n * })\n * ```\n *\n * @public\n */\n buildView(args: ViewBuilderArgs): ViewEvent {\n const { componentId, viewId, experienceId, variantIndex, viewDurationMs, ...universal } =\n parseWithFriendlyError(ViewBuilderArgs, args)\n\n return {\n ...this.buildEntryInteractionBase(universal, componentId, experienceId, variantIndex),\n type: 'component',\n viewId,\n viewDurationMs,\n }\n }\n\n /**\n * Builds a `component_click` payload for entry click tracking.\n *\n * @param args - {@link ClickBuilderArgs} arguments describing the entry click.\n * @returns A {@link ClickEvent} describing the click.\n *\n * @example\n * ```ts\n * const event = builder.buildClick({\n * componentId: 'entry-123',\n * experienceId: 'experience-123',\n * variantIndex: 1,\n * })\n * ```\n *\n * @public\n */\n buildClick(args: ClickBuilderArgs): ClickEvent {\n const { componentId, experienceId, variantIndex, ...universal } = parseWithFriendlyError(\n ClickBuilderArgs,\n args,\n )\n\n return {\n ...this.buildEntryInteractionBase(universal, componentId, experienceId, variantIndex),\n type: 'component_click',\n }\n }\n\n /**\n * Builds a `component_hover` payload for entry hover tracking.\n *\n * @param args - {@link HoverBuilderArgs} arguments describing the entry hover.\n * @returns A {@link HoverEvent} describing the hover.\n *\n * @example\n * ```ts\n * const event = builder.buildHover({\n * componentId: 'entry-123',\n * hoverId: crypto.randomUUID(),\n * experienceId: 'experience-123',\n * hoverDurationMs: 1_000,\n * variantIndex: 1,\n * })\n * ```\n *\n * @public\n */\n buildHover(args: HoverBuilderArgs): HoverEvent {\n const { hoverId, componentId, experienceId, hoverDurationMs, variantIndex, ...universal } =\n parseWithFriendlyError(HoverBuilderArgs, args)\n\n return {\n ...this.buildEntryInteractionBase(universal, componentId, experienceId, variantIndex),\n type: 'component_hover',\n hoverId,\n hoverDurationMs,\n }\n }\n\n /**\n * Builds a `component` view event payload for Custom Flag exposure tracking.\n *\n * @param args - {@link FlagViewBuilderArgs} arguments describing the Custom Flag view.\n * @returns A {@link ViewEvent} describing the view.\n *\n * @remarks\n * This is a specialized variant of {@link EventBuilder.buildView}\n * that sets `componentType` to `'Variable'`.\n *\n * @example\n * ```ts\n * const event = builder.buildFlagView({\n * componentId: 'feature-flag-key',\n * viewId: crypto.randomUUID(),\n * experienceId: 'experience-123',\n * viewDurationMs: 1_000,\n * })\n * ```\n *\n * @public\n */\n buildFlagView(args: FlagViewBuilderArgs): ViewEvent {\n const { componentId, experienceId, variantIndex, viewId, viewDurationMs, ...universal } =\n parseWithFriendlyError(FlagViewBuilderArgs, args)\n\n return {\n ...this.buildEntryInteractionBase(universal, componentId, experienceId, variantIndex),\n ...(viewDurationMs === undefined ? {} : { viewDurationMs }),\n ...(viewId === undefined ? {} : { viewId }),\n type: 'component',\n componentType: 'Variable',\n }\n }\n\n /**\n * Builds an identify event payload to associate a user ID with traits.\n *\n * @param args - {@link IdentifyBuilderArgs} arguments describing the identified user.\n * @returns An {@link IdentifyEvent} payload.\n *\n * @remarks\n * - Traits are merged by the API; only specified properties may be overwritten.\n * - The User ID is consumer-specified and should not contain the value of any\n * ID generated by the Experience API.\n *\n * @example\n * ```ts\n * const event = builder.buildIdentify({\n * userId: 'user-123',\n * traits: { plan: 'pro' },\n * })\n * ```\n *\n * @public\n */\n buildIdentify(args: IdentifyBuilderArgs): IdentifyEvent {\n const { traits = {}, userId, ...universal } = parseWithFriendlyError(IdentifyBuilderArgs, args)\n\n return {\n ...this.buildUniversalEventProperties(universal),\n type: 'identify',\n traits,\n userId,\n }\n }\n\n /**\n * Builds a page view event payload.\n *\n * @param args - Optional {@link PageViewBuilderArgs} overrides for the page view event.\n * @returns A {@link PageViewEvent} payload.\n *\n * @remarks\n * Page properties are created by merging:\n * 1. The base page properties from {@link EventBuilderConfig.getPageProperties}, and\n * 2. The partial `properties` argument passed in.\n *\n * The title always falls back to {@link DEFAULT_PAGE_PROPERTIES}.title when undefined.\n *\n * @example\n * ```ts\n * const event = builder.buildPageView({\n * properties: {\n * title: 'Homepage',\n * },\n * })\n * ```\n *\n * @public\n */\n buildPageView(args: PageViewBuilderArgs = {}): PageViewEvent {\n const { properties = {}, ...universal } = parseWithFriendlyError(PageViewBuilderArgs, args)\n\n const pageProperties = this.getPageProperties()\n\n const merged = merge(\n {\n ...pageProperties,\n title: pageProperties.title ?? DEFAULT_PAGE_PROPERTIES.title,\n },\n properties,\n )\n\n const {\n context: { screen: _, ...universalContext },\n ...universalProperties\n } = this.buildUniversalEventProperties(universal)\n\n const context = parseWithFriendlyError(PageEventContext, universalContext)\n\n return {\n ...universalProperties,\n context,\n type: 'page',\n properties: merged,\n }\n }\n\n /**\n * Builds a screen view event payload.\n *\n * @param args - {@link ScreenViewBuilderArgs} arguments for the screen view event.\n * @returns A {@link ScreenViewEvent} payload.\n *\n * @example\n * ```ts\n * const event = builder.buildScreenView({\n * name: 'home',\n * properties: {\n * title: 'Home Screen',\n * },\n * })\n * ```\n *\n * @public\n */\n buildScreenView(args: ScreenViewBuilderArgs): ScreenViewEvent {\n const { name, properties, ...universal } = parseWithFriendlyError(ScreenViewBuilderArgs, args)\n\n const {\n context: { page: _, ...universalContext },\n ...universalProperties\n } = this.buildUniversalEventProperties(universal)\n\n const context = parseWithFriendlyError(ScreenEventContext, universalContext)\n\n return {\n ...universalProperties,\n context,\n type: 'screen',\n name,\n properties,\n }\n }\n\n /**\n * Builds a track event payload for arbitrary user actions.\n *\n * @param args - {@link TrackBuilderArgs} arguments describing the tracked event.\n * @returns A {@link TrackEvent} payload.\n *\n * @example\n * ```ts\n * const event = builder.buildTrack({\n * event: 'button_clicked',\n * properties: { id: 'primary-cta', location: 'hero' },\n * })\n * ```\n *\n * @public\n */\n buildTrack(args: TrackBuilderArgs): TrackEvent {\n const { event, properties = {}, ...universal } = parseWithFriendlyError(TrackBuilderArgs, args)\n\n return {\n ...this.buildUniversalEventProperties(universal),\n type: 'track',\n event,\n properties,\n }\n }\n}\n\nexport default EventBuilder\n","import { cloneDeep } from 'es-toolkit'\n\n/**\n * A utility type representing a value that may be synchronously available or\n * produced asynchronously.\n *\n * @typeParam T - The resolved value type.\n * @public\n */\nexport type MaybePromise<T> = T | Promise<T>\n\n/**\n * A function that receives a value of type `T` and returns a (possibly async)\n * value of the same type `T`. The input is marked as `readonly` to discourage\n * mutation of the original object.\n *\n * @typeParam T - The value type intercepted and returned.\n * @param value - The current (readonly) value in the interception chain.\n * @returns The next value for the chain, either directly or via a promise.\n * @remarks Implementations SHOULD avoid mutating `value` and instead return a\n * new or safely-updated instance.\n * @see {@link InterceptorManager}\n * @public\n */\nexport type Interceptor<T> = (value: Readonly<T>) => MaybePromise<T>\n\n/**\n * Manages a list of interceptors and provides a way to run them in sequence.\n *\n * Interceptors are executed in insertion order. Each interceptor receives the\n * result of the previous interceptor (or the initial input for the first one)\n * and may return a new value synchronously or asynchronously.\n *\n * @typeParam T - The value type processed by the interceptors.\n * @remarks This class snapshots the current interceptor list at invocation time\n * so additions/removals during `run` do not affect the in-flight execution.\n * @example\n * ```ts\n * const mgr = new InterceptorManager<number>();\n * const id = mgr.add((n) => n + 1);\n * const final = await mgr.run(1); // 2\n * mgr.remove(id);\n * ```\n * @public\n */\nexport class InterceptorManager<T> {\n /**\n * The registry of interceptors keyed by their insertion id.\n *\n * @privateRemarks Internal storage; use {@link add}, {@link remove}, and\n * {@link clear} to manage contents.\n * @readonly\n * @defaultValue `new Map()`\n */\n private readonly interceptors = new Map<number, Interceptor<T>>()\n\n /**\n * The next numeric id to assign to an added interceptor.\n *\n * @privateRemarks Used only to generate unique, monotonically increasing ids.\n * @defaultValue `0`\n */\n private nextId = 0\n\n /**\n * Add an interceptor and return its identifier.\n *\n * @param interceptor - The interceptor function to register.\n * @returns The numeric id that can later be used with {@link remove}.\n * @remarks Interceptors are executed in the order they are added.\n * @example\n * ```ts\n * const id = manager.add(async (value) => transform(value));\n * ```\n * @public\n */\n add(interceptor: Interceptor<T>): number {\n const { nextId: id } = this\n this.nextId += 1\n this.interceptors.set(id, interceptor)\n return id\n }\n\n /**\n * Remove an interceptor by its identifier.\n *\n * @param id - The id previously returned by {@link add}.\n * @returns `true` if an interceptor was removed; otherwise `false`.\n * @example\n * ```ts\n * const removed = manager.remove(id);\n * ```\n * @public\n */\n remove(id: number): boolean {\n return this.interceptors.delete(id)\n }\n\n /**\n * Remove all registered interceptors.\n *\n * @returns Nothing.\n * @remarks After calling this, {@link count} will return `0`.\n * @example\n * ```ts\n * manager.clear();\n * ```\n * @public\n */\n clear(): void {\n this.interceptors.clear()\n }\n\n /**\n * Get the number of currently registered interceptors.\n *\n * @returns The count of interceptors.\n * @example\n * ```ts\n * if (manager.count() === 0) { /* ... *\\/ }\n * ```\n * @public\n */\n count(): number {\n return this.interceptors.size\n }\n\n /**\n * Run all interceptors in sequence on an input value and return the final result.\n *\n * Supports both sync and async interceptors; the return type is always `Promise<T>`\n * for consistency.\n *\n * @param input - The initial value to pass to the first interceptor.\n * @returns A promise resolving to the final value after all interceptors have run.\n * @throws May rethrow any error thrown by an interceptor. <!-- Intentionally vague: error type depends on interceptor implementation -->\n * @remarks The interceptor list is snapshotted at invocation time; changes to\n * the registry during execution do not affect the running sequence.\n * @example\n * ```ts\n * const result = await manager.run(initial);\n * ```\n * @public\n */\n async run(input: T): Promise<T> {\n // Snapshot to avoid issues if interceptors are added/removed during execution.\n const fns: ReadonlyArray<Interceptor<T>> = Array.from(this.interceptors.values())\n\n let acc: T = input\n\n for (const fn of fns) {\n // Pass a deep-cloned readonly view to prevent in-place interceptor\n // mutations from affecting references held outside the interceptor chain.\n acc = await fn(cloneDeep(acc))\n }\n\n return acc\n }\n}\n","import type { ChangeArray, Flags } from '@contentful/optimization-api-client/api-schemas'\n\n/**\n * Resolves a {@link Flags} map from a list of optimization changes.\n *\n * @public\n * @remarks\n * Given an Optimization {@link ChangeArray}, this utility flattens the list into a\n * simple key–value object suitable for quick lookups in client code. When `changes`\n * is `undefined`, an empty object is returned. If a change value is wrapped in an\n * object like `{ value: { ... } }`, this resolver unwraps it to the underlying object.\n */\nconst FlagsResolver = {\n /**\n * Build a flattened map of flag keys to values from a change list.\n *\n * @param changes - The change list returned by the optimization service.\n * @returns A map of flag keys to their resolved values.\n * @example\n * ```ts\n * const flags = FlagsResolver.resolve(data.changes)\n * if (flags['theme'] === 'dark') enableDarkMode()\n * ```\n * @example\n * // Handles wrapped values produced by the API\n * ```ts\n * const flags = FlagsResolver.resolve([\n * { type: 'Variable', key: 'price', value: { value: { amount: 10, currency: 'USD' } } }\n * ])\n * console.log(flags.price.amount) // 10\n * ```\n */\n resolve(changes?: ChangeArray): Flags {\n if (!changes) return {}\n\n return changes.reduce<Flags>((acc, { key, value }) => {\n const actualValue =\n typeof value === 'object' &&\n value !== null &&\n 'value' in value &&\n typeof value.value === 'object'\n ? value.value\n : value\n\n acc[key] = actualValue\n\n return acc\n }, {})\n },\n}\n\nexport default FlagsResolver\n","import type { MergeTagEntry } from '@contentful/optimization-api-client/api-schemas'\nimport { Profile, isMergeTagEntry } from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger } from '@contentful/optimization-api-client/logger'\n\nconst logger = createScopedLogger('Optimization')\n\n/**\n * Base string for log messages when merge-tag resolution fails.\n *\n * @internal\n */\nconst RESOLUTION_WARNING_BASE = 'Could not resolve Merge Tag value:'\n\nconst getAtPath = (value: unknown, path: string): unknown => {\n if (!value || typeof value !== 'object') return undefined\n if (!path) return value\n\n let current: unknown = value\n const segments = path.split('.').filter(Boolean)\n\n for (const segment of segments) {\n if (!current || (typeof current !== 'object' && typeof current !== 'function')) return undefined\n current = Reflect.get(current, segment)\n }\n\n return current\n}\n\n/**\n * Resolves merge tag values from a {@link Profile}.\n *\n * @public\n * @remarks\n * *Merge tags* are references to user profile data that may be embedded in content\n * and expanded at runtime. This resolver normalizes the merge-tag identifier into\n * a set of candidate selectors and searches the profile for a matching value.\n * Result values are returned as strings; numeric/boolean primitives are stringified.\n */\nconst MergeTagValueResolver = {\n /**\n * Generate a list of candidate selectors for a merge-tag ID.\n *\n * @param id - Merge-tag identifier (segments separated by `_`).\n * @returns Array of dot-path selectors to try against a profile.\n * @example\n * ```ts\n * // \"profile_name_first\" -> [\n * // 'profile',\n * // 'profile.name',\n * // 'profile.name.first'\n * // ]\n * const selectors = MergeTagValueResolver.normalizeSelectors('profile_name_first')\n * ```\n */\n normalizeSelectors(id: string): string[] {\n return id.split('_').map((_path, index, paths) => {\n const dotPath = paths.slice(0, index).join('.')\n const underScorePath = paths.slice(index).join('_')\n\n return [dotPath, underScorePath].filter((path) => path !== '').join('.')\n })\n },\n\n /**\n * Look up a merge-tag value from a profile using normalized selectors.\n *\n * @param id - Merge-tag identifier.\n * @param profile - Profile from which to resolve the value.\n * @returns A stringified primitive if found; otherwise `undefined`.\n * @remarks\n * Only string/number/boolean primitives are returned; objects/arrays are ignored.\n * @example\n * ```ts\n * const value = MergeTagValueResolver.getValueFromProfile('user_email', profile)\n * if (value) sendEmailTo(value)\n * ```\n */\n getValueFromProfile(id: string, profile?: Profile): string | undefined {\n const selectors = MergeTagValueResolver.normalizeSelectors(id)\n const matchingSelector = selectors.find((selector) => getAtPath(profile, selector))\n\n if (!matchingSelector) return undefined\n\n const value = getAtPath(profile, matchingSelector)\n\n if (\n !value ||\n (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean')\n )\n return undefined\n\n return `${value}`\n },\n\n /**\n * Resolve the display value for a merge-tag entry using the provided profile,\n * falling back to the entry's configured `nt_fallback` when necessary.\n *\n * @param mergeTagEntry - The merge-tag entry to resolve.\n * @param profile - Optional profile used for lookup.\n * @returns The resolved string, or `undefined` if the entry is invalid and no\n * fallback is available.\n * @remarks\n * The resolved value depends on the current request profile, so callers\n * should not reuse rendered output across users or requests unless the\n * cache varies on the same profile inputs.\n * @example\n * ```ts\n * const text = MergeTagValueResolver.resolve(entry, profile)\n * render(text ?? 'Guest')\n * ```\n */\n resolve(mergeTagEntry: MergeTagEntry | undefined, profile?: Profile): string | undefined {\n if (!isMergeTagEntry(mergeTagEntry)) {\n logger.warn(`${RESOLUTION_WARNING_BASE} supplied entry is not a Merge Tag entry`)\n return\n }\n\n const {\n fields: { nt_fallback: fallback },\n } = mergeTagEntry\n\n if (!Profile.safeParse(profile).success) {\n logger.warn(`${RESOLUTION_WARNING_BASE} no valid profile`)\n return fallback\n }\n\n return (\n MergeTagValueResolver.getValueFromProfile(mergeTagEntry.fields.nt_mergetag_id, profile) ??\n fallback\n )\n },\n}\n\nexport default MergeTagValueResolver\n","import {\n type EntryReplacementComponent,\n type EntryReplacementVariant,\n isEntry,\n isEntryReplacementComponent,\n isEntryReplacementVariant,\n isOptimizationEntry,\n isOptimizedEntry,\n normalizeOptimizationConfig,\n type OptimizationEntry,\n type OptimizedEntry,\n type SelectedOptimization,\n type SelectedOptimizationArray,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger } from '@contentful/optimization-api-client/logger'\nimport type { ChainModifiers, Entry, EntrySkeletonType, LocaleCode } from 'contentful'\n\nconst logger = createScopedLogger('Optimization')\n\n/**\n * Result returned by {@link OptimizedEntryResolver.resolve}.\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam M - Chain modifiers.\n * @typeParam L - Locale code.\n * @public\n */\nexport interface ResolvedData<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n> {\n /** The baseline or resolved variant entry. */\n entry: Entry<S, M, L>\n /** The selected optimization metadata, if a non-baseline variant was chosen. */\n selectedOptimization?: SelectedOptimization\n}\n\n/**\n * Base string for resolver warning messages.\n *\n * @internal\n */\nconst RESOLUTION_WARNING_BASE = 'Could not resolve optimized entry variant:'\n\n/**\n * Resolve the selected entry (baseline or variant) for an optimized entry\n * and optional selected optimizations, returning both the entry and the\n * optimization metadata.\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam L - Locale code.\n * @typeParam M - Chain modifiers for advanced/non-default Contentful clients.\n * @param entry - The baseline optimized entry.\n * @param selectedOptimizations - Optional selections for the current profile.\n * @returns An object containing the resolved entry and (if chosen) the selection.\n * @example\n * ```ts\n * const { entry: optimizedEntry, selectedOptimization } = OptimizedEntryResolver.resolve(\n * entry,\n * selections,\n * )\n * if (selectedOptimization) {\n * console.log('Variant index', selectedOptimization.variantIndex)\n * }\n * ```\n */\nfunction resolve<\n S extends EntrySkeletonType = EntrySkeletonType,\n L extends LocaleCode = LocaleCode,\n>(\n entry: Entry<S, undefined, L>,\n selectedOptimizations?: SelectedOptimizationArray,\n): ResolvedData<S, undefined, L>\nfunction resolve<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n>(entry: Entry<S, M, L>, selectedOptimizations?: SelectedOptimizationArray): ResolvedData<S, M, L>\nfunction resolve<\n S extends EntrySkeletonType,\n M extends ChainModifiers,\n L extends LocaleCode = LocaleCode,\n>(entry: Entry<S, M, L>, selectedOptimizations?: SelectedOptimizationArray): ResolvedData<S, M, L> {\n logger.debug(`Resolving optimized entry for baseline entry ${entry.sys.id}`)\n\n if (!selectedOptimizations?.length) {\n logger.warn(`${RESOLUTION_WARNING_BASE} no selectedOptimizations exist for the current profile`)\n return { entry }\n }\n\n if (!isOptimizedEntry(entry)) {\n logger.warn(`${RESOLUTION_WARNING_BASE} entry ${entry.sys.id} is not optimized`)\n return { entry }\n }\n\n const optimizationEntry = OptimizedEntryResolver.getOptimizationEntry(\n {\n optimizedEntry: entry,\n selectedOptimizations,\n },\n true,\n )\n\n if (!optimizationEntry) {\n logger.warn(\n `${RESOLUTION_WARNING_BASE} could not find an optimization entry for ${entry.sys.id}`,\n )\n return { entry }\n }\n\n const selectedOptimization = OptimizedEntryResolver.getSelectedOptimization(\n {\n optimizationEntry,\n selectedOptimizations,\n },\n true,\n )\n\n const selectedVariantIndex = selectedOptimization?.variantIndex ?? 0\n\n if (selectedVariantIndex === 0) {\n logger.debug(`Resolved optimization entry for entry ${entry.sys.id} is baseline`)\n\n return { entry }\n }\n\n const selectedVariant = OptimizedEntryResolver.getSelectedVariant(\n {\n optimizedEntry: entry,\n optimizationEntry,\n selectedVariantIndex,\n },\n true,\n )\n\n if (!selectedVariant) {\n logger.warn(\n `${RESOLUTION_WARNING_BASE} could not find a valid replacement variant entry for ${entry.sys.id}`,\n )\n return { entry }\n }\n\n const selectedVariantEntry = OptimizedEntryResolver.getSelectedVariantEntry<S, M, L>(\n {\n optimizationEntry,\n selectedVariant,\n },\n true,\n )\n\n if (!selectedVariantEntry) {\n logger.warn(\n `${RESOLUTION_WARNING_BASE} could not find a valid replacement variant entry for ${entry.sys.id}`,\n )\n return { entry }\n } else {\n logger.debug(\n `Entry ${entry.sys.id} has been resolved to variant entry ${selectedVariantEntry.sys.id}`,\n )\n }\n\n return { entry: selectedVariantEntry, selectedOptimization }\n}\n\n/**\n * Resolve an optimized Contentful entry to the correct variant for the current\n * selections.\n *\n * @public\n * @remarks\n * Given a baseline {@link OptimizedEntry} and a set of selected optimizations\n * (variants per experience), this resolver finds the matching replacement variant\n * for the component configured against the baseline entry.\n *\n * **Variant indexing**: `variantIndex` in {@link SelectedOptimization} is treated as\n * 1‑based (index 1 = first variant). A value of `0` indicates baseline.\n */\nconst OptimizedEntryResolver = {\n /**\n * Find the optimization entry corresponding to one of the selected experiences.\n *\n * @param params - Object containing the baseline optimized entry and the selections.\n * @param skipValidation - When `true`, skip type/shape validation for perf.\n * @returns The matching {@link OptimizationEntry}, or `undefined` if not found/invalid.\n * @remarks\n * An optimization entry is an optimization configuration object supplied in an\n * `OptimizedEntry.nt_experiences` array. An optimized entry may relate to\n * multiple optimizations.\n * @example\n * ```ts\n * const optimizationEntry = OptimizedEntryResolver.getOptimizationEntry({\n * optimizedEntry: entry,\n * selectedOptimizations\n * })\n * ```\n */\n getOptimizationEntry(\n {\n optimizedEntry,\n selectedOptimizations,\n }: {\n optimizedEntry: OptimizedEntry\n selectedOptimizations: SelectedOptimizationArray\n },\n skipValidation = false,\n ): OptimizationEntry | undefined {\n if (!skipValidation && (!selectedOptimizations.length || !isOptimizedEntry(optimizedEntry)))\n return\n\n const optimizationEntry = optimizedEntry.fields.nt_experiences\n .filter((maybeOptimization) => isOptimizationEntry(maybeOptimization))\n .find((optimizationEntry) =>\n selectedOptimizations.some(\n ({ experienceId }) => experienceId === optimizationEntry.fields.nt_experience_id,\n ),\n )\n\n return optimizationEntry\n },\n\n /**\n * Look up the selection metadata for a specific optimization entry.\n *\n * @param params - Object with the target optimization entry and selections.\n * @param skipValidation - When `true`, skip type checks.\n * @returns The matching {@link SelectedOptimization}, if present.\n * @remarks\n * Selected optimizations are supplied by the Experience API in the\n * `experiences` response data property.\n * @example\n * ```ts\n * const selectedOptimization = OptimizedEntryResolver.getSelectedOptimization({\n * optimizationEntry,\n * selectedOptimizations\n * })\n * ```\n */\n getSelectedOptimization(\n {\n optimizationEntry,\n selectedOptimizations,\n }: {\n optimizationEntry: OptimizationEntry\n selectedOptimizations: SelectedOptimizationArray\n },\n skipValidation = false,\n ): SelectedOptimization | undefined {\n if (\n !skipValidation &&\n (!selectedOptimizations.length || !isOptimizationEntry(optimizationEntry))\n )\n return\n\n const selectedOptimization = selectedOptimizations.find(\n ({ experienceId }) => experienceId === optimizationEntry.fields.nt_experience_id,\n )\n\n return selectedOptimization\n },\n\n /**\n * Get the replacement variant config for the given selection index.\n *\n * @param params - Baseline entry, optimization entry, and 1‑based variant index.\n * @param skipValidation - When `true`, skip type checks.\n * @returns The {@link EntryReplacementVariant} for the component, if any.\n * @remarks\n * Entry replacement variants are variant configurations specified in a\n * optimization configuration component's `variants` array supplied by the\n * optimized entry via its `nt_config` field.\n * @example\n * ```ts\n * const selectedVariant = OptimizedEntryResolver.getSelectedVariant({\n * optimizedEntry: entry,\n * optimizationEntry,\n * selectedVariantIndex: 2 // second variant (1‑based)\n * })\n * ```\n */\n getSelectedVariant(\n {\n optimizedEntry,\n optimizationEntry,\n selectedVariantIndex,\n }: {\n optimizedEntry: OptimizedEntry\n optimizationEntry: OptimizationEntry\n selectedVariantIndex: number\n },\n skipValidation = false,\n ): EntryReplacementVariant | undefined {\n if (\n !skipValidation &&\n (!isOptimizedEntry(optimizedEntry) || !isOptimizationEntry(optimizationEntry))\n )\n return\n\n const relevantVariants = normalizeOptimizationConfig(optimizationEntry.fields.nt_config)\n .components.filter(\n (component): component is EntryReplacementComponent =>\n isEntryReplacementComponent(component) && !component.baseline.hidden,\n )\n .find((component) => component.baseline.id === optimizedEntry.sys.id)?.variants\n\n if (!relevantVariants?.length) return\n\n return relevantVariants.at(selectedVariantIndex - 1)\n },\n\n /**\n * Resolve the concrete Contentful entry that corresponds to a selected variant.\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam M - Chain modifiers.\n * @typeParam L - Locale code.\n * @param params - Optimization entry and selected variant.\n * @param skipValidation - When `true`, skip type checks.\n * @returns The resolved entry typed as {@link Entry} or `undefined`.\n * @remarks\n * An optimized entry will resolve either to the baseline (the entry\n * supplied as `optimizedEntry`) or the selected variant.\n * @example\n * ```ts\n * const selectedVariantEntry = OptimizedEntryResolver.getSelectedVariantEntry<{ fields: unknown }>({\n * optimizationEntry,\n * selectedVariant\n * })\n * ```\n */\n getSelectedVariantEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(\n {\n optimizationEntry,\n selectedVariant,\n }: {\n optimizationEntry: OptimizationEntry\n selectedVariant: EntryReplacementVariant\n },\n skipValidation = false,\n ): Entry<S, M, L> | undefined {\n if (\n !skipValidation &&\n (!isOptimizationEntry(optimizationEntry) || !isEntryReplacementVariant(selectedVariant))\n )\n return\n\n const selectedVariantEntry = optimizationEntry.fields.nt_variants?.find(\n (variant) => variant.sys.id === selectedVariant.id,\n )\n\n return isEntry<S, M, L>(selectedVariantEntry) ? selectedVariantEntry : undefined\n },\n\n resolve,\n}\n\nexport default OptimizedEntryResolver\n","import {\n ApiClient,\n type ApiClientConfig,\n type GlobalApiConfigProperties,\n} from '@contentful/optimization-api-client'\nimport type {\n ChangeArray,\n ExperienceEvent as ExperienceEventPayload,\n InsightsEvent as InsightsEventPayload,\n Json,\n MergeTagEntry,\n OptimizationData,\n Profile,\n SelectedOptimizationArray,\n} from '@contentful/optimization-api-client/api-schemas'\nimport type { LogLevels } from '@contentful/optimization-api-client/logger'\nimport { ConsoleLogSink, logger } from '@contentful/optimization-api-client/logger'\nimport type { ChainModifiers, Entry, EntrySkeletonType, LocaleCode } from 'contentful'\nimport { OPTIMIZATION_CORE_SDK_NAME, OPTIMIZATION_CORE_SDK_VERSION } from './constants'\nimport { EventBuilder, type EventBuilderConfig } from './events'\nimport { InterceptorManager } from './lib/interceptor'\nimport type { ResolvedData } from './resolvers'\nimport { FlagsResolver, MergeTagValueResolver, OptimizedEntryResolver } from './resolvers'\n\n/**\n * Lifecycle container for event and state interceptors.\n *\n * @public\n */\nexport interface LifecycleInterceptors {\n /** Interceptors invoked for individual events prior to validation/sending. */\n event: InterceptorManager<InsightsEventPayload | ExperienceEventPayload>\n /** Interceptors invoked before optimization state updates. */\n state: InterceptorManager<OptimizationData>\n}\n\n/**\n * Options for configuring the `CoreBase` runtime and underlying clients.\n *\n * @public\n */\nexport interface CoreConfig extends Pick<ApiClientConfig, GlobalApiConfigProperties> {\n /**\n * Event builder configuration (channel/library metadata, etc.).\n */\n eventBuilder?: EventBuilderConfig\n\n /** Minimum log level for the default console sink. */\n logLevel?: LogLevels\n}\n\ninterface CoreBaseApiClientConfig {\n experience?: ApiClientConfig['experience']\n insights?: ApiClientConfig['insights']\n}\n\n/**\n * Internal base that wires the API client, event builder, and logging.\n *\n * @internal\n */\nabstract class CoreBase<TConfig extends CoreConfig = CoreConfig> {\n /** Shared Optimization API client instance. */\n readonly api: ApiClient\n /** Shared event builder instance. */\n readonly eventBuilder: EventBuilder\n /** Resolved core configuration. */\n readonly config: TConfig\n /** Static resolver for evaluating optimized custom flags. */\n readonly flagsResolver = FlagsResolver\n /** Static resolver for merge-tag lookups against profile data. */\n readonly mergeTagValueResolver = MergeTagValueResolver\n /** Static resolver for optimized Contentful entries. */\n readonly optimizedEntryResolver = OptimizedEntryResolver\n\n /** Lifecycle interceptors for events and state updates. */\n readonly interceptors: LifecycleInterceptors = {\n event: new InterceptorManager<InsightsEventPayload | ExperienceEventPayload>(),\n state: new InterceptorManager<OptimizationData>(),\n }\n\n /**\n * Create the core with API client and logging preconfigured.\n *\n * @param config - Core configuration including API and builder options.\n * @example\n * ```ts\n * const sdk = new CoreStateless({ clientId: 'abc123', environment: 'prod' })\n * ```\n */\n constructor(config: TConfig, api: CoreBaseApiClientConfig = {}) {\n this.config = config\n\n const { eventBuilder, logLevel, environment, clientId, fetchOptions } = config\n\n logger.addSink(new ConsoleLogSink(logLevel))\n\n const apiConfig: ApiClientConfig = {\n clientId,\n environment,\n fetchOptions,\n experience: api.experience,\n insights: api.insights,\n }\n\n this.api = new ApiClient(apiConfig)\n\n this.eventBuilder = new EventBuilder(\n eventBuilder ?? {\n channel: 'server',\n library: { name: OPTIMIZATION_CORE_SDK_NAME, version: OPTIMIZATION_CORE_SDK_VERSION },\n },\n )\n }\n\n /**\n * Get the value of a custom flag derived from a set of optimization changes.\n *\n * @param name - The flag key to resolve.\n * @param changes - Optional change list to resolve from.\n * @returns The resolved JSON value for the flag if available.\n * @remarks\n * This is a convenience wrapper around Core's shared flag resolution.\n * @example\n * ```ts\n * const darkMode = core.getFlag('dark-mode', data.changes)\n * ```\n */\n getFlag(name: string, changes?: ChangeArray): Json {\n return this.flagsResolver.resolve(changes)[name]\n }\n\n /**\n * Resolve a Contentful entry to the appropriate optimized variant (or\n * return the baseline entry if no matching variant is selected).\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam M - Chain modifiers.\n * @typeParam L - Locale code.\n * @param entry - The baseline entry to resolve.\n * @param selectedOptimizations - Optional selected optimization array for the current profile.\n * @returns {@link ResolvedData} containing the resolved entry and\n * selected optimization metadata (if any).\n * @remarks\n * This helper is intended for request-local resolution. When the supplied\n * entry comes from a shared application cache, avoid mutating the returned\n * entry in place unless you first clone it.\n * @example\n * ```ts\n * const { entry, selectedOptimization } = core.resolveOptimizedEntry(\n * baselineEntry,\n * data.selectedOptimizations,\n * )\n * ```\n */\n resolveOptimizedEntry<\n S extends EntrySkeletonType = EntrySkeletonType,\n L extends LocaleCode = LocaleCode,\n >(\n entry: Entry<S, undefined, L>,\n selectedOptimizations?: SelectedOptimizationArray,\n ): ResolvedData<S, undefined, L>\n resolveOptimizedEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(entry: Entry<S, M, L>, selectedOptimizations?: SelectedOptimizationArray): ResolvedData<S, M, L>\n resolveOptimizedEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(\n entry: Entry<S, M, L>,\n selectedOptimizations?: SelectedOptimizationArray,\n ): ResolvedData<S, M, L> {\n return this.optimizedEntryResolver.resolve<S, M, L>(entry, selectedOptimizations)\n }\n\n /**\n * Resolve a merge-tag value from the given entry node and profile.\n *\n * @param embeddedEntryNodeTarget - The merge-tag entry node to resolve.\n * @param profile - Optional profile used for value lookup.\n * @returns The resolved value (typically a string) or `undefined` if not found.\n * @remarks\n * Use this during request rendering with the current profile. The resolved\n * value is profile-dependent and is not safe for shared-output caching.\n * @example\n * ```ts\n * const name = core.getMergeTagValue(mergeTagNode, profile)\n * ```\n */\n getMergeTagValue(embeddedEntryNodeTarget: MergeTagEntry, profile?: Profile): string | undefined {\n return this.mergeTagValueResolver.resolve(embeddedEntryNodeTarget, profile)\n }\n}\n\nexport default CoreBase\n","import type {\n ChangeArray,\n ExperienceEvent as ExperienceEventPayload,\n InsightsEvent as InsightsEventPayload,\n Json,\n MergeTagEntry,\n OptimizationData,\n PartialProfile,\n Profile,\n SelectedOptimizationArray,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger, logger } from '@contentful/optimization-api-client/logger'\nimport type { ChainModifiers, Entry, EntrySkeletonType, LocaleCode } from 'contentful'\nimport { isEqual } from 'es-toolkit/predicate'\nimport type { BlockedEvent } from './BlockedEvent'\nimport type { ConsentGuard } from './Consent'\nimport CoreBase from './CoreBase'\nimport type { CoreStatefulConfig, EventType } from './CoreStateful'\nimport type {\n ClickBuilderArgs,\n FlagViewBuilderArgs,\n HoverBuilderArgs,\n IdentifyBuilderArgs,\n PageViewBuilderArgs,\n ScreenViewBuilderArgs,\n TrackBuilderArgs,\n ViewBuilderArgs,\n} from './events'\nimport type { ExperienceQueue } from './queues/ExperienceQueue'\nimport type { InsightsQueue } from './queues/InsightsQueue'\nimport type { ResolvedData } from './resolvers'\nimport {\n blockedEvent as blockedEventSignal,\n changes as changesSignal,\n consent as consentSignal,\n type Observable,\n profile as profileSignal,\n selectedOptimizations as selectedOptimizationsSignal,\n signalFns,\n toDistinctObservable,\n} from './signals'\n\nconst coreLogger = createScopedLogger('CoreStateful')\n\nconst CONSENT_EVENT_TYPE_MAP: Readonly<Partial<Record<string, EventType>>> = {\n trackView: 'component',\n trackFlagView: 'component',\n trackClick: 'component_click',\n trackHover: 'component_hover',\n}\n\n/**\n * Shared stateful event-emission surface extracted to keep `CoreStateful.ts`\n * below the local max-lines limit while preserving the public API.\n *\n * @internal\n */\nabstract class CoreStatefulEventEmitter\n extends CoreBase<CoreStatefulConfig>\n implements ConsentGuard\n{\n protected readonly flagObservables = new Map<string, Observable<Json>>()\n\n protected abstract readonly allowedEventTypes: EventType[]\n protected abstract readonly experienceQueue: ExperienceQueue\n protected abstract readonly insightsQueue: InsightsQueue\n protected abstract readonly onEventBlocked?: CoreStatefulConfig['onEventBlocked']\n\n override getFlag(name: string, changes: ChangeArray | undefined = changesSignal.value): Json {\n const value = super.getFlag(name, changes)\n const payload = this.buildFlagViewBuilderArgs(name, changes)\n\n void this.trackFlagView(payload).catch((error: unknown) => {\n logger.warn(`Failed to emit \"flag view\" event for \"${name}\"`, String(error))\n })\n\n return value\n }\n\n override resolveOptimizedEntry<\n S extends EntrySkeletonType = EntrySkeletonType,\n L extends LocaleCode = LocaleCode,\n >(\n entry: Entry<S, undefined, L>,\n selectedOptimizations?: SelectedOptimizationArray,\n ): ResolvedData<S, undefined, L>\n override resolveOptimizedEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(entry: Entry<S, M, L>, selectedOptimizations?: SelectedOptimizationArray): ResolvedData<S, M, L>\n override resolveOptimizedEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(\n entry: Entry<S, M, L>,\n selectedOptimizations:\n | SelectedOptimizationArray\n | undefined = selectedOptimizationsSignal.value,\n ): ResolvedData<S, M, L> {\n return super.resolveOptimizedEntry(entry, selectedOptimizations)\n }\n\n override getMergeTagValue(\n embeddedEntryNodeTarget: MergeTagEntry,\n profile: Profile | undefined = profileSignal.value,\n ): string | undefined {\n return super.getMergeTagValue(embeddedEntryNodeTarget, profile)\n }\n\n /**\n * Convenience wrapper for sending an `identify` event through the Experience path.\n *\n * @param payload - Identify builder arguments.\n * @returns The resulting {@link OptimizationData} for the identified user.\n * @example\n * ```ts\n * const data = await core.identify({ userId: 'user-123', traits: { plan: 'pro' } })\n * ```\n */\n async identify(\n payload: IdentifyBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData | undefined> {\n const { profile, ...builderArgs } = payload\n return await this.sendExperienceEvent(\n 'identify',\n [payload],\n this.eventBuilder.buildIdentify(builderArgs),\n profile,\n )\n }\n\n /**\n * Convenience wrapper for sending a `page` event through the Experience path.\n *\n * @param payload - Page view builder arguments.\n * @returns The evaluated {@link OptimizationData} for this page view.\n * @example\n * ```ts\n * const data = await core.page({ properties: { title: 'Home' } })\n * ```\n */\n async page(\n payload: PageViewBuilderArgs & { profile?: PartialProfile } = {},\n ): Promise<OptimizationData | undefined> {\n const { profile, ...builderArgs } = payload\n return await this.sendExperienceEvent(\n 'page',\n [payload],\n this.eventBuilder.buildPageView(builderArgs),\n profile,\n )\n }\n\n /**\n * Convenience wrapper for sending a `screen` event through the Experience path.\n *\n * @param payload - Screen view builder arguments.\n * @returns The evaluated {@link OptimizationData} for this screen view.\n * @example\n * ```ts\n * const data = await core.screen({ name: 'HomeScreen' })\n * ```\n */\n async screen(\n payload: ScreenViewBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData | undefined> {\n const { profile, ...builderArgs } = payload\n return await this.sendExperienceEvent(\n 'screen',\n [payload],\n this.eventBuilder.buildScreenView(builderArgs),\n profile,\n )\n }\n\n /**\n * Convenience wrapper for sending a custom `track` event through the Experience path.\n *\n * @param payload - Track builder arguments.\n * @returns The evaluated {@link OptimizationData} for this event.\n * @example\n * ```ts\n * const data = await core.track({ event: 'button_click', properties: { label: 'Buy' } })\n * ```\n */\n async track(\n payload: TrackBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData | undefined> {\n const { profile, ...builderArgs } = payload\n return await this.sendExperienceEvent(\n 'track',\n [payload],\n this.eventBuilder.buildTrack(builderArgs),\n profile,\n )\n }\n\n /**\n * Track an entry view through Insights and, when sticky, Experience.\n *\n * @param payload - Entry view builder arguments. When `payload.sticky` is\n * `true`, the event will also be sent through Experience as a sticky\n * entry view.\n * @returns A promise that resolves when all delegated calls complete.\n * @remarks\n * Experience receives sticky entry views only; Insights is always invoked\n * regardless of `sticky`.\n * @example\n * ```ts\n * await core.trackView({ componentId: 'entry-123', sticky: true })\n * ```\n */\n async trackView(\n payload: ViewBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData | undefined> {\n const { profile, ...builderArgs } = payload\n let result: OptimizationData | undefined = undefined\n\n if (payload.sticky) {\n result = await this.sendExperienceEvent(\n 'trackView',\n [payload],\n this.eventBuilder.buildView(builderArgs),\n profile,\n )\n }\n await this.sendInsightsEvent(\n 'trackView',\n [payload],\n this.eventBuilder.buildView(builderArgs),\n profile,\n )\n\n return result\n }\n\n /**\n * Track an entry click through Insights.\n *\n * @param payload - Entry click builder arguments.\n * @returns A promise that resolves when processing completes.\n * @example\n * ```ts\n * await core.trackClick({ componentId: 'entry-123' })\n * ```\n */\n async trackClick(payload: ClickBuilderArgs): Promise<void> {\n await this.sendInsightsEvent('trackClick', [payload], this.eventBuilder.buildClick(payload))\n }\n\n /**\n * Track an entry hover through Insights.\n *\n * @param payload - Entry hover builder arguments.\n * @returns A promise that resolves when processing completes.\n * @example\n * ```ts\n * await core.trackHover({ componentId: 'entry-123' })\n * ```\n */\n async trackHover(payload: HoverBuilderArgs): Promise<void> {\n await this.sendInsightsEvent('trackHover', [payload], this.eventBuilder.buildHover(payload))\n }\n\n /**\n * Track a feature flag view through Insights.\n *\n * @param payload - Flag view builder arguments used to build the flag view event.\n * @returns A promise that resolves when processing completes.\n * @example\n * ```ts\n * await core.trackFlagView({ componentId: 'feature-flag-123' })\n * ```\n */\n async trackFlagView(payload: FlagViewBuilderArgs): Promise<void> {\n await this.sendInsightsEvent(\n 'trackFlagView',\n [payload],\n this.eventBuilder.buildFlagView(payload),\n )\n }\n\n hasConsent(name: string): boolean {\n const { [name]: mappedEventType } = CONSENT_EVENT_TYPE_MAP\n const isAllowed =\n mappedEventType !== undefined\n ? this.allowedEventTypes.includes(mappedEventType)\n : this.allowedEventTypes.some((eventType) => eventType === name)\n\n return !!consentSignal.value || isAllowed\n }\n\n onBlockedByConsent(name: string, args: readonly unknown[]): void {\n coreLogger.warn(\n `Event \"${name}\" was blocked due to lack of consent; payload: ${JSON.stringify(args)}`,\n )\n this.reportBlockedEvent('consent', name, args)\n }\n\n protected async sendExperienceEvent(\n method: string,\n args: readonly unknown[],\n event: ExperienceEventPayload,\n _profile?: PartialProfile,\n ): Promise<OptimizationData | undefined> {\n if (!this.hasConsent(method)) {\n this.onBlockedByConsent(method, args)\n return undefined\n }\n\n return await this.experienceQueue.send(event)\n }\n\n protected async sendInsightsEvent(\n method: string,\n args: readonly unknown[],\n event: InsightsEventPayload,\n _profile?: PartialProfile,\n ): Promise<void> {\n if (!this.hasConsent(method)) {\n this.onBlockedByConsent(method, args)\n return\n }\n\n await this.insightsQueue.send(event)\n }\n\n private buildFlagViewBuilderArgs(\n name: string,\n changes: ChangeArray | undefined = changesSignal.value,\n ): FlagViewBuilderArgs {\n const change = changes?.find((candidate) => candidate.key === name)\n\n return {\n componentId: name,\n experienceId: change?.meta.experienceId,\n variantIndex: change?.meta.variantIndex,\n }\n }\n\n protected getFlagObservable(name: string): Observable<Json> {\n const existingObservable = this.flagObservables.get(name)\n if (existingObservable) return existingObservable\n\n const trackFlagView = this.trackFlagView.bind(this)\n const buildFlagViewBuilderArgs = this.buildFlagViewBuilderArgs.bind(this)\n const valueSignal = signalFns.computed<Json>(() => super.getFlag(name, changesSignal.value))\n const distinctObservable = toDistinctObservable(valueSignal, isEqual)\n\n const trackedObservable: Observable<Json> = {\n get current() {\n const { current: value } = distinctObservable\n const payload = buildFlagViewBuilderArgs(name, changesSignal.value)\n\n void trackFlagView(payload).catch((error: unknown) => {\n logger.warn(`Failed to emit \"flag view\" event for \"${name}\"`, String(error))\n })\n\n return value\n },\n\n subscribe: (next) =>\n distinctObservable.subscribe((value) => {\n const payload = buildFlagViewBuilderArgs(name, changesSignal.value)\n\n void trackFlagView(payload).catch((error: unknown) => {\n logger.warn(`Failed to emit \"flag view\" event for \"${name}\"`, String(error))\n })\n next(value)\n }),\n\n subscribeOnce: (next) =>\n distinctObservable.subscribeOnce((value) => {\n const payload = buildFlagViewBuilderArgs(name, changesSignal.value)\n\n void trackFlagView(payload).catch((error: unknown) => {\n logger.warn(`Failed to emit \"flag view\" event for \"${name}\"`, String(error))\n })\n next(value)\n }),\n }\n\n this.flagObservables.set(name, trackedObservable)\n\n return trackedObservable\n }\n\n private reportBlockedEvent(\n reason: BlockedEvent['reason'],\n method: string,\n args: readonly unknown[],\n ): void {\n const event: BlockedEvent = { reason, method, args }\n\n try {\n this.onEventBlocked?.(event)\n } catch (error) {\n coreLogger.warn(`onEventBlocked callback failed for method \"${method}\"`, error)\n }\n\n blockedEventSignal.value = event\n }\n}\n\nexport default CoreStatefulEventEmitter\n","/**\n * Normalize a candidate positive integer value with fallback.\n *\n * @param value - Incoming numeric value.\n * @param fallback - Fallback when value is invalid.\n * @returns Normalized positive integer.\n *\n * @internal\n */\nexport const toPositiveInt = (value: number | undefined, fallback: number): number => {\n if (!Number.isFinite(value) || value === undefined || value < 1) return fallback\n\n return Math.floor(value)\n}\n\n/**\n * Normalize a candidate ratio to the `[0, 1]` interval.\n *\n * @param value - Incoming ratio value.\n * @param fallback - Fallback when value is invalid.\n * @returns Normalized ratio.\n *\n * @internal\n */\nexport const toRatio = (value: number | undefined, fallback: number): number => {\n if (!Number.isFinite(value) || value === undefined) return fallback\n\n return Math.min(1, Math.max(0, value))\n}\n","import { toPositiveInt, toRatio } from '../number'\n\n/**\n * Context payload emitted when a queue flush fails.\n *\n * @public\n */\nexport interface QueueFlushFailureContext {\n /** Number of consecutive failed flush attempts. */\n consecutiveFailures: number\n /** Number of queued batches at the time of the failed attempt. */\n queuedBatches: number\n /** Number of queued events at the time of the failed attempt. */\n queuedEvents: number\n /** Delay before the next retry attempt is scheduled. */\n retryDelayMs: number\n}\n\n/**\n * Context payload emitted when a failed queue flush sequence recovers.\n *\n * @public\n */\nexport interface QueueFlushRecoveredContext {\n /** Consecutive failure count that existed immediately before recovery. */\n consecutiveFailures: number\n}\n\n/**\n * Policy options for controlling queue flush retry behavior.\n *\n * @public\n */\nexport interface QueueFlushPolicy {\n /**\n * Periodic flush interval in milliseconds while events remain queued.\n *\n * @defaultValue `30000`\n */\n flushIntervalMs?: number\n\n /**\n * Base retry backoff delay in milliseconds.\n *\n * @defaultValue `500`\n */\n baseBackoffMs?: number\n\n /**\n * Maximum retry backoff delay in milliseconds.\n *\n * @defaultValue `30000`\n */\n maxBackoffMs?: number\n\n /**\n * Jitter ratio applied to retry delay to avoid synchronized retries.\n *\n * @remarks\n * Value is clamped to `[0, 1]`.\n *\n * @defaultValue `0.2`\n */\n jitterRatio?: number\n\n /**\n * Consecutive failures threshold before opening the circuit window.\n *\n * @defaultValue `8`\n */\n maxConsecutiveFailures?: number\n\n /**\n * Duration in milliseconds to wait before retrying after circuit opens.\n *\n * @defaultValue `120000`\n */\n circuitOpenMs?: number\n\n /**\n * Callback invoked after each failed flush attempt.\n */\n onFlushFailure?: (context: QueueFlushFailureContext) => void\n\n /**\n * Callback invoked when the circuit opens after consecutive failures.\n */\n onCircuitOpen?: (context: QueueFlushFailureContext) => void\n\n /**\n * Callback invoked when a flush succeeds after previous failures.\n */\n onFlushRecovered?: (context: QueueFlushRecoveredContext) => void\n}\n\ninterface QueueFlushDefaults {\n flushIntervalMs: number\n baseBackoffMs: number\n maxBackoffMs: number\n jitterRatio: number\n maxConsecutiveFailures: number\n circuitOpenMs: number\n}\n\n/**\n * Default queue flush policy values.\n *\n * @internal\n */\nexport const DEFAULT_QUEUE_FLUSH_POLICY: QueueFlushDefaults = {\n flushIntervalMs: 30_000,\n baseBackoffMs: 500,\n maxBackoffMs: 30_000,\n jitterRatio: 0.2,\n maxConsecutiveFailures: 8,\n circuitOpenMs: 120_000,\n}\n\n/**\n * Internal normalized shape of queue flush policy values.\n *\n * @internal\n */\nexport interface ResolvedQueueFlushPolicy {\n flushIntervalMs: number\n baseBackoffMs: number\n maxBackoffMs: number\n jitterRatio: number\n maxConsecutiveFailures: number\n circuitOpenMs: number\n onCircuitOpen?: QueueFlushPolicy['onCircuitOpen']\n onFlushFailure?: QueueFlushPolicy['onFlushFailure']\n onFlushRecovered?: QueueFlushPolicy['onFlushRecovered']\n}\n\n/**\n * Resolve and normalize queue flush policy values.\n *\n * @param policy - Candidate queue flush policy configuration.\n * @param defaults - Optional fallback defaults.\n * @returns Normalized queue flush policy.\n *\n * @internal\n */\nexport const resolveQueueFlushPolicy = (\n policy: QueueFlushPolicy | undefined,\n defaults: QueueFlushDefaults = DEFAULT_QUEUE_FLUSH_POLICY,\n): ResolvedQueueFlushPolicy => {\n const configuredPolicy: QueueFlushPolicy = policy ?? {}\n const baseBackoffMs = toPositiveInt(configuredPolicy.baseBackoffMs, defaults.baseBackoffMs)\n const maxBackoffMs = Math.max(\n baseBackoffMs,\n toPositiveInt(configuredPolicy.maxBackoffMs, defaults.maxBackoffMs),\n )\n\n return {\n flushIntervalMs: toPositiveInt(configuredPolicy.flushIntervalMs, defaults.flushIntervalMs),\n baseBackoffMs,\n maxBackoffMs,\n jitterRatio: toRatio(configuredPolicy.jitterRatio, defaults.jitterRatio),\n maxConsecutiveFailures: toPositiveInt(\n configuredPolicy.maxConsecutiveFailures,\n defaults.maxConsecutiveFailures,\n ),\n circuitOpenMs: toPositiveInt(configuredPolicy.circuitOpenMs, defaults.circuitOpenMs),\n onCircuitOpen: configuredPolicy.onCircuitOpen,\n onFlushFailure: configuredPolicy.onFlushFailure,\n onFlushRecovered: configuredPolicy.onFlushRecovered,\n }\n}\n\n/**\n * Compute retry delay in milliseconds using exponential backoff plus jitter.\n *\n * @param options - Retry delay inputs.\n * @returns Backoff delay in milliseconds.\n *\n * @internal\n */\nexport const computeQueueFlushRetryDelayMs = (options: {\n consecutiveFailures: number\n policy: Pick<ResolvedQueueFlushPolicy, 'baseBackoffMs' | 'maxBackoffMs' | 'jitterRatio'>\n}): number => {\n const {\n consecutiveFailures,\n policy: { baseBackoffMs, jitterRatio, maxBackoffMs },\n } = options\n const exponential = baseBackoffMs * 2 ** Math.max(0, consecutiveFailures - 1)\n const capped = Math.min(maxBackoffMs, exponential)\n const jitter = capped * jitterRatio * Math.random()\n\n return Math.round(capped + jitter)\n}\n\n/**\n * Derived retry scheduling state after a failed flush attempt.\n *\n * @internal\n */\nexport interface QueueFlushFailureWindow {\n openedCircuit: boolean\n retryDelayMs: number\n nextFlushAllowedAt: number\n circuitOpenUntil: number\n}\n\n/**\n * Create the next retry scheduling window from a failed flush attempt.\n *\n * @param options - Failure window inputs.\n * @returns Derived retry scheduling state.\n *\n * @internal\n */\nexport const createQueueFlushFailureWindow = (options: {\n consecutiveFailures: number\n failureTimestamp: number\n retryDelayMs: number\n policy: Pick<ResolvedQueueFlushPolicy, 'maxConsecutiveFailures' | 'circuitOpenMs'>\n}): QueueFlushFailureWindow => {\n const {\n consecutiveFailures,\n failureTimestamp,\n retryDelayMs,\n policy: { maxConsecutiveFailures, circuitOpenMs },\n } = options\n\n if (consecutiveFailures < maxConsecutiveFailures) {\n return {\n openedCircuit: false,\n retryDelayMs,\n nextFlushAllowedAt: failureTimestamp + retryDelayMs,\n circuitOpenUntil: 0,\n }\n }\n\n const circuitOpenUntil = failureTimestamp + circuitOpenMs\n\n return {\n openedCircuit: true,\n retryDelayMs: circuitOpenMs,\n nextFlushAllowedAt: circuitOpenUntil,\n circuitOpenUntil,\n }\n}\n","const STATEFUL_RUNTIME_LOCK_KEY = '__ctfl_optimization_stateful_runtime_lock__'\n\ninterface StatefulRuntimeLockState {\n owner: string | undefined\n}\n\ntype SingletonGlobal = typeof globalThis & {\n __ctfl_optimization_stateful_runtime_lock__?: StatefulRuntimeLockState\n}\n\nconst getStatefulRuntimeLock = (): StatefulRuntimeLockState => {\n const singletonGlobal = globalThis as SingletonGlobal\n\n singletonGlobal[STATEFUL_RUNTIME_LOCK_KEY] ??= { owner: undefined }\n\n return singletonGlobal[STATEFUL_RUNTIME_LOCK_KEY]\n}\n\nexport const acquireStatefulRuntimeSingleton = (owner: string): void => {\n const lock = getStatefulRuntimeLock()\n\n if (lock.owner) {\n throw new Error(\n `Stateful Optimization SDK already initialized (${lock.owner}). Only one stateful instance is supported per runtime.`,\n )\n }\n\n lock.owner = owner\n}\n\nexport const releaseStatefulRuntimeSingleton = (owner: string): void => {\n const lock = getStatefulRuntimeLock()\n\n if (lock.owner === owner) {\n lock.owner = undefined\n }\n}\n","import {\n computeQueueFlushRetryDelayMs,\n createQueueFlushFailureWindow,\n type QueueFlushFailureContext,\n type QueueFlushRecoveredContext,\n type ResolvedQueueFlushPolicy,\n} from './flushPolicy'\n\n/**\n * Callback names for queue flush policy hooks.\n *\n * @internal\n */\nexport type QueueFlushCallbackName = 'onCircuitOpen' | 'onFlushFailure' | 'onFlushRecovered'\n\n/**\n * Construction options for {@link QueueFlushRuntime}.\n *\n * @internal\n */\ninterface QueueFlushRuntimeOptions {\n onCallbackError?: (callbackName: QueueFlushCallbackName, error: unknown) => void\n onRetry: () => void\n policy: ResolvedQueueFlushPolicy\n}\n\n/**\n * Shared runtime state machine for queue flush retry, backoff, and circuit behavior.\n *\n * @internal\n */\nexport class QueueFlushRuntime {\n private circuitOpenUntil = 0\n private flushFailureCount = 0\n private flushInFlight = false\n private nextFlushAllowedAt = 0\n private readonly onCallbackError?: QueueFlushRuntimeOptions['onCallbackError']\n private readonly onRetry: QueueFlushRuntimeOptions['onRetry']\n private readonly policy: QueueFlushRuntimeOptions['policy']\n private retryTimer: ReturnType<typeof setTimeout> | undefined\n\n constructor(options: QueueFlushRuntimeOptions) {\n const { onCallbackError, onRetry, policy } = options\n\n this.policy = policy\n this.onRetry = onRetry\n this.onCallbackError = onCallbackError\n }\n\n /**\n * Reset runtime state and clear any scheduled retry.\n */\n reset(): void {\n this.clearScheduledRetry()\n\n this.circuitOpenUntil = 0\n this.flushFailureCount = 0\n this.flushInFlight = false\n this.nextFlushAllowedAt = 0\n }\n\n /**\n * Clear the currently scheduled retry timer, if any.\n */\n clearScheduledRetry(): void {\n if (this.retryTimer === undefined) return\n\n clearTimeout(this.retryTimer)\n this.retryTimer = undefined\n }\n\n /**\n * Determine whether flush should be skipped due to current state gates.\n *\n * @param options - Flush gate options.\n * @param options.force - When true, bypass online/backoff/circuit gates.\n * @param options.isOnline - Whether connectivity gates permit flushing.\n * @returns `true` when flush should be skipped.\n */\n shouldSkip(options: { force: boolean; isOnline: boolean }): boolean {\n const { force, isOnline } = options\n\n if (this.flushInFlight) return true\n if (force) return false\n if (!isOnline) return true\n\n const now = Date.now()\n\n if (this.nextFlushAllowedAt > now) return true\n if (this.circuitOpenUntil > now) return true\n\n return false\n }\n\n /**\n * Mark a flush attempt as in flight.\n */\n markFlushStarted(): void {\n this.flushInFlight = true\n }\n\n /**\n * Mark a flush attempt as finished.\n */\n markFlushFinished(): void {\n this.flushInFlight = false\n }\n\n /**\n * Apply successful flush state transitions and invoke recovery callback as needed.\n */\n handleFlushSuccess(): void {\n const { flushFailureCount: previousConsecutiveFailures } = this\n\n this.clearScheduledRetry()\n\n this.circuitOpenUntil = 0\n this.flushFailureCount = 0\n this.nextFlushAllowedAt = 0\n\n if (previousConsecutiveFailures <= 0) return\n\n this.safeInvoke('onFlushRecovered', {\n consecutiveFailures: previousConsecutiveFailures,\n })\n }\n\n /**\n * Apply failed flush state transitions, invoke callbacks, and schedule retry.\n *\n * @param options - Failure inputs.\n * @param options.queuedBatches - Number of failed queued batches.\n * @param options.queuedEvents - Number of failed queued events.\n */\n handleFlushFailure(options: { queuedBatches: number; queuedEvents: number }): void {\n const { queuedBatches, queuedEvents } = options\n\n this.flushFailureCount += 1\n\n const retryDelayMs = computeQueueFlushRetryDelayMs({\n consecutiveFailures: this.flushFailureCount,\n policy: this.policy,\n })\n const failureTimestamp = Date.now()\n const failureContext: QueueFlushFailureContext = {\n consecutiveFailures: this.flushFailureCount,\n queuedBatches,\n queuedEvents,\n retryDelayMs,\n }\n\n this.safeInvoke('onFlushFailure', failureContext)\n\n const failureWindow = createQueueFlushFailureWindow({\n consecutiveFailures: this.flushFailureCount,\n failureTimestamp,\n retryDelayMs,\n policy: this.policy,\n })\n const {\n circuitOpenUntil,\n nextFlushAllowedAt,\n openedCircuit,\n retryDelayMs: scheduledRetryDelayMs,\n } = failureWindow\n\n this.nextFlushAllowedAt = nextFlushAllowedAt\n\n if (openedCircuit) {\n this.circuitOpenUntil = circuitOpenUntil\n this.safeInvoke('onCircuitOpen', {\n ...failureContext,\n retryDelayMs: scheduledRetryDelayMs,\n })\n }\n\n this.scheduleRetry(scheduledRetryDelayMs)\n }\n\n /**\n * Schedule a future flush attempt.\n *\n * @param delayMs - Delay in milliseconds before next attempt.\n */\n private scheduleRetry(delayMs: number): void {\n this.clearScheduledRetry()\n\n this.retryTimer = setTimeout(() => {\n this.retryTimer = undefined\n this.onRetry()\n }, delayMs)\n }\n\n /**\n * Invoke a policy callback in a fault-tolerant manner.\n *\n * @param callbackName - Callback key.\n * @param payload - Callback payload.\n */\n private safeInvoke(\n ...args:\n | ['onFlushRecovered', QueueFlushRecoveredContext]\n | ['onCircuitOpen' | 'onFlushFailure', QueueFlushFailureContext]\n ): void {\n const [callbackName, payload] = args\n\n try {\n if (callbackName === 'onFlushRecovered') {\n this.policy.onFlushRecovered?.(payload)\n return\n }\n\n if (callbackName === 'onCircuitOpen') {\n this.policy.onCircuitOpen?.(payload)\n return\n }\n\n this.policy.onFlushFailure?.(payload)\n } catch (error) {\n this.onCallbackError?.(callbackName, error)\n }\n }\n}\n","import {\n ExperienceEvent as ExperienceEventSchema,\n parseWithFriendlyError,\n type ExperienceEventArray,\n type ExperienceEvent as ExperienceEventPayload,\n type OptimizationData,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger } from '@contentful/optimization-api-client/logger'\nimport { isEqual } from 'es-toolkit/predicate'\nimport type { LifecycleInterceptors } from '../CoreBase'\nimport { QueueFlushRuntime, type ResolvedQueueFlushPolicy } from '../lib/queue'\nimport {\n batch,\n changes as changesSignal,\n event as eventSignal,\n online as onlineSignal,\n profile as profileSignal,\n selectedOptimizations as selectedOptimizationsSignal,\n} from '../signals'\n\nconst coreLogger = createScopedLogger('CoreStateful')\n\n/**\n * Context payload emitted when offline Experience events are dropped.\n *\n * @public\n */\nexport interface ExperienceQueueDropContext {\n /** Number of dropped events. */\n droppedCount: number\n /** Dropped events in oldest-first order. */\n droppedEvents: ExperienceEventArray\n /** Configured queue max size. */\n maxEvents: number\n /** Queue size after enqueueing the current event. */\n queuedEvents: number\n}\n\ninterface ExperienceQueueOptions {\n experienceApi: {\n upsertProfile: (payload: {\n profileId?: string\n events: ExperienceEventArray\n }) => Promise<OptimizationData>\n }\n eventInterceptors: LifecycleInterceptors['event']\n flushPolicy: ResolvedQueueFlushPolicy\n getAnonymousId: () => string | undefined\n offlineMaxEvents: number\n onOfflineDrop?: (context: ExperienceQueueDropContext) => void\n stateInterceptors: LifecycleInterceptors['state']\n}\n\n/**\n * Internal Experience send/offline runtime used by {@link CoreStateful}.\n *\n * @internal\n */\nexport class ExperienceQueue {\n private readonly experienceApi: ExperienceQueueOptions['experienceApi']\n private readonly eventInterceptors: ExperienceQueueOptions['eventInterceptors']\n private readonly flushRuntime: QueueFlushRuntime\n private readonly getAnonymousId: ExperienceQueueOptions['getAnonymousId']\n private readonly offlineMaxEvents: number\n private readonly onOfflineDrop?: ExperienceQueueOptions['onOfflineDrop']\n private readonly queuedExperienceEvents = new Set<ExperienceEventPayload>()\n private readonly stateInterceptors: ExperienceQueueOptions['stateInterceptors']\n\n constructor(options: ExperienceQueueOptions) {\n const {\n experienceApi,\n eventInterceptors,\n flushPolicy,\n getAnonymousId,\n offlineMaxEvents,\n onOfflineDrop,\n stateInterceptors,\n } = options\n\n this.experienceApi = experienceApi\n this.eventInterceptors = eventInterceptors\n this.getAnonymousId = getAnonymousId\n this.offlineMaxEvents = offlineMaxEvents\n this.onOfflineDrop = onOfflineDrop\n this.stateInterceptors = stateInterceptors\n this.flushRuntime = new QueueFlushRuntime({\n policy: flushPolicy,\n onRetry: () => {\n void this.flush()\n },\n onCallbackError: (callbackName, error) => {\n coreLogger.warn(`Experience flush policy callback \"${callbackName}\" failed`, error)\n },\n })\n }\n\n clearScheduledRetry(): void {\n this.flushRuntime.clearScheduledRetry()\n }\n\n async send(event: ExperienceEventPayload): Promise<OptimizationData | undefined> {\n const intercepted = await this.eventInterceptors.run(event)\n const validEvent = parseWithFriendlyError(ExperienceEventSchema, intercepted)\n\n eventSignal.value = validEvent\n\n if (onlineSignal.value) return await this.upsertProfile([validEvent])\n\n coreLogger.debug(`Queueing ${validEvent.type} event`, validEvent)\n this.enqueueEvent(validEvent)\n\n return undefined\n }\n\n async flush(options: { force?: boolean } = {}): Promise<void> {\n const { force = false } = options\n\n if (this.flushRuntime.shouldSkip({ force, isOnline: !!onlineSignal.value })) return\n\n if (this.queuedExperienceEvents.size === 0) {\n this.flushRuntime.clearScheduledRetry()\n return\n }\n\n coreLogger.debug('Flushing offline Experience event queue')\n\n const queuedEvents = Array.from(this.queuedExperienceEvents)\n this.flushRuntime.markFlushStarted()\n\n try {\n const sendSuccess = await this.tryUpsertQueuedEvents(queuedEvents)\n\n if (sendSuccess) {\n queuedEvents.forEach((queuedEvent) => {\n this.queuedExperienceEvents.delete(queuedEvent)\n })\n this.flushRuntime.handleFlushSuccess()\n } else {\n this.flushRuntime.handleFlushFailure({\n queuedBatches: this.queuedExperienceEvents.size > 0 ? 1 : 0,\n queuedEvents: this.queuedExperienceEvents.size,\n })\n }\n } finally {\n this.flushRuntime.markFlushFinished()\n }\n }\n\n private enqueueEvent(event: ExperienceEventPayload): void {\n let droppedEvents: ExperienceEventArray = []\n\n if (this.queuedExperienceEvents.size >= this.offlineMaxEvents) {\n const dropCount = this.queuedExperienceEvents.size - this.offlineMaxEvents + 1\n droppedEvents = this.dropOldestEvents(dropCount)\n\n if (droppedEvents.length > 0) {\n coreLogger.warn(\n `Dropped ${droppedEvents.length} oldest offline event(s) due to queue limit (${this.offlineMaxEvents})`,\n )\n }\n }\n\n this.queuedExperienceEvents.add(event)\n\n if (droppedEvents.length > 0) {\n this.invokeOfflineDropCallback({\n droppedCount: droppedEvents.length,\n droppedEvents,\n maxEvents: this.offlineMaxEvents,\n queuedEvents: this.queuedExperienceEvents.size,\n })\n }\n }\n\n private dropOldestEvents(count: number): ExperienceEventArray {\n const droppedEvents: ExperienceEventArray = []\n\n for (let index = 0; index < count; index += 1) {\n const oldestEvent = this.queuedExperienceEvents.values().next()\n if (oldestEvent.done) break\n\n this.queuedExperienceEvents.delete(oldestEvent.value)\n droppedEvents.push(oldestEvent.value)\n }\n\n return droppedEvents\n }\n\n private invokeOfflineDropCallback(context: ExperienceQueueDropContext): void {\n try {\n this.onOfflineDrop?.(context)\n } catch (error) {\n coreLogger.warn('Offline queue drop callback failed', error)\n }\n }\n\n private async tryUpsertQueuedEvents(events: ExperienceEventArray): Promise<boolean> {\n try {\n await this.upsertProfile(events)\n return true\n } catch (error) {\n coreLogger.warn('Experience queue flush request threw an error', error)\n return false\n }\n }\n\n private async upsertProfile(events: ExperienceEventArray): Promise<OptimizationData> {\n const anonymousId = this.getAnonymousId()\n if (anonymousId) coreLogger.debug(`Anonymous ID found: ${anonymousId}`)\n\n const data = await this.experienceApi.upsertProfile({\n profileId: anonymousId ?? profileSignal.value?.id,\n events,\n })\n\n await this.updateOutputSignals(data)\n\n return data\n }\n\n private async updateOutputSignals(data: OptimizationData): Promise<void> {\n const intercepted = await this.stateInterceptors.run(data)\n const { changes, profile, selectedOptimizations } = intercepted\n\n batch(() => {\n if (!isEqual(changesSignal.value, changes)) changesSignal.value = changes\n if (!isEqual(profileSignal.value, profile)) profileSignal.value = profile\n if (!isEqual(selectedOptimizationsSignal.value, selectedOptimizations)) {\n selectedOptimizationsSignal.value = selectedOptimizations\n }\n })\n }\n}\n","import {\n InsightsEvent as InsightsEventSchema,\n parseWithFriendlyError,\n type BatchInsightsEventArray,\n type InsightsEventArray,\n type InsightsEvent as InsightsEventPayload,\n type Profile,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger } from '@contentful/optimization-api-client/logger'\nimport type { LifecycleInterceptors } from '../CoreBase'\nimport { QueueFlushRuntime, type ResolvedQueueFlushPolicy } from '../lib/queue'\nimport { event as eventSignal, online as onlineSignal, profile as profileSignal } from '../signals'\n\nconst coreLogger = createScopedLogger('CoreStateful')\n\nconst MAX_QUEUED_INSIGHTS_EVENTS = 25\n\ninterface QueuedProfileEvents {\n profile: Profile\n events: InsightsEventArray\n}\n\ninterface InsightsQueueOptions {\n eventInterceptors: LifecycleInterceptors['event']\n flushPolicy: ResolvedQueueFlushPolicy\n insightsApi: {\n sendBatchEvents: (batches: BatchInsightsEventArray) => Promise<boolean>\n }\n}\n\n/**\n * Internal Insights queueing and flush runtime used by {@link CoreStateful}.\n *\n * @internal\n */\nexport class InsightsQueue {\n private readonly eventInterceptors: InsightsQueueOptions['eventInterceptors']\n private readonly flushIntervalMs: number\n private readonly flushRuntime: QueueFlushRuntime\n private readonly insightsApi: InsightsQueueOptions['insightsApi']\n private readonly queuedInsightsByProfile = new Map<Profile['id'], QueuedProfileEvents>()\n private insightsPeriodicFlushTimer: ReturnType<typeof setInterval> | undefined\n\n constructor(options: InsightsQueueOptions) {\n const { eventInterceptors, flushPolicy, insightsApi } = options\n const { flushIntervalMs } = flushPolicy\n\n this.eventInterceptors = eventInterceptors\n this.flushIntervalMs = flushIntervalMs\n this.insightsApi = insightsApi\n this.flushRuntime = new QueueFlushRuntime({\n policy: flushPolicy,\n onRetry: () => {\n void this.flush()\n },\n onCallbackError: (callbackName, error) => {\n coreLogger.warn(`Insights flush policy callback \"${callbackName}\" failed`, error)\n },\n })\n }\n\n clearScheduledRetry(): void {\n this.flushRuntime.clearScheduledRetry()\n }\n\n clearPeriodicFlushTimer(): void {\n if (this.insightsPeriodicFlushTimer === undefined) return\n\n clearInterval(this.insightsPeriodicFlushTimer)\n this.insightsPeriodicFlushTimer = undefined\n }\n\n async send(event: InsightsEventPayload): Promise<void> {\n const { value: profile } = profileSignal\n\n if (!profile) {\n coreLogger.warn('Attempting to emit an event without an Optimization profile')\n return\n }\n\n const intercepted = await this.eventInterceptors.run(event)\n const validEvent = parseWithFriendlyError(InsightsEventSchema, intercepted)\n\n coreLogger.debug(`Queueing ${validEvent.type} event for profile ${profile.id}`, validEvent)\n\n const queuedProfileEvents = this.queuedInsightsByProfile.get(profile.id)\n\n eventSignal.value = validEvent\n\n if (queuedProfileEvents) {\n queuedProfileEvents.profile = profile\n queuedProfileEvents.events.push(validEvent)\n } else {\n this.queuedInsightsByProfile.set(profile.id, { profile, events: [validEvent] })\n }\n\n this.ensurePeriodicFlushTimer()\n if (this.getQueuedEventCount() >= MAX_QUEUED_INSIGHTS_EVENTS) {\n await this.flush()\n }\n this.reconcilePeriodicFlushTimer()\n }\n\n async flush(options: { force?: boolean } = {}): Promise<void> {\n const { force = false } = options\n\n if (this.flushRuntime.shouldSkip({ force, isOnline: !!onlineSignal.value })) return\n\n coreLogger.debug('Flushing insights event queue')\n\n const batches = this.createBatches()\n\n if (!batches.length) {\n this.flushRuntime.clearScheduledRetry()\n this.reconcilePeriodicFlushTimer()\n return\n }\n\n this.flushRuntime.markFlushStarted()\n\n try {\n const sendSuccess = await this.trySendBatches(batches)\n\n if (sendSuccess) {\n this.queuedInsightsByProfile.clear()\n this.flushRuntime.handleFlushSuccess()\n } else {\n this.flushRuntime.handleFlushFailure({\n queuedBatches: batches.length,\n queuedEvents: this.getQueuedEventCount(),\n })\n }\n } finally {\n this.flushRuntime.markFlushFinished()\n this.reconcilePeriodicFlushTimer()\n }\n }\n\n private createBatches(): BatchInsightsEventArray {\n const batches: BatchInsightsEventArray = []\n\n this.queuedInsightsByProfile.forEach(({ profile, events }) => {\n batches.push({ profile, events })\n })\n\n return batches\n }\n\n private async trySendBatches(batches: BatchInsightsEventArray): Promise<boolean> {\n try {\n return await this.insightsApi.sendBatchEvents(batches)\n } catch (error) {\n coreLogger.warn('Insights queue flush request threw an error', error)\n return false\n }\n }\n\n private getQueuedEventCount(): number {\n let queuedCount = 0\n\n this.queuedInsightsByProfile.forEach(({ events }) => {\n queuedCount += events.length\n })\n\n return queuedCount\n }\n\n private ensurePeriodicFlushTimer(): void {\n if (this.insightsPeriodicFlushTimer !== undefined) return\n if (this.getQueuedEventCount() === 0) return\n\n this.insightsPeriodicFlushTimer = setInterval(() => {\n void this.flush()\n }, this.flushIntervalMs)\n }\n\n private reconcilePeriodicFlushTimer(): void {\n if (this.getQueuedEventCount() > 0) {\n this.ensurePeriodicFlushTimer()\n return\n }\n\n this.clearPeriodicFlushTimer()\n }\n}\n","import type { ApiClientConfig } from '@contentful/optimization-api-client'\nimport type {\n ChangeArray,\n ExperienceEvent as ExperienceEventPayload,\n ExperienceEventType,\n InsightsEvent as InsightsEventPayload,\n InsightsEventType,\n Json,\n Profile,\n SelectedOptimizationArray,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger, logger } from '@contentful/optimization-api-client/logger'\nimport type { BlockedEvent } from './BlockedEvent'\nimport type { ConsentController, ConsentGuard } from './Consent'\nimport type { CoreStatefulApiConfig } from './CoreApiConfig'\nimport type { CoreConfig } from './CoreBase'\nimport CoreStatefulEventEmitter from './CoreStatefulEventEmitter'\nimport { toPositiveInt } from './lib/number'\nimport { type QueueFlushPolicy, resolveQueueFlushPolicy } from './lib/queue'\nimport {\n acquireStatefulRuntimeSingleton,\n releaseStatefulRuntimeSingleton,\n} from './lib/singleton/StatefulRuntimeSingleton'\nimport { ExperienceQueue, type ExperienceQueueDropContext } from './queues/ExperienceQueue'\nimport { InsightsQueue } from './queues/InsightsQueue'\nimport {\n batch,\n blockedEvent as blockedEventSignal,\n canOptimize as canOptimizeSignal,\n changes as changesSignal,\n consent as consentSignal,\n effect,\n event as eventSignal,\n type Observable,\n online as onlineSignal,\n previewPanelAttached as previewPanelAttachedSignal,\n previewPanelOpen as previewPanelOpenSignal,\n profile as profileSignal,\n selectedOptimizations as selectedOptimizationsSignal,\n signalFns,\n type SignalFns,\n type Signals,\n signals,\n toObservable,\n} from './signals'\nimport { PREVIEW_PANEL_SIGNAL_FNS_SYMBOL, PREVIEW_PANEL_SIGNALS_SYMBOL } from './symbols'\n\nconst coreLogger = createScopedLogger('CoreStateful')\n\n/**\n * Union of all event type keys that stateful Core may emit.\n *\n * @public\n */\nexport type EventType = InsightsEventType | ExperienceEventType\n\nconst DEFAULT_ALLOWED_EVENT_TYPES: EventType[] = ['identify', 'page', 'screen']\nconst OFFLINE_QUEUE_MAX_EVENTS = 100\nexport type { ExperienceQueueDropContext } from './queues/ExperienceQueue'\n\nconst hasDefinedValues = (record: Record<string, unknown>): boolean =>\n Object.values(record).some((value) => value !== undefined)\n\nconst createStatefulExperienceApiConfig = (\n api: CoreStatefulApiConfig | undefined,\n): ApiClientConfig['experience'] => {\n if (api === undefined) return undefined\n\n const experienceConfig = {\n baseUrl: api.experienceBaseUrl,\n enabledFeatures: api.enabledFeatures,\n ip: api.ip,\n locale: api.locale,\n plainText: api.plainText,\n preflight: api.preflight,\n }\n\n return hasDefinedValues(experienceConfig) ? experienceConfig : undefined\n}\n\nconst createStatefulInsightsApiConfig = (\n api: CoreStatefulApiConfig | undefined,\n): ApiClientConfig['insights'] => {\n if (api === undefined) return undefined\n\n const insightsConfig = {\n baseUrl: api.insightsBaseUrl,\n beaconHandler: api.beaconHandler,\n }\n\n return hasDefinedValues(insightsConfig) ? insightsConfig : undefined\n}\n\n/**\n * Unified queue policy for stateful Core.\n *\n * @public\n */\nexport interface QueuePolicy {\n /** Shared retry/backoff/circuit policy for queued flushes. */\n flush?: QueueFlushPolicy\n /** Maximum number of offline Experience events retained. */\n offlineMaxEvents?: number\n /** Callback invoked when oldest offline Experience events are dropped. */\n onOfflineDrop?: (context: ExperienceQueueDropContext) => void\n}\n\ninterface ResolvedQueuePolicy {\n flush: ReturnType<typeof resolveQueueFlushPolicy>\n offlineMaxEvents: number\n onOfflineDrop?: QueuePolicy['onOfflineDrop']\n}\n\nconst resolveQueuePolicy = (policy: QueuePolicy | undefined): ResolvedQueuePolicy => ({\n flush: resolveQueueFlushPolicy(policy?.flush),\n offlineMaxEvents: toPositiveInt(policy?.offlineMaxEvents, OFFLINE_QUEUE_MAX_EVENTS),\n onOfflineDrop: policy?.onOfflineDrop,\n})\n\n/**\n * Symbol-keyed signal bridge shared between core and first-party preview tooling.\n *\n * @public\n */\nexport interface PreviewPanelSignalObject {\n /** Signals instance populated by {@link CoreStateful.registerPreviewPanel}. */\n [PREVIEW_PANEL_SIGNALS_SYMBOL]?: Signals | null | undefined\n /** Signal helper functions populated by {@link CoreStateful.registerPreviewPanel}. */\n [PREVIEW_PANEL_SIGNAL_FNS_SYMBOL]?: SignalFns | null | undefined\n}\n\n/**\n * Combined observable state exposed by the stateful core.\n *\n * @public\n */\nexport interface CoreStates {\n /** Current consent value (if any). */\n consent: Observable<boolean | undefined>\n /** Whether the preview panel has been attached to the host runtime. */\n previewPanelAttached: Observable<boolean>\n /** Whether the preview panel is currently open in the host runtime. */\n previewPanelOpen: Observable<boolean>\n /** Stream of the most recent blocked event payload. */\n blockedEventStream: Observable<BlockedEvent | undefined>\n /** Stream of the most recent event emitted. */\n eventStream: Observable<InsightsEventPayload | ExperienceEventPayload | undefined>\n /** Key-scoped observable for a single Custom Flag value. */\n flag: (name: string) => Observable<Json>\n /** Live view of the current profile. */\n profile: Observable<Profile | undefined>\n /** Live view of selected optimizations (variants). */\n selectedOptimizations: Observable<SelectedOptimizationArray | undefined>\n /** Whether optimization data is currently available. */\n canOptimize: Observable<boolean>\n}\n\n/**\n * Default values used to preconfigure the stateful core.\n *\n * @public\n */\nexport interface CoreConfigDefaults {\n /** Global consent default applied at construction time. */\n consent?: boolean\n /** Default active profile used for optimization and insights. */\n profile?: Profile\n /** Initial diff of changes produced by the service. */\n changes?: ChangeArray\n /** Preselected optimization variants (e.g., winning treatments). */\n selectedOptimizations?: SelectedOptimizationArray\n}\n\n/**\n * Configuration for {@link CoreStateful}.\n *\n * @public\n */\nexport interface CoreStatefulConfig extends CoreConfig {\n /**\n * Unified API configuration for stateful environments.\n */\n api?: CoreStatefulApiConfig\n\n /**\n * Allow-listed event type strings permitted when consent is not set.\n */\n allowedEventTypes?: EventType[]\n\n /** Optional set of default values applied on initialization. */\n defaults?: CoreConfigDefaults\n\n /** Function used to obtain an anonymous user identifier. */\n getAnonymousId?: () => string | undefined\n\n /**\n * Callback invoked whenever an event call is blocked by checks.\n */\n onEventBlocked?: (event: BlockedEvent) => void\n\n /** Unified queue policy for queued stateful work. */\n queuePolicy?: QueuePolicy\n}\n\nlet statefulInstanceCounter = 0\n\n/**\n * Core runtime that owns stateful event delivery, consent, and shared signals.\n *\n * @public\n */\nclass CoreStateful extends CoreStatefulEventEmitter implements ConsentController, ConsentGuard {\n private readonly singletonOwner: string\n private destroyed = false\n protected readonly allowedEventTypes: EventType[]\n protected readonly experienceQueue: ExperienceQueue\n protected readonly insightsQueue: InsightsQueue\n protected readonly onEventBlocked?: CoreStatefulConfig['onEventBlocked']\n\n /**\n * Expose merged observable state for consumers.\n */\n readonly states: CoreStates = {\n blockedEventStream: toObservable(blockedEventSignal),\n flag: (name: string): Observable<Json> => this.getFlagObservable(name),\n consent: toObservable(consentSignal),\n eventStream: toObservable(eventSignal),\n canOptimize: toObservable(canOptimizeSignal),\n selectedOptimizations: toObservable(selectedOptimizationsSignal),\n previewPanelAttached: toObservable(previewPanelAttachedSignal),\n previewPanelOpen: toObservable(previewPanelOpenSignal),\n profile: toObservable(profileSignal),\n }\n\n constructor(config: CoreStatefulConfig) {\n super(config, {\n experience: createStatefulExperienceApiConfig(config.api),\n insights: createStatefulInsightsApiConfig(config.api),\n })\n\n this.singletonOwner = `CoreStateful#${++statefulInstanceCounter}`\n acquireStatefulRuntimeSingleton(this.singletonOwner)\n\n try {\n const { allowedEventTypes, defaults, getAnonymousId, onEventBlocked, queuePolicy } = config\n const {\n changes: defaultChanges,\n consent: defaultConsent,\n selectedOptimizations: defaultSelectedOptimizations,\n profile: defaultProfile,\n } = defaults ?? {}\n const resolvedQueuePolicy = resolveQueuePolicy(queuePolicy)\n\n this.allowedEventTypes = allowedEventTypes ?? DEFAULT_ALLOWED_EVENT_TYPES\n this.onEventBlocked = onEventBlocked\n this.insightsQueue = new InsightsQueue({\n eventInterceptors: this.interceptors.event,\n flushPolicy: resolvedQueuePolicy.flush,\n insightsApi: this.api.insights,\n })\n this.experienceQueue = new ExperienceQueue({\n experienceApi: this.api.experience,\n eventInterceptors: this.interceptors.event,\n flushPolicy: resolvedQueuePolicy.flush,\n getAnonymousId: getAnonymousId ?? (() => undefined),\n offlineMaxEvents: resolvedQueuePolicy.offlineMaxEvents,\n onOfflineDrop: resolvedQueuePolicy.onOfflineDrop,\n stateInterceptors: this.interceptors.state,\n })\n\n if (defaultConsent !== undefined) consentSignal.value = defaultConsent\n\n batch(() => {\n if (defaultChanges !== undefined) changesSignal.value = defaultChanges\n if (defaultSelectedOptimizations !== undefined) {\n selectedOptimizationsSignal.value = defaultSelectedOptimizations\n }\n if (defaultProfile !== undefined) profileSignal.value = defaultProfile\n })\n\n this.initializeEffects()\n } catch (error) {\n releaseStatefulRuntimeSingleton(this.singletonOwner)\n throw error\n }\n }\n\n private initializeEffects(): void {\n effect(() => {\n coreLogger.debug(\n `Profile ${profileSignal.value && `with ID ${profileSignal.value.id}`} has been ${profileSignal.value ? 'set' : 'cleared'}`,\n )\n })\n\n effect(() => {\n coreLogger.debug(\n `Variants have been ${selectedOptimizationsSignal.value?.length ? 'populated' : 'cleared'}`,\n )\n })\n\n effect(() => {\n coreLogger.info(\n `Core ${consentSignal.value ? 'will' : 'will not'} emit gated events due to consent (${consentSignal.value})`,\n )\n })\n\n effect(() => {\n if (!onlineSignal.value) return\n\n this.insightsQueue.clearScheduledRetry()\n this.experienceQueue.clearScheduledRetry()\n void this.flushQueues({ force: true })\n })\n }\n\n private async flushQueues(options: { force?: boolean } = {}): Promise<void> {\n await this.insightsQueue.flush(options)\n await this.experienceQueue.flush(options)\n }\n\n destroy(): void {\n if (this.destroyed) return\n\n this.destroyed = true\n void this.insightsQueue.flush({ force: true }).catch((error: unknown) => {\n logger.warn('Failed to flush insights queue during destroy()', String(error))\n })\n void this.experienceQueue.flush({ force: true }).catch((error: unknown) => {\n logger.warn('Failed to flush Experience queue during destroy()', String(error))\n })\n this.insightsQueue.clearPeriodicFlushTimer()\n\n releaseStatefulRuntimeSingleton(this.singletonOwner)\n }\n\n reset(): void {\n batch(() => {\n blockedEventSignal.value = undefined\n eventSignal.value = undefined\n changesSignal.value = undefined\n profileSignal.value = undefined\n selectedOptimizationsSignal.value = undefined\n })\n }\n\n async flush(): Promise<void> {\n await this.flushQueues()\n }\n\n consent(accept: boolean): void {\n consentSignal.value = accept\n }\n\n protected get online(): boolean {\n return onlineSignal.value ?? false\n }\n\n protected set online(isOnline: boolean) {\n onlineSignal.value = isOnline\n }\n\n registerPreviewPanel(previewPanel: PreviewPanelSignalObject): void {\n Reflect.set(previewPanel, PREVIEW_PANEL_SIGNALS_SYMBOL, signals)\n Reflect.set(previewPanel, PREVIEW_PANEL_SIGNAL_FNS_SYMBOL, signalFns)\n }\n}\n\nexport default CoreStateful\n","import type {\n ApiClientConfig,\n ExperienceApiClientRequestOptions,\n} from '@contentful/optimization-api-client'\nimport {\n BatchInsightsEventArray,\n ExperienceEvent as ExperienceEventSchema,\n InsightsEvent as InsightsEventSchema,\n parseWithFriendlyError,\n type ExperienceEvent as ExperienceEventPayload,\n type InsightsEvent as InsightsEventPayload,\n} from '@contentful/optimization-api-client/api-schemas'\nimport type { CoreStatelessApiConfig } from './CoreApiConfig'\nimport CoreBase, { type CoreConfig } from './CoreBase'\nimport { PartialProfile, type OptimizationData } from './api-schemas'\nimport type {\n ClickBuilderArgs,\n EventBuilderConfig,\n FlagViewBuilderArgs,\n HoverBuilderArgs,\n IdentifyBuilderArgs,\n PageViewBuilderArgs,\n ScreenViewBuilderArgs,\n TrackBuilderArgs,\n ViewBuilderArgs,\n} from './events'\n\n/**\n * Request-bound Experience API options for stateless runtimes.\n *\n * @public\n */\nexport interface CoreStatelessRequestOptions extends Pick<\n ExperienceApiClientRequestOptions,\n 'ip' | 'locale' | 'plainText' | 'preflight'\n> {}\n\n/**\n * Configuration for stateless Optimization Core runtimes.\n *\n * @public\n * @remarks\n * This configuration extends {@link CoreConfig} but allows partial overrides\n * of the event-builder configuration. SDKs commonly inject their own library\n * metadata or channel definitions.\n */\nexport interface CoreStatelessConfig extends CoreConfig {\n /**\n * Unified API configuration for stateless environments.\n */\n api?: CoreStatelessApiConfig\n\n /**\n * Overrides for the event builder configuration. Omits methods that are only\n * useful in stateful environments.\n */\n eventBuilder?: Omit<EventBuilderConfig, 'getLocale' | 'getPageProperties' | 'getUserAgent'>\n}\n\ntype StatelessExperiencePayload<TPayload> = TPayload & { profile?: PartialProfile }\ntype StatelessInsightsPayload<TPayload> = TPayload & { profile: PartialProfile }\ntype StatelessStickyTrackViewPayload = ViewBuilderArgs & {\n profile?: PartialProfile\n sticky: true\n}\ntype StatelessNonStickyTrackViewPayload = Omit<ViewBuilderArgs, 'sticky'> & {\n profile: PartialProfile\n sticky?: false | undefined\n}\n\nconst TRACK_CLICK_PROFILE_ERROR =\n 'CoreStateless.trackClick() requires `payload.profile.id` for Insights delivery.'\nconst TRACK_HOVER_PROFILE_ERROR =\n 'CoreStateless.trackHover() requires `payload.profile.id` for Insights delivery.'\nconst TRACK_FLAG_VIEW_PROFILE_ERROR =\n 'CoreStateless.trackFlagView() requires `payload.profile.id` for Insights delivery.'\nconst NON_STICKY_TRACK_VIEW_PROFILE_ERROR =\n 'CoreStateless.trackView() requires `payload.profile.id` when `payload.sticky` is not `true`.'\nconst STICKY_TRACK_VIEW_PROFILE_ERROR =\n 'CoreStateless.trackView() could not derive a profile from the sticky Experience response. Pass `payload.profile.id` explicitly if you need a fallback.'\n\nconst hasDefinedValues = (record: Record<string, unknown>): boolean =>\n Object.values(record).some((value) => value !== undefined)\n\nconst requireInsightsProfile = (\n profile: PartialProfile | undefined,\n errorMessage: string,\n): PartialProfile => {\n if (profile !== undefined) return profile\n\n throw new Error(errorMessage)\n}\n\nconst createStatelessExperienceApiConfig = (\n api: CoreStatelessConfig['api'] | undefined,\n): ApiClientConfig['experience'] => {\n if (api === undefined) return undefined\n\n const experienceConfig = {\n baseUrl: api.experienceBaseUrl,\n enabledFeatures: api.enabledFeatures,\n }\n\n return hasDefinedValues(experienceConfig) ? experienceConfig : undefined\n}\n\nconst createStatelessInsightsApiConfig = (\n api: CoreStatelessConfig['api'] | undefined,\n): ApiClientConfig['insights'] => {\n if (api?.insightsBaseUrl === undefined) return undefined\n\n return {\n baseUrl: api.insightsBaseUrl,\n }\n}\n\n/**\n * Core runtime for stateless environments.\n *\n * @public\n * Built on top of `CoreBase`. Event-emitting methods are exposed directly on\n * the stateless instance and accept request-scoped Experience options as a\n * separate final argument.\n * @remarks\n * The runtime itself is stateless, but event methods still perform outbound\n * Experience and Insights API calls. Cache Contentful delivery data in the\n * host application, not the results of those calls.\n */\nclass CoreStateless extends CoreBase<CoreStatelessConfig> {\n constructor(config: CoreStatelessConfig) {\n super(config, {\n experience: createStatelessExperienceApiConfig(config.api),\n insights: createStatelessInsightsApiConfig(config.api),\n })\n }\n\n async identify(\n payload: StatelessExperiencePayload<IdentifyBuilderArgs>,\n requestOptions?: CoreStatelessRequestOptions,\n ): Promise<OptimizationData> {\n const { profile, ...builderArgs } = payload\n\n return await this.sendExperienceEvent(\n this.eventBuilder.buildIdentify(builderArgs),\n profile,\n requestOptions,\n )\n }\n\n async page(\n payload: StatelessExperiencePayload<PageViewBuilderArgs> = {},\n requestOptions?: CoreStatelessRequestOptions,\n ): Promise<OptimizationData> {\n const { profile, ...builderArgs } = payload\n\n return await this.sendExperienceEvent(\n this.eventBuilder.buildPageView(builderArgs),\n profile,\n requestOptions,\n )\n }\n\n async screen(\n payload: StatelessExperiencePayload<ScreenViewBuilderArgs>,\n requestOptions?: CoreStatelessRequestOptions,\n ): Promise<OptimizationData> {\n const { profile, ...builderArgs } = payload\n\n return await this.sendExperienceEvent(\n this.eventBuilder.buildScreenView(builderArgs),\n profile,\n requestOptions,\n )\n }\n\n async track(\n payload: StatelessExperiencePayload<TrackBuilderArgs>,\n requestOptions?: CoreStatelessRequestOptions,\n ): Promise<OptimizationData> {\n const { profile, ...builderArgs } = payload\n\n return await this.sendExperienceEvent(\n this.eventBuilder.buildTrack(builderArgs),\n profile,\n requestOptions,\n )\n }\n\n async trackView(\n payload: StatelessStickyTrackViewPayload | StatelessNonStickyTrackViewPayload,\n requestOptions?: CoreStatelessRequestOptions,\n ): Promise<OptimizationData | undefined> {\n const { profile, ...builderArgs } = payload\n let result: OptimizationData | undefined = undefined\n let insightsProfile: PartialProfile | undefined = profile\n\n if (payload.sticky) {\n result = await this.sendExperienceEvent(\n this.eventBuilder.buildView(builderArgs),\n profile,\n requestOptions,\n )\n const { profile: responseProfile } = result\n insightsProfile = responseProfile\n }\n\n await this.sendInsightsEvent(\n this.eventBuilder.buildView(builderArgs),\n requireInsightsProfile(\n insightsProfile,\n payload.sticky ? STICKY_TRACK_VIEW_PROFILE_ERROR : NON_STICKY_TRACK_VIEW_PROFILE_ERROR,\n ),\n )\n\n return result\n }\n\n async trackClick(\n payload: StatelessInsightsPayload<ClickBuilderArgs>,\n _requestOptions?: CoreStatelessRequestOptions,\n ): Promise<void> {\n const { profile, ...builderArgs } = payload\n\n await this.sendInsightsEvent(\n this.eventBuilder.buildClick(builderArgs),\n requireInsightsProfile(profile, TRACK_CLICK_PROFILE_ERROR),\n )\n }\n\n async trackHover(\n payload: StatelessInsightsPayload<HoverBuilderArgs>,\n _requestOptions?: CoreStatelessRequestOptions,\n ): Promise<void> {\n const { profile, ...builderArgs } = payload\n\n await this.sendInsightsEvent(\n this.eventBuilder.buildHover(builderArgs),\n requireInsightsProfile(profile, TRACK_HOVER_PROFILE_ERROR),\n )\n }\n\n async trackFlagView(\n payload: StatelessInsightsPayload<FlagViewBuilderArgs>,\n _requestOptions?: CoreStatelessRequestOptions,\n ): Promise<void> {\n const { profile, ...builderArgs } = payload\n\n await this.sendInsightsEvent(\n this.eventBuilder.buildFlagView(builderArgs),\n requireInsightsProfile(profile, TRACK_FLAG_VIEW_PROFILE_ERROR),\n )\n }\n\n private async sendExperienceEvent(\n event: ExperienceEventPayload,\n profile?: PartialProfile,\n requestOptions?: CoreStatelessRequestOptions,\n ): Promise<OptimizationData> {\n const intercepted = await this.interceptors.event.run(event)\n const validEvent = parseWithFriendlyError(ExperienceEventSchema, intercepted)\n\n return await this.api.experience.upsertProfile(\n {\n profileId: profile?.id,\n events: [validEvent],\n },\n requestOptions,\n )\n }\n\n private async sendInsightsEvent(\n event: InsightsEventPayload,\n profile: PartialProfile,\n ): Promise<void> {\n const intercepted = await this.interceptors.event.run(event)\n const validEvent = parseWithFriendlyError(InsightsEventSchema, intercepted)\n const batchEvent: BatchInsightsEventArray = parseWithFriendlyError(BatchInsightsEventArray, [\n { profile: parseWithFriendlyError(PartialProfile, profile), events: [validEvent] },\n ])\n\n await this.api.insights.sendBatchEvents(batchEvent)\n }\n}\n\nexport default CoreStateless\n","/**\n * A callback invoked when a method call is blocked by {@link guardedBy}.\n *\n * @param methodName - The name of the method that was attempted.\n * @param args - The readonly array of arguments supplied to the blocked call.\n * @returns Nothing.\n *\n * @public\n */\nexport type BlockHandler = (methodName: string, args: readonly unknown[]) => void\n\n/**\n * The original method implementation.\n *\n * @typeParam A - The parameter tuple of the original method.\n * @typeParam R - The return type of the original method.\n * @param value - The method being decorated.\n * @param context - The Stage-3 decorator context for a class method.\n * @returns Nothing.\n *\n * @remarks\n * Users do not call this directly; it's returned by {@link guardedBy}.\n *\n * @internal\n */\nexport type GuardedByFunction<T extends object> = <A extends readonly unknown[], R>(\n value: (...args: A) => R,\n context: ClassMethodDecoratorContext<T, (...args: A) => R>,\n) => void\n\n/**\n * Options that tweak the behavior of {@link guardedBy}.\n *\n * @typeParam T - The instance type on which the decorator is applied.\n *\n * @public\n */\nexport interface GuardedByOptions<T extends object> {\n /**\n * Inverts the predicate result.\n *\n * When `true`, a truthy predicate result **blocks** the method.\n * When `false` (default) or omitted, a truthy predicate result **allows** the method.\n *\n * @defaultValue `false`\n * @remarks\n * This option is useful when the predicate expresses a *forbid* condition\n * (e.g. \"isLocked\" or \"isDestroyed\") rather than an *allow* condition.\n */\n readonly invert?: boolean\n\n /**\n * Either a function to call when a method is blocked, or the name/symbol of\n * an instance method on `this` to call when blocked.\n *\n * Both forms are **synchronous** and receive `(methodName, argsArray)`.\n * If omitted, blocked calls fail silently (i.e., return `undefined` or\n * `Promise<undefined>` for async methods).\n *\n * @remarks\n * - If a property key is supplied and the instance does not have a callable at that key,\n * the hook is ignored.\n * - The hook **must not** be `async`; any async work should be scheduled manually.\n */\n readonly onBlocked?: BlockHandler | (keyof T & (string | symbol))\n}\n\n/**\n * Type guard for functions.\n *\n * @internal\n */\nconst isFunction = (v: unknown): v is (...args: readonly unknown[]) => unknown =>\n typeof v === 'function'\n\n/**\n * Converts a property key to a readable string for logs and messages.\n *\n * @param name - The property key to stringify.\n * @returns A human-friendly name.\n *\n * @internal\n */\nconst nameToString = (name: PropertyKey): string =>\n typeof name === 'string'\n ? name\n : typeof name === 'symbol'\n ? (name.description ?? String(name))\n : String(name)\n\n/**\n * True when the `onBlocked` option is a property key (string or symbol).\n *\n * @typeParam T - The instance type.\n * @param v - The `onBlocked` option value.\n * @returns Whether `v` is a property key.\n *\n * @internal\n */\nconst isOnBlockedKey = <T extends object>(\n v: GuardedByOptions<T>['onBlocked'],\n): v is keyof T & (string | symbol) => typeof v === 'string' || typeof v === 'symbol'\n\n/**\n * Detects declared `async` functions.\n *\n * @param fn - The candidate to test.\n * @returns `true` if `fn` is an async function, else `false`.\n *\n * @internal\n */\nconst isAsyncFunction = (fn: (...args: readonly unknown[]) => unknown): boolean =>\n Object.prototype.toString.call(fn) === '[object AsyncFunction]'\n\n/**\n * Decorator factory that **guards** class methods behind a synchronous predicate.\n *\n * When a decorated method is invoked:\n * - If the predicate returns a value that evaluates to **allowed** (see `invert`), the original\n * method is executed and its result is returned.\n * - If the call is **blocked**, the optional `onBlocked` hook is invoked (if configured) and:\n * - `undefined` is returned for sync methods; or\n * - `Promise<undefined>` is returned for async methods (to preserve `await` compatibility).\n *\n * @typeParam T - The instance type that owns both the predicate and the decorated method.\n *\n * @param predicateName - The name (string or symbol) of a **synchronous** instance method on `this`\n * that acts as the predicate. It is called as `this[predicateName](methodName, argsArray)`.\n * @param opts - Optional `GuardedByOptions` to configure inversion and `onBlocked`.\n *\n * @returns A methods-only class decorator compatible with Stage-3 decorators that wraps the method.\n *\n * @throws TypeError\n * Thrown at initialization time (first instance construction) if `predicateName` does not resolve\n * to a **synchronous function** on the instance.\n *\n * @remarks\n * - This is a **methods-only** decorator; applying it to accessors/fields is a no-op.\n * - The decorator preserves the original method's sync/async shape.\n * - The predicate is invoked with `(decoratedMethodName, argsArray)` to support context-aware checks.\n *\n * @example\n * Here, `canRun` allows the call when it returns truthy:\n * ```ts\n * class Runner {\n * canRun(method: string, _args: readonly unknown[]) { return method !== 'stop'; }\n *\n * @guardedBy<Runner>('canRun')\n * go() { console.log('running'); }\n * }\n * ```\n *\n * @example\n * Invert the predicate and call a handler on block:\n * ```ts\n * class Door {\n * isLocked() { return true } // truthy means \"locked\"\n * onBlocked(method: string) { console.warn(`${method} blocked`) }\n *\n * @guardedBy<Door>('isLocked', { invert: true, onBlocked: 'onBlocked' })\n * open() { /* ... *\\/ }\n * }\n * ```\n *\n * @public\n */\nexport function guardedBy<T extends object>(\n predicateName: keyof T & (string | symbol),\n opts?: GuardedByOptions<T>,\n): GuardedByFunction<T> {\n return function <A extends readonly unknown[], R>(\n _value: (...args: A) => R,\n context: ClassMethodDecoratorContext<T, (...args: A) => R>,\n ): void {\n const decoratedName = nameToString(context.name)\n\n context.addInitializer(function init(this: T): void {\n // Original method on the instance\n const originalUnknown: unknown = Reflect.get(this, context.name)\n if (!isFunction(originalUnknown)) {\n return // defensive: nothing to wrap\n }\n const original = originalUnknown\n const originalIsAsync = isAsyncFunction(original)\n\n const resolvePredicate = (self: T): ((...args: readonly unknown[]) => unknown) => {\n const { [predicateName]: cand } = self\n if (!isFunction(cand)) {\n throw new TypeError(\n `@guardedBy expects predicate \"${String(predicateName)}\" to be a synchronous function.`,\n )\n }\n return cand\n }\n\n const computeAllowed = (self: T, args: readonly unknown[]): boolean => {\n const pred = resolvePredicate(self)\n const ok = Boolean(pred.call(self, decoratedName, args))\n return opts?.invert === true ? !ok : ok\n }\n\n const runOnBlocked = (self: T, args: readonly unknown[]): void => {\n const { onBlocked } = opts ?? {}\n if (onBlocked === undefined) {\n return\n }\n if (isFunction(onBlocked)) {\n onBlocked.call(self, decoratedName, args)\n return\n }\n if (isOnBlockedKey<T>(onBlocked)) {\n const { [onBlocked]: handlerCandidate } = self\n if (isFunction(handlerCandidate)) {\n handlerCandidate.call(self, decoratedName, args)\n }\n }\n }\n\n const blockedReturn = (): unknown =>\n originalIsAsync ? Promise.resolve(undefined) : undefined\n\n const wrapped = function (this: T, ...args: readonly unknown[]): unknown {\n if (!computeAllowed(this, args)) {\n runOnBlocked(this, args)\n return blockedReturn()\n }\n return original.call(this, ...args)\n }\n\n // Replace the instance method with our wrapper\n Reflect.set(this, context.name, wrapped)\n })\n }\n}\n"],"names":["OPTIMIZATION_CORE_SDK_VERSION","__OPTIMIZATION_VERSION__","OPTIMIZATION_CORE_SDK_NAME","__OPTIMIZATION_PACKAGE_NAME__","ANONYMOUS_ID_COOKIE","ANONYMOUS_ID_KEY","CONSENT_KEY","CHANGES_CACHE_KEY","DEBUG_FLAG_KEY","PROFILE_CACHE_KEY","SELECTED_OPTIMIZATIONS_CACHE_KEY","ANONYMOUS_ID_COOKIE_LEGACY","ANONYMOUS_ID_KEY_LEGACY","PREVIEW_PANEL_SIGNALS_SYMBOL","Symbol","PREVIEW_PANEL_SIGNAL_FNS_SYMBOL","__webpack_require__","module","getter","definition","key","Object","obj","prop","isNonNullish","value","toError","Error","String","toObservable","s","cloneDeep","next","dispose","effect","closed","isEffectActive","undefined","stop","callbackError","error","queueMicrotask","toDistinctObservable","isEqual","observable","hasPrevious","previous","changes","signal","blockedEvent","consent","event","online","previewPanelAttached","previewPanelOpen","selectedOptimizations","canOptimize","computed","profile","signals","signalFns","batch","untracked","UniversalEventBuilderArgs","z","Campaign","GeoLocation","Page","Screen","EntryInteractionBuilderArgsBase","ViewBuilderArgs","FlagViewBuilderArgs","ClickBuilderArgs","HoverBuilderArgs","IdentifyBuilderArgs","Traits","PageViewBuilderArgs","ScreenViewBuilderArgs","Properties","TrackBuilderArgs","DEFAULT_PAGE_PROPERTIES","EventBuilder","config","app","channel","library","getLocale","getPageProperties","getUserAgent","campaign","locale","location","page","screen","userAgent","timestamp","Date","crypto","universal","componentId","experienceId","variantIndex","args","viewId","viewDurationMs","parseWithFriendlyError","hoverId","hoverDurationMs","traits","userId","properties","pageProperties","merged","merge","_","universalContext","universalProperties","context","PageEventContext","name","ScreenEventContext","InterceptorManager","Map","interceptor","id","input","fns","Array","acc","fn","FlagsResolver","actualValue","logger","createScopedLogger","RESOLUTION_WARNING_BASE","getAtPath","path","current","segments","Boolean","segment","Reflect","MergeTagValueResolver","_path","index","paths","dotPath","underScorePath","selectors","matchingSelector","selector","mergeTagEntry","isMergeTagEntry","fallback","Profile","resolve","entry","isOptimizedEntry","optimizationEntry","OptimizedEntryResolver","selectedOptimization","selectedVariantIndex","selectedVariant","selectedVariantEntry","optimizedEntry","skipValidation","maybeOptimization","isOptimizationEntry","relevantVariants","normalizeOptimizationConfig","component","isEntryReplacementComponent","isEntryReplacementVariant","variant","isEntry","CoreBase","api","eventBuilder","logLevel","environment","clientId","fetchOptions","ConsoleLogSink","apiConfig","ApiClient","embeddedEntryNodeTarget","coreLogger","CONSENT_EVENT_TYPE_MAP","CoreStatefulEventEmitter","changesSignal","payload","selectedOptimizationsSignal","profileSignal","builderArgs","result","mappedEventType","isAllowed","eventType","consentSignal","JSON","method","_profile","change","candidate","existingObservable","trackFlagView","buildFlagViewBuilderArgs","valueSignal","distinctObservable","trackedObservable","reason","blockedEventSignal","toPositiveInt","Number","Math","toRatio","DEFAULT_QUEUE_FLUSH_POLICY","resolveQueueFlushPolicy","policy","defaults","configuredPolicy","baseBackoffMs","maxBackoffMs","computeQueueFlushRetryDelayMs","options","consecutiveFailures","jitterRatio","exponential","capped","jitter","createQueueFlushFailureWindow","failureTimestamp","retryDelayMs","maxConsecutiveFailures","circuitOpenMs","circuitOpenUntil","STATEFUL_RUNTIME_LOCK_KEY","getStatefulRuntimeLock","singletonGlobal","globalThis","acquireStatefulRuntimeSingleton","owner","lock","releaseStatefulRuntimeSingleton","QueueFlushRuntime","onCallbackError","onRetry","clearTimeout","force","isOnline","now","previousConsecutiveFailures","queuedBatches","queuedEvents","failureContext","failureWindow","nextFlushAllowedAt","openedCircuit","scheduledRetryDelayMs","delayMs","setTimeout","callbackName","ExperienceQueue","Set","experienceApi","eventInterceptors","flushPolicy","getAnonymousId","offlineMaxEvents","onOfflineDrop","stateInterceptors","intercepted","validEvent","ExperienceEventSchema","eventSignal","onlineSignal","sendSuccess","queuedEvent","droppedEvents","dropCount","count","oldestEvent","events","anonymousId","data","MAX_QUEUED_INSIGHTS_EVENTS","InsightsQueue","insightsApi","flushIntervalMs","clearInterval","InsightsEventSchema","queuedProfileEvents","batches","queuedCount","setInterval","DEFAULT_ALLOWED_EVENT_TYPES","OFFLINE_QUEUE_MAX_EVENTS","hasDefinedValues","record","createStatefulExperienceApiConfig","experienceConfig","createStatefulInsightsApiConfig","insightsConfig","resolveQueuePolicy","statefulInstanceCounter","CoreStateful","canOptimizeSignal","previewPanelAttachedSignal","previewPanelOpenSignal","allowedEventTypes","onEventBlocked","queuePolicy","defaultChanges","defaultConsent","defaultSelectedOptimizations","defaultProfile","resolvedQueuePolicy","accept","previewPanel","TRACK_CLICK_PROFILE_ERROR","TRACK_HOVER_PROFILE_ERROR","TRACK_FLAG_VIEW_PROFILE_ERROR","NON_STICKY_TRACK_VIEW_PROFILE_ERROR","STICKY_TRACK_VIEW_PROFILE_ERROR","requireInsightsProfile","errorMessage","createStatelessExperienceApiConfig","createStatelessInsightsApiConfig","CoreStateless","requestOptions","insightsProfile","responseProfile","_requestOptions","batchEvent","BatchInsightsEventArray","PartialProfile","isFunction","v","nameToString","isOnBlockedKey","isAsyncFunction","guardedBy","predicateName","opts","_value","decoratedName","originalUnknown","original","originalIsAsync","resolvePredicate","self","cand","TypeError","computeAllowed","pred","ok","runOnBlocked","onBlocked","handlerCandidate","blockedReturn","Promise","wrapped"],"mappings":"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"}