@contentful/optimization-core 0.1.0-alpha → 0.1.0-alpha10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +221 -31
- package/dist/260.mjs +14 -0
- package/dist/260.mjs.map +1 -0
- package/dist/499.mjs +4 -0
- package/dist/632.mjs +5 -0
- package/dist/632.mjs.map +1 -0
- package/dist/808.mjs +2 -0
- package/dist/942.mjs +2 -0
- package/dist/api-client.cjs +60 -0
- package/dist/api-client.cjs.map +1 -0
- package/dist/api-client.d.cts +4 -0
- package/dist/api-client.d.mts +4 -0
- package/dist/api-client.d.ts +4 -0
- package/dist/api-client.mjs +2 -0
- package/dist/api-schemas.cjs +60 -0
- package/dist/api-schemas.cjs.map +1 -0
- package/dist/api-schemas.d.cts +4 -0
- package/dist/api-schemas.d.mts +4 -0
- package/dist/api-schemas.d.ts +4 -0
- package/dist/api-schemas.mjs +2 -0
- package/dist/constants.cjs +78 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/constants.d.cts +88 -0
- package/dist/constants.d.mts +88 -0
- package/dist/constants.d.ts +88 -0
- package/dist/constants.mjs +1 -0
- package/dist/index.cjs +1853 -1665
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2432 -0
- package/dist/index.d.mts +2432 -0
- package/dist/index.d.ts +2432 -15
- package/dist/index.mjs +625 -327
- package/dist/index.mjs.map +1 -1
- package/dist/logger.cjs +67 -0
- package/dist/logger.cjs.map +1 -0
- package/dist/logger.d.cts +8 -0
- package/dist/logger.d.mts +8 -0
- package/dist/logger.d.ts +8 -0
- package/dist/logger.mjs +2 -0
- package/dist/symbols.cjs +42 -0
- package/dist/symbols.cjs.map +1 -0
- package/dist/symbols.d.cts +10 -0
- package/dist/symbols.d.mts +10 -0
- package/dist/symbols.d.ts +10 -0
- package/dist/symbols.mjs +1 -0
- package/package.json +65 -12
- package/dist/Consent.d.ts +0 -44
- package/dist/Consent.d.ts.map +0 -1
- package/dist/Consent.js +0 -2
- package/dist/Consent.js.map +0 -1
- package/dist/CoreBase.d.ts +0 -161
- package/dist/CoreBase.d.ts.map +0 -1
- package/dist/CoreBase.js +0 -151
- package/dist/CoreBase.js.map +0 -1
- package/dist/CoreStateful.d.ts +0 -142
- package/dist/CoreStateful.d.ts.map +0 -1
- package/dist/CoreStateful.js +0 -137
- package/dist/CoreStateful.js.map +0 -1
- package/dist/CoreStateless.d.ts +0 -53
- package/dist/CoreStateless.d.ts.map +0 -1
- package/dist/CoreStateless.js +0 -43
- package/dist/CoreStateless.js.map +0 -1
- package/dist/ProductBase.d.ts +0 -83
- package/dist/ProductBase.d.ts.map +0 -1
- package/dist/ProductBase.js +0 -50
- package/dist/ProductBase.js.map +0 -1
- package/dist/analytics/AnalyticsBase.d.ts +0 -35
- package/dist/analytics/AnalyticsBase.d.ts.map +0 -1
- package/dist/analytics/AnalyticsBase.js +0 -13
- package/dist/analytics/AnalyticsBase.js.map +0 -1
- package/dist/analytics/AnalyticsStateful.d.ts +0 -138
- package/dist/analytics/AnalyticsStateful.d.ts.map +0 -1
- package/dist/analytics/AnalyticsStateful.js +0 -179
- package/dist/analytics/AnalyticsStateful.js.map +0 -1
- package/dist/analytics/AnalyticsStateless.d.ts +0 -48
- package/dist/analytics/AnalyticsStateless.d.ts.map +0 -1
- package/dist/analytics/AnalyticsStateless.js +0 -61
- package/dist/analytics/AnalyticsStateless.js.map +0 -1
- package/dist/analytics/index.d.ts +0 -5
- package/dist/analytics/index.d.ts.map +0 -1
- package/dist/analytics/index.js +0 -5
- package/dist/analytics/index.js.map +0 -1
- package/dist/global-constants.d.ts +0 -18
- package/dist/global-constants.d.ts.map +0 -1
- package/dist/global-constants.js +0 -18
- package/dist/global-constants.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -15
- package/dist/index.js.map +0 -1
- package/dist/lib/decorators/guardedBy.d.ts +0 -113
- package/dist/lib/decorators/guardedBy.d.ts.map +0 -1
- package/dist/lib/decorators/guardedBy.js +0 -143
- package/dist/lib/decorators/guardedBy.js.map +0 -1
- package/dist/lib/decorators/index.d.ts +0 -2
- package/dist/lib/decorators/index.d.ts.map +0 -1
- package/dist/lib/decorators/index.js +0 -2
- package/dist/lib/decorators/index.js.map +0 -1
- package/dist/lib/interceptor/InterceptorManager.d.ts +0 -127
- package/dist/lib/interceptor/InterceptorManager.d.ts.map +0 -1
- package/dist/lib/interceptor/InterceptorManager.js +0 -125
- package/dist/lib/interceptor/InterceptorManager.js.map +0 -1
- package/dist/lib/interceptor/index.d.ts +0 -2
- package/dist/lib/interceptor/index.d.ts.map +0 -1
- package/dist/lib/interceptor/index.js +0 -2
- package/dist/lib/interceptor/index.js.map +0 -1
- package/dist/lib/value-presence/ValuePresence.d.ts +0 -123
- package/dist/lib/value-presence/ValuePresence.d.ts.map +0 -1
- package/dist/lib/value-presence/ValuePresence.js +0 -141
- package/dist/lib/value-presence/ValuePresence.js.map +0 -1
- package/dist/lib/value-presence/index.d.ts +0 -2
- package/dist/lib/value-presence/index.d.ts.map +0 -1
- package/dist/lib/value-presence/index.js +0 -2
- package/dist/lib/value-presence/index.js.map +0 -1
- package/dist/personalization/PersonalizationBase.d.ts +0 -184
- package/dist/personalization/PersonalizationBase.d.ts.map +0 -1
- package/dist/personalization/PersonalizationBase.js +0 -76
- package/dist/personalization/PersonalizationBase.js.map +0 -1
- package/dist/personalization/PersonalizationStateful.d.ts +0 -226
- package/dist/personalization/PersonalizationStateful.d.ts.map +0 -1
- package/dist/personalization/PersonalizationStateful.js +0 -297
- package/dist/personalization/PersonalizationStateful.js.map +0 -1
- package/dist/personalization/PersonalizationStateless.d.ts +0 -74
- package/dist/personalization/PersonalizationStateless.d.ts.map +0 -1
- package/dist/personalization/PersonalizationStateless.js +0 -98
- package/dist/personalization/PersonalizationStateless.js.map +0 -1
- package/dist/personalization/index.d.ts +0 -6
- package/dist/personalization/index.d.ts.map +0 -1
- package/dist/personalization/index.js +0 -6
- package/dist/personalization/index.js.map +0 -1
- package/dist/personalization/resolvers/FlagsResolver.d.ts +0 -35
- package/dist/personalization/resolvers/FlagsResolver.d.ts.map +0 -1
- package/dist/personalization/resolvers/FlagsResolver.js +0 -47
- package/dist/personalization/resolvers/FlagsResolver.js.map +0 -1
- package/dist/personalization/resolvers/MergeTagValueResolver.d.ts +0 -74
- package/dist/personalization/resolvers/MergeTagValueResolver.d.ts.map +0 -1
- package/dist/personalization/resolvers/MergeTagValueResolver.js +0 -109
- package/dist/personalization/resolvers/MergeTagValueResolver.js.map +0 -1
- package/dist/personalization/resolvers/PersonalizedEntryResolver.d.ts +0 -142
- package/dist/personalization/resolvers/PersonalizedEntryResolver.d.ts.map +0 -1
- package/dist/personalization/resolvers/PersonalizedEntryResolver.js +0 -196
- package/dist/personalization/resolvers/PersonalizedEntryResolver.js.map +0 -1
- package/dist/personalization/resolvers/index.d.ts +0 -7
- package/dist/personalization/resolvers/index.d.ts.map +0 -1
- package/dist/personalization/resolvers/index.js +0 -7
- package/dist/personalization/resolvers/index.js.map +0 -1
- package/dist/signals.d.ts +0 -35
- package/dist/signals.d.ts.map +0 -1
- package/dist/signals.js +0 -30
- package/dist/signals.js.map +0 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/CoreBase.ts","../src/CoreStateful.ts","../src/CoreStateless.ts","../src/ProductBase.ts","../src/analytics/AnalyticsBase.ts","../src/analytics/AnalyticsStateful.ts","../src/analytics/AnalyticsStateless.ts","../src/global-constants.ts","../src/lib/decorators/guardedBy.ts","../src/lib/interceptor/InterceptorManager.ts","../src/lib/value-presence/ValuePresence.ts","../src/personalization/PersonalizationBase.ts","../src/personalization/PersonalizationStateful.ts","../src/personalization/PersonalizationStateless.ts","../src/personalization/resolvers/FlagsResolver.ts","../src/personalization/resolvers/MergeTagValueResolver.ts","../src/personalization/resolvers/PersonalizedEntryResolver.ts","../src/signals.ts","../../../lib/logger/src/Logger.ts","../../../lib/logger/src/LogSink.ts","../../../lib/logger/src/ConsoleLogSink.ts","webpack/runtime/compat_get_default_export","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object"],"sourcesContent":["import {\n ApiClient,\n EventBuilder,\n type InsightsEvent as AnalyticsEvent,\n type ApiClientConfig,\n type ChangeArray,\n type ComponentViewBuilderArgs,\n type EventBuilderConfig,\n type ExperienceApiClientConfig,\n type GlobalApiConfigProperties,\n type IdentifyBuilderArgs,\n type InsightsApiClientConfig,\n type Json,\n type MergeTagEntry,\n type OptimizationData,\n type PageViewBuilderArgs,\n type PartialProfile,\n type ExperienceEvent as PersonalizationEvent,\n type Profile,\n type ScreenViewBuilderArgs,\n type SelectedPersonalizationArray,\n type TrackBuilderArgs,\n} from '@contentful/optimization-api-client'\nimport type { ChainModifiers, Entry, EntrySkeletonType, LocaleCode } from 'contentful'\nimport type { LogLevels } from 'logger'\nimport { ConsoleLogSink, logger } from 'logger'\nimport type AnalyticsBase from './analytics/AnalyticsBase'\nimport { OPTIMIZATION_CORE_SDK_VERSION } from './global-constants'\nimport { InterceptorManager } from './lib/interceptor'\nimport type { ResolvedData } from './personalization'\nimport type PersonalizationBase from './personalization/PersonalizationBase'\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<AnalyticsEvent | PersonalizationEvent>\n /** Interceptors invoked before optimization state updates. */\n state: InterceptorManager<OptimizationData>\n}\n\n/**\n * Options for configuring the {@link CoreBase} runtime and underlying clients.\n *\n * @public\n */\nexport interface CoreConfig extends Pick<ApiClientConfig, GlobalApiConfigProperties> {\n /**\n * Configuration for the personalization (Experience) API client.\n */\n personalization?: Omit<ExperienceApiClientConfig, GlobalApiConfigProperties>\n\n /**\n * Configuration for the analytics (Insights) API client.\n */\n analytics?: Omit<InsightsApiClientConfig, GlobalApiConfigProperties>\n\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\n/**\n * Internal base that wires the API client, event builder, and logging.\n *\n * @internal\n */\nabstract class CoreBase {\n /** Product implementation for analytics. */\n abstract readonly analytics: AnalyticsBase\n /** Product implementation for personalization. */\n abstract readonly personalization: PersonalizationBase\n\n /** Shared Optimization API client instance. */\n readonly api: ApiClient\n /** Shared event builder instance. */\n readonly eventBuilder: EventBuilder\n /** Resolved core configuration (minus any name metadata). */\n readonly config: Omit<CoreConfig, 'name'>\n\n readonly interceptors: LifecycleInterceptors = {\n event: new InterceptorManager<AnalyticsEvent | PersonalizationEvent>(),\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: CoreConfig) {\n this.config = config\n\n const { analytics, personalization, eventBuilder, logLevel, environment, clientId } = config\n\n logger.addSink(new ConsoleLogSink(logLevel))\n\n const apiConfig = {\n ...analytics,\n ...personalization,\n clientId,\n environment,\n }\n\n this.api = new ApiClient(apiConfig)\n\n this.eventBuilder = new EventBuilder(\n eventBuilder ?? {\n channel: 'server',\n library: { name: 'Optimization Core', 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 personalization’s flag resolution.\n */\n getCustomFlag(name: string, changes?: ChangeArray): Json {\n return this.personalization.getCustomFlag(name, changes)\n }\n\n /**\n * Resolve a Contentful entry to the appropriate personalized 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 personalizations - Optional selection array for the current profile.\n * @returns {@link ResolvedData} containing the resolved entry and\n * personalization metadata (if any).\n */\n personalizeEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(entry: Entry<S, M, L>, personalizations?: SelectedPersonalizationArray): ResolvedData<S, M, L> {\n return this.personalization.personalizeEntry<S, M, L>(entry, personalizations)\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 */\n getMergeTagValue(embeddedEntryNodeTarget: MergeTagEntry, profile?: Profile): unknown {\n return this.personalization.getMergeTagValue(embeddedEntryNodeTarget, profile)\n }\n\n /**\n * Convenience wrapper for sending an `identify` event via personalization.\n *\n * @param payload - Identify builder arguments.\n * @returns The resulting {@link OptimizationData} for the identified user.\n */\n async identify(\n payload: IdentifyBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData | undefined> {\n return await this.personalization.identify(payload)\n }\n\n /**\n * Convenience wrapper for sending a `page` event via personalization.\n *\n * @param payload - Page view builder arguments.\n * @returns The evaluated {@link OptimizationData} for this page view.\n */\n async page(\n payload: PageViewBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData | undefined> {\n return await this.personalization.page(payload)\n }\n\n /**\n * Convenience wrapper for sending a `screen` event via personalization.\n *\n * @param payload - Screen view builder arguments.\n * @returns The evaluated {@link OptimizationData} for this screen view.\n */\n async screen(\n payload: ScreenViewBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData | undefined> {\n return await this.personalization.screen(payload)\n }\n\n /**\n * Convenience wrapper for sending a custom `track` event via personalization.\n *\n * @param payload - Track builder arguments.\n * @returns The evaluated {@link OptimizationData} for this event.\n */\n async track(\n payload: TrackBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData | undefined> {\n return await this.personalization.track(payload)\n }\n\n /**\n * Track a component view in both personalization and analytics.\n *\n * @param payload - Component view builder arguments. When `payload.sticky` is\n * `true`, the event will also be sent via personalization as a sticky\n * component view.\n * @param duplicationScope - Optional string used to scope duplication used in Stateful\n * implementations\n * @returns A promise that resolves when all delegated calls complete.\n * @remarks\n * The sticky behavior is delegated to personalization; analytics is always\n * invoked regardless of `sticky`.\n */\n async trackComponentView(\n payload: ComponentViewBuilderArgs & { profile?: PartialProfile },\n duplicationScope?: string,\n ): Promise<OptimizationData | undefined> {\n if (payload.sticky) {\n return await this.personalization.trackComponentView(payload, duplicationScope)\n }\n\n await this.analytics.trackComponentView(payload, duplicationScope)\n }\n\n /**\n * Track a feature flag view via analytics.\n *\n * @param payload - Component view builder arguments used to build the flag view event.\n * @param duplicationScope - Optional string used to scope duplication used in Stateful\n * implementations\n * @returns A promise that resolves when processing completes.\n */\n async trackFlagView(payload: ComponentViewBuilderArgs, duplicationScope?: string): Promise<void> {\n await this.analytics.trackFlagView(payload, duplicationScope)\n }\n}\n\nexport default CoreBase\n","import type {\n InsightsEvent as AnalyticsEvent,\n ChangeArray,\n ExperienceEvent as PersonalizationEvent,\n Profile,\n SelectedPersonalizationArray,\n} from '@contentful/optimization-api-client'\nimport { AnalyticsStateful, type AnalyticsStates } from './analytics'\nimport type { ConsentController } from './Consent'\nimport CoreBase, { type CoreConfig } from './CoreBase'\nimport {\n PersonalizationStateful,\n type PersonalizationProductConfig,\n type PersonalizationStates,\n} from './personalization'\nimport type { ProductConfig } from './ProductBase'\nimport {\n batch,\n changes,\n consent,\n event,\n flags,\n online,\n personalizations,\n profile,\n signals,\n toObservable,\n type Observable,\n type Signals,\n} from './signals'\n\n/**\n * Interface for objects that can be registered with the preview panel system.\n * When registered, the object receives direct access to SDK signals for state manipulation.\n *\n * @public\n */\nexport interface PreviewPanelSignalObject {\n /** Signals instance that will be populated by registerPreviewPanel */\n signals: Signals | null\n}\n\n/**\n * Combined observable state exposed by the stateful core.\n *\n * @public\n * @see {@link AnalyticsStates}\n * @see {@link PersonalizationStates}\n */\nexport interface CoreStates extends AnalyticsStates, PersonalizationStates {\n /** Current consent value (if any). */\n consent: Observable<boolean | undefined>\n /** Stream of the most recent event emitted (analytics or personalization). */\n eventStream: Observable<AnalyticsEvent | PersonalizationEvent | undefined>\n}\n\n/**\n * Default values used to preconfigure the stateful core and products.\n *\n * @public\n */\nexport interface CoreConfigDefaults {\n /** Global consent default applied at construction time. */\n consent?: boolean\n /** Default active profile used for personalization and analytics. */\n profile?: Profile\n /** Initial diff of changes produced by the service. */\n changes?: ChangeArray\n /** Preselected personalization variants (e.g., winning treatments). */\n personalizations?: SelectedPersonalizationArray\n}\n\n/**\n * Configuration for {@link CoreStateful}.\n *\n * @public\n * @see {@link CoreConfig}\n */\nexport interface CoreStatefulConfig extends CoreConfig {\n /**\n * Allow-listed event type strings permitted when consent is not set.\n *\n * @see {@link ProductConfig.allowedEventTypes}\n */\n allowedEventTypes?: ProductConfig['allowedEventTypes']\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?: PersonalizationProductConfig['getAnonymousId']\n\n /**\n * Initial duplication prevention configuration for component events.\n *\n * @see {@link ProductConfig.preventedComponentEvents}\n */\n preventedComponentEvents?: ProductConfig['preventedComponentEvents']\n}\n\n/**\n * Core runtime that constructs stateful product instances and exposes shared\n * states, including consent and the event stream.\n *\n * @public\n * @remarks\n * @see {@link CoreBase}\n * @see {@link ConsentController}\n */\nclass CoreStateful extends CoreBase implements ConsentController {\n /** Stateful analytics product. */\n readonly analytics: AnalyticsStateful\n /** Stateful personalization product. */\n readonly personalization: PersonalizationStateful\n\n /**\n * Create a stateful core with optional default consent and product defaults.\n *\n * @param config - Core and defaults configuration.\n * @example\n * ```ts\n * const core = new CoreStateful({\n * clientId: 'app',\n * environment: 'prod',\n * defaults: { consent: true }\n * })\n * core.consent(true)\n * ```\n */\n constructor(config: CoreStatefulConfig) {\n super(config)\n\n const { allowedEventTypes, defaults, getAnonymousId, preventedComponentEvents } = config\n\n if (defaults?.consent !== undefined) {\n const { consent: defaultConsent } = defaults\n consent.value = defaultConsent\n }\n\n this.analytics = new AnalyticsStateful({\n api: this.api,\n builder: this.eventBuilder,\n config: {\n allowedEventTypes,\n preventedComponentEvents,\n defaults: {\n consent: defaults?.consent,\n profile: defaults?.profile,\n },\n },\n interceptors: this.interceptors,\n })\n\n this.personalization = new PersonalizationStateful({\n api: this.api,\n builder: this.eventBuilder,\n config: {\n allowedEventTypes,\n getAnonymousId,\n preventedComponentEvents,\n defaults: {\n consent: defaults?.consent,\n changes: defaults?.changes,\n profile: defaults?.profile,\n personalizations: defaults?.personalizations,\n },\n },\n interceptors: this.interceptors,\n })\n }\n\n /**\n * Expose merged observable state for consumers.\n */\n get states(): CoreStates {\n return {\n consent: toObservable(consent),\n eventStream: toObservable(event),\n flags: toObservable(flags),\n personalizations: toObservable(personalizations),\n profile: toObservable(profile),\n }\n }\n\n /**\n * Reset internal state. Consent is intentionally preserved.\n *\n * @remarks\n * Resetting personalization also resets analytics dependencies as a\n * consequence of the current shared-state design.\n */\n reset(): void {\n batch(() => {\n event.value = undefined\n changes.value = undefined\n profile.value = undefined\n personalizations.value = undefined\n })\n }\n\n /**\n * Flush the queues for both the analytics and personalization products.\n * @remarks\n * The personalization queue is only populated if events have been triggered\n * while a device is offline.\n */\n async flush(): Promise<void> {\n await this.analytics.flush()\n await this.personalization.flush()\n }\n\n /**\n * Update consent state\n *\n * @param accept - `true` if the user has granted consent; `false` otherwise.\n */\n consent(accept: boolean): void {\n consent.value = accept\n }\n\n /**\n * Update online state\n *\n * @param isOnline - `true` if the browser is online; `false` otherwise.\n */\n protected online(isOnline: boolean): void {\n online.value = isOnline\n }\n\n /**\n * Register a preview panel compatible object to receive direct signal access.\n * This enables the preview panel to modify SDK state for testing and simulation.\n *\n * @param previewPanel - An object implementing PreviewPanelSignalObject\n * @remarks\n * This method is intended for use by the Preview Panel component.\n * Direct signal access allows immediate state updates without API calls.\n */\n registerPreviewPanel(previewPanel: PreviewPanelSignalObject): void {\n previewPanel.signals = signals\n }\n}\n\nexport default CoreStateful\n","import type { EventBuilderConfig } from '@contentful/optimization-api-client'\nimport { AnalyticsStateless } from './analytics'\nimport CoreBase, { type CoreConfig } from './CoreBase'\nimport { PersonalizationStateless } from './personalization'\n\n/**\n * Configuration for the Node-specific Optimization SDK.\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 * Override configuration for the analytics (Insights) API client. Omits\n * `beaconHandler`.\n */\n analytics?: Omit<CoreConfig['analytics'], 'beaconHandler'>\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\n/**\n * Core runtime that constructs product instances for stateless environments.\n *\n * @public\n * @see {@link CoreBase}\n */\nclass CoreStateless extends CoreBase {\n /** Stateless analytics product. */\n readonly analytics: AnalyticsStateless\n /** Stateless personalization product. */\n readonly personalization: PersonalizationStateless\n\n /**\n * Create a stateless core. Product instances share the same API client and\n * event builder configured in {@link CoreBase}.\n *\n * @param config - Stateless Core configuration.\n * @example\n * ```ts\n * const sdk = new CoreStateless({ clientId: 'app', environment: 'prod' })\n * core.analytics.trackFlagView({ componentId: 'hero' })\n * // or\n * core.trackFlagView({ componentId: 'hero' })\n * ```\n */\n constructor(config: CoreStatelessConfig) {\n super(config)\n\n this.analytics = new AnalyticsStateless({\n api: this.api,\n builder: this.eventBuilder,\n interceptors: this.interceptors,\n })\n\n this.personalization = new PersonalizationStateless({\n api: this.api,\n builder: this.eventBuilder,\n interceptors: this.interceptors,\n })\n }\n}\n\nexport default CoreStateless\n","import type {\n InsightsEventType as AnalyticsEventType,\n ApiClient,\n EventBuilder,\n ExperienceEventType as PersonalizationEventType,\n} from '@contentful/optimization-api-client'\nimport type { LifecycleInterceptors } from './CoreBase'\nimport ValuePresence from './lib/value-presence/ValuePresence'\n\n/**\n * Union of all event {@link AnalyticsEventType | type keys} that this package may emit.\n *\n * @public\n */\nexport type EventType = AnalyticsEventType | PersonalizationEventType\n\n/**\n * Default allow‑list of event types that can be emitted without explicit consent.\n *\n * @internal\n * @privateRemarks These defaults are only applied when a consumer does not provide\n * {@link ProductConfig.allowedEventTypes}.\n */\nconst defaultAllowedEvents: EventType[] = ['page', 'identify']\n\n/**\n * Common configuration for all product implementations.\n *\n * @public\n */\nexport interface ProductConfig {\n /**\n * The set of event type strings that are allowed to be sent even if consent is\n * not granted.\n *\n * @defaultValue `['page', 'identify']`\n * @remarks These types are compared against the `type` property of events.\n */\n allowedEventTypes?: EventType[]\n\n /**\n * A map of duplication keys to a list of component IDs that should be\n * considered duplicates and therefore suppressed.\n *\n * @remarks\n * The actual duplication check is performed by {@link ValuePresence}. The\n * keys of this record are used as duplication scopes. An empty string `''`\n * is converted to an `indefined` scope when specific scopes are not required.\n */\n preventedComponentEvents?: Record<string, string[]>\n}\n\n/**\n * Options for configuring the common functionality of {@link ProductBase} descendents.\n *\n * @public\n */\nexport interface ProductBaseOptions {\n /** Optimization API client. */\n api: ApiClient\n /** Event builder for constructing events. */\n builder: EventBuilder\n /** Optional configuration for allow‑lists and duplication prevention. */\n config?: ProductConfig\n /** Lifecycle container for event and state interceptors. */\n interceptors: LifecycleInterceptors\n}\n\n/**\n * Shared base for all product implementations.\n *\n * @internal\n * @remarks\n * This abstract class is not exported as part of the public API surface.\n * Concrete implementations (e.g., analytics) should extend this class and\n * expose their own public methods.\n */\nabstract class ProductBase {\n /**\n * Allow‑list of event {@link AnalyticsEventType | type keys} permitted when consent is not present.\n */\n protected readonly allowedEventTypes?: string[]\n\n /** Event builder used to construct strongly‑typed events. */\n protected readonly builder: EventBuilder\n\n /** Optimization API client used to send events to the Experience and Insights APIs. */\n protected readonly api: ApiClient\n\n /**\n * Deduplication helper used to track previously seen values within optional\n * scopes\n */\n readonly duplicationDetector: ValuePresence\n\n /** Interceptors that can mutate/augment outgoing events or optimization state. */\n readonly interceptors: LifecycleInterceptors\n\n /**\n * Creates a new product base instance.\n *\n * @param options - Options for configuring the functionality common among products.\n */\n constructor(options: ProductBaseOptions) {\n const { api, builder, config, interceptors } = options\n this.allowedEventTypes = config?.allowedEventTypes ?? defaultAllowedEvents\n this.api = api\n this.builder = builder\n this.duplicationDetector = new ValuePresence(config?.preventedComponentEvents)\n this.interceptors = interceptors\n }\n}\n\nexport default ProductBase\n","import type { ComponentViewBuilderArgs } from '@contentful/optimization-api-client'\nimport ProductBase from '../ProductBase'\n\n/**\n * Base class for analytics implementations (internal).\n *\n * @internal\n * @remarks\n * Concrete analytics classes should implement the component/flag view tracking\n * methods below. This base is not part of the public API.\n */\nabstract class AnalyticsBase extends ProductBase {\n /**\n * Track a UI component view event.\n *\n * @param payload - Component view builder arguments.\n * @param duplicationScope - Optional string used to scope duplication used in Stateful\n * implementations.\n * @privateRemarks\n * Duplication prevention should be handled in Stateful implementations\n */\n abstract trackComponentView(\n payload: ComponentViewBuilderArgs,\n duplicationScope?: string,\n ): Promise<void> | void\n\n /**\n * Track a flag (feature) view event.\n *\n * @param payload - Flag view builder arguments.\n * @param duplicationScope - Optional string used to scope duplication used in Stateful\n * implementations.\n * @returns A promise that resolves when processing is complete (or `void`).\n * @privateRemarks\n * Duplication prevention should be handled in Stateful implementations\n */\n abstract trackFlagView(\n payload: ComponentViewBuilderArgs,\n duplicationScope?: string,\n ): Promise<void> | void\n}\n\nexport default AnalyticsBase\n","import {\n InsightsEvent as AnalyticsEvent,\n type BatchInsightsEventArray,\n type ComponentViewBuilderArgs,\n type InsightsEventArray,\n type ExperienceEvent as PersonalizationEvent,\n type Profile,\n} from '@contentful/optimization-api-client'\nimport { createScopedLogger } from 'logger'\nimport type { ConsentGuard } from '../Consent'\nimport { guardedBy } from '../lib/decorators'\nimport type { ProductBaseOptions, ProductConfig } from '../ProductBase'\nimport {\n batch,\n consent,\n effect,\n event as eventSignal,\n online as onlineSignal,\n profile as profileSignal,\n toObservable,\n type Observable,\n} from '../signals'\nimport AnalyticsBase from './AnalyticsBase'\n\nconst logger = createScopedLogger('Analytics')\n\n/**\n * Default analytics state values applied at construction time.\n *\n * @public\n */\nexport interface AnalyticsProductConfigDefaults {\n /** Whether analytics collection is allowed by default. */\n consent?: boolean\n /** Default profile to associate with events. */\n profile?: Profile\n}\n\n/**\n * Configuration for the stateful analytics implementation.\n *\n * @public\n */\nexport interface AnalyticsProductConfig extends ProductConfig {\n /**\n * Default signal values applied on initialization.\n */\n defaults?: AnalyticsProductConfigDefaults\n}\n\n/**\n * Observables exposed by the stateful analytics product.\n *\n * @public\n */\nexport interface AnalyticsStates {\n /** Observable stream of the latest {@link AnalyticsEvent} or {@link PersonalizationEvent} (or `undefined`). */\n eventStream: Observable<AnalyticsEvent | PersonalizationEvent | undefined>\n /** Observable stream of the active {@link Profile} (or `undefined`). */\n profile: Observable<Profile | undefined>\n}\n\n/**\n * Options for configuring {@link AnalyticsStateful} functionality.\n *\n * @public\n * @see {@link ProductBaseOptions}\n */\nexport type AnalyticsStatefulOptions = ProductBaseOptions & {\n /** Configuration specific to the Analytics product */\n config?: AnalyticsProductConfig\n}\n\n/**\n * Maximum number of queued events before an automatic flush is triggered.\n */\nconst MAX_QUEUED_EVENTS = 25\n\n/**\n * Analytics implementation that maintains local state (consent, profile) and\n * queues events until flushed or the queue reaches a maximum size.\n *\n * @public\n */\nclass AnalyticsStateful extends AnalyticsBase implements ConsentGuard {\n /** In‑memory queue keyed by profile. */\n private readonly queue = new Map<Profile, InsightsEventArray>()\n\n /** Exposed observable state references. */\n readonly states: AnalyticsStates = {\n eventStream: toObservable(eventSignal),\n profile: toObservable(profileSignal),\n }\n\n /**\n * Create a new stateful analytics instance.\n *\n * @param options - Options to configure the analytics product for stateful environments.\n */\n constructor(options: AnalyticsStatefulOptions) {\n const { api, builder, config, interceptors } = options\n\n super({ api, builder, config, interceptors })\n\n const { defaults } = config ?? {}\n\n if (defaults?.profile !== undefined) {\n const { profile: defaultProfile } = defaults\n profileSignal.value = defaultProfile\n }\n\n effect(() => {\n const id = profileSignal.value?.id\n\n logger.info(\n `Analytics ${consent.value ? 'will' : 'will not'} be collected due to consent (${consent.value})`,\n )\n\n logger.debug(`Profile ${id && `with ID ${id}`} has been ${id ? 'set' : 'cleared'}`)\n })\n\n effect(() => {\n if (onlineSignal.value) void this.flush()\n })\n }\n\n /**\n * Reset analytics‑related signals and the last emitted event.\n */\n reset(): void {\n batch(() => {\n eventSignal.value = undefined\n profileSignal.value = undefined\n })\n }\n\n /**\n * Determine whether the named operation is permitted based on consent and\n * allowed event type configuration.\n *\n * @param name - The method name; `'trackComponentView'` is normalized\n * to `'component'` for allow‑list checks.\n * @returns `true` if the operation is permitted; otherwise `false`.\n */\n hasConsent(name: string): boolean {\n return (\n !!consent.value ||\n (this.allowedEventTypes ?? []).includes(\n name === 'trackComponentView' || name === 'trackFlagView' ? 'component' : name,\n )\n )\n }\n\n /**\n * Hook invoked when an operation is blocked due to missing consent.\n *\n * @param name - The blocked operation name.\n * @param payload - The original arguments supplied to the operation.\n */\n onBlockedByConsent(name: string, payload: unknown[]): void {\n logger.warn(\n `Event \"${name}\" was blocked due to lack of consent; payload: ${JSON.stringify(payload)}`,\n )\n }\n\n /**\n * Guard used to suppress duplicate component/flag view events based on a\n * duplication key and the component identifier.\n *\n * @param _name - The operation name (unused).\n * @param payload - Tuple of [builderArgs, duplicationScope].\n * @returns `true` if the event is NOT a duplicate and should proceed.\n */\n isNotDuplicated(_name: string, payload: [ComponentViewBuilderArgs, string]): boolean {\n const [{ componentId: value }, duplicationScope] = payload\n\n const isDuplicated = this.duplicationDetector.isPresent(duplicationScope, value)\n\n if (!isDuplicated) this.duplicationDetector.addValue(duplicationScope, value)\n\n return !isDuplicated\n }\n\n /**\n * Hook invoked when an operation is blocked by the duplication guard.\n *\n * @param name - The blocked operation name.\n * @param payload - The original arguments supplied to the operation.\n */\n onBlockedByDuplication(name: string, payload: unknown[]): void {\n const componentType = name === 'trackFlagView' ? 'flag' : 'component'\n\n logger.debug(\n `Duplicate \"${componentType} view\" event detected, skipping; payload: ${JSON.stringify(payload)}`,\n )\n }\n\n /**\n * Queue a component view event for the active profile.\n *\n * @param payload - Component view builder arguments.\n * @param _duplicationScope - Optional string used to scope duplication (used\n * by guards); an empty string `''` is converted to the `undefined` scope\n */\n @guardedBy('isNotDuplicated', { onBlocked: 'onBlockedByDuplication' })\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async trackComponentView(\n payload: ComponentViewBuilderArgs,\n _duplicationScope = '',\n ): Promise<void> {\n logger.info(`Processing \"component view\" event for ${payload.componentId}`)\n\n await this.enqueueEvent(this.builder.buildComponentView(payload))\n }\n\n /**\n * Queue a flag view event for the active profile.\n *\n * @param payload - Flag view builder arguments.\n * @param _duplicationScope - Optional string used to scope duplication (used\n * by guards); an empty string `''` is converted to the `undefined` scope\n */\n @guardedBy('isNotDuplicated', { onBlocked: 'onBlockedByDuplication' })\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async trackFlagView(payload: ComponentViewBuilderArgs, _duplicationScope = ''): Promise<void> {\n logger.debug(`Processing \"flag view\" event for ${payload.componentId}`)\n\n await this.enqueueEvent(this.builder.buildFlagView(payload))\n }\n\n /**\n * Intercept, validate, and place an event into the profile‑scoped queue; then\n * trigger a size‑based flush if necessary.\n *\n * @param event - The event to enqueue.\n */\n private async enqueueEvent(event: AnalyticsEvent): Promise<void> {\n const { value: profile } = profileSignal\n\n if (!profile) {\n logger.warn('Attempting to emit an event without an Optimization profile')\n\n return\n }\n\n const intercepted = await this.interceptors.event.run(event)\n\n const validEvent = AnalyticsEvent.parse(intercepted)\n\n logger.debug(`Queueing ${validEvent.type} event for profile ${profile.id}`, validEvent)\n\n const profileEventQueue = this.queue.get(profile)\n\n eventSignal.value = validEvent\n\n if (profileEventQueue) {\n profileEventQueue.push(validEvent)\n } else {\n this.queue.set(profile, [validEvent])\n }\n\n await this.flushMaxEvents()\n }\n\n /**\n * Flush the queue automatically when the total number of queued events\n * reaches {@link MAX_QUEUED_EVENTS}.\n */\n private async flushMaxEvents(): Promise<void> {\n if (this.queue.values().toArray().flat().length >= MAX_QUEUED_EVENTS) await this.flush()\n }\n\n /**\n * Send all queued events grouped by profile and clear the queue.\n * @remarks Only under rare circumstances should there be more than one\n * profile in a stateful application.\n */\n async flush(): Promise<void> {\n logger.debug('Flushing event queue')\n\n const batches: BatchInsightsEventArray = []\n\n this.queue.forEach((events, profile) => batches.push({ profile, events }))\n\n if (!batches.length) return\n\n const sendSuccess = await this.api.insights.sendBatchEvents(batches)\n\n if (sendSuccess) this.queue.clear()\n }\n}\n\nexport default AnalyticsStateful\n","import {\n BatchInsightsEventArray,\n type ComponentViewBuilderArgs,\n ComponentViewEvent,\n type InsightsEvent,\n type PartialProfile,\n} from '@contentful/optimization-api-client'\nimport { createScopedLogger } from 'logger'\nimport AnalyticsBase from './AnalyticsBase'\n\nconst logger = createScopedLogger('Analytics')\n\n/**\n * Arguments for tracking a component/flag view in stateless mode.\n *\n * @public\n * @remarks\n * The `profile` is optional; when omitted, the APIs may infer identity via\n * other means.\n */\nexport type TrackViewArgs = ComponentViewBuilderArgs & { profile?: PartialProfile }\n\n/**\n * Stateless analytics implementation that sends each event immediately in a\n * single‑event batch.\n *\n * @public\n */\nclass AnalyticsStateless extends AnalyticsBase {\n /**\n * Build, intercept, validate, and send a component view event.\n *\n * @param args - {@link TrackViewArgs} used to build the event. Includes an\n * optional partial profile.\n * @returns A promise that resolves once the batch has been sent.\n */\n async trackComponentView(args: TrackViewArgs): Promise<void> {\n logger.info('Processing \"component view\" event')\n\n const { profile, ...builderArgs } = args\n\n const event = this.builder.buildComponentView(builderArgs)\n\n const intercepted = await this.interceptors.event.run(event)\n\n const parsed = ComponentViewEvent.parse(intercepted)\n\n await this.sendBatchEvent(parsed, profile)\n }\n\n /**\n * Build, intercept, validate, and send a flag view event.\n *\n * @param args - {@link TrackViewArgs} used to build the event. Includes an\n * optional partial profile.\n * @returns A promise that resolves once the batch has been sent.\n */\n async trackFlagView(args: TrackViewArgs): Promise<void> {\n logger.debug('Processing \"flag view\" event')\n\n const { profile, ...builderArgs } = args\n\n const event = this.builder.buildFlagView(builderArgs)\n\n const intercepted = await this.interceptors.event.run(event)\n\n const parsed = ComponentViewEvent.parse(intercepted)\n\n await this.sendBatchEvent(parsed, profile)\n }\n\n /**\n * Send a single {@link InsightsEvent} wrapped in a one‑item batch.\n *\n * @param event - The event to send.\n * @param profile - Optional partial profile to attach to the batch.\n * @returns A promise that resolves when the API call completes.\n * @internal\n */\n private async sendBatchEvent(event: InsightsEvent, profile?: PartialProfile): Promise<void> {\n const batchEvent: BatchInsightsEventArray = BatchInsightsEventArray.parse([\n {\n profile,\n events: [event],\n },\n ])\n\n await this.api.insights.sendBatchEvents(batchEvent)\n }\n}\n\nexport default AnalyticsStateless\n","// eslint-disable-next-line @typescript-eslint/naming-convention -- Replaced at build-time\ndeclare const __OPTIMIZATION_VERSION__: string | undefined\n\nexport const OPTIMIZATION_CORE_SDK_VERSION =\n typeof __OPTIMIZATION_VERSION__ === 'string' ? __OPTIMIZATION_VERSION__ : '0.0.0'\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 personalization and analytics\n * events when no explicit profile is known.\n *\n * @example\n * ```ts\n * import { ANONYMOUS_ID_COOKIE } from '@contentful/optimization-core'\n * const profileId = request.cookies[ANONYMOUS_ID_COOKIE]\n * ```\n */\nexport const ANONYMOUS_ID_COOKIE = 'ctfl-opt-aid'\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 */\ntype 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 */\ntype 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 {@link GuardedByOptions | options} 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","/**\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 */\ntype 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 readonly view to discourage mutation of intermediate values.\n // Each interceptor must return a T (or Promise<T>).\n acc = await fn(acc as Readonly<T>)\n }\n\n return acc\n }\n}\n","/**\n * A scope identifier for grouping values.\n *\n * @remarks\n * Use a non-empty string for a named scope. Use `undefined` for the\n * \"global/default\" scope. An empty string (`\"\"`) passed to the constructor\n * initializer is normalized to `undefined`.\n *\n * @public\n */\ntype ValuePresenceScope = string | undefined\n\n/**\n * Tracks whether a given value is present within one or more logical scopes.\n *\n * @remarks\n * - Scope names are case-sensitive.\n * - Presence is based on `Set.has` reference equality for objects and\n * value equality for primitives.\n *\n * @example\n * ```ts\n * const presence = new ValuePresence({ default: ['a', 'b'] })\n * presence.isPresent('default', 'a') // true\n * presence.addValue('default', 'c')\n * presence.removeValue('default', 'b')\n * presence.reset('default')\n * ```\n *\n * @see {@link ValuePresenceScope}\n * @public\n */\nclass ValuePresence {\n /**\n * Internal map of scope -> set of values present in that scope.\n *\n * @internal\n */\n readonly #map: Map<ValuePresenceScope, Set<unknown>>\n\n /**\n * Create a new {@link ValuePresence}.\n *\n * @param defaultMap - Optional initial data. Keys are scope names; values are arrays of items to seed.\n * Empty-string keys are normalized to the default scope (`undefined`).\n *\n * @remarks\n * - If `defaultMap` contains duplicate items for a scope, duplicates are collapsed by the `Set`.\n */\n constructor(defaultMap?: Record<string, unknown[]>) {\n const map = new Map<ValuePresenceScope, Set<unknown>>()\n\n if (defaultMap)\n Object.entries(defaultMap).map(([scope, values]) =>\n map.set(scope.length ? scope : undefined, new Set(values)),\n )\n\n this.#map = map\n }\n\n /**\n * Check whether a value is present within a given scope.\n *\n * @param scope - The scope to check. Use `undefined` for the default scope.\n * @param value - The value to test for presence.\n * @returns `true` if the value is present in the specified scope; otherwise `false`.\n *\n * @remarks\n * Presence testing uses `Set.prototype.has` semantics.\n *\n * @example\n * ```ts\n * presence.isPresent(undefined, 42) // e.g., true or false\n * ```\n *\n * @public\n */\n isPresent(scope: ValuePresenceScope, value: unknown): boolean {\n return this.#map.get(scope)?.has(value) ?? false\n }\n\n /**\n * Add a value to a scope, creating the scope if it does not exist.\n *\n * @param scope - Scope to add the value to. Use `undefined` for the default scope.\n * @param value - The value to add.\n * @returns void\n *\n * @remarks\n * - No-op if the value is already present (due to `Set` semantics).\n *\n * @example\n * ```ts\n * presence.addValue('users', userId)\n * ```\n *\n * @public\n */\n addValue(scope: ValuePresenceScope, value: unknown): void {\n const values = this.#map.get(scope)\n\n if (!values) {\n this.#map.set(scope, new Set([value]))\n } else {\n values.add(value)\n }\n }\n\n /**\n * Remove a value from a scope.\n *\n * @param scope - Scope to remove from. Use `undefined` for the default scope.\n * @param value - The value to remove.\n * @returns void\n *\n * @remarks\n * If the scope does not exist or the value is not present, this is a no-op.\n *\n * @example\n * ```ts\n * presence.removeValue('users', userId)\n * ```\n *\n * @public\n */\n removeValue(scope: ValuePresenceScope, value: unknown): void {\n this.#map.get(scope)?.delete(value)\n }\n\n /**\n * Clear values from a single scope, or from all scopes.\n *\n * @param scope - If provided, clears only that scope. If omitted, clears all scopes.\n * @returns void\n *\n * @remarks\n * - When called with a specific scope that does not exist, this is a no-op.\n * - When called with no arguments, all scopes and values are removed.\n * - Clearing a non-existent scope will not create the scope.\n *\n * @example\n * ```ts\n * // Clear one scope\n * presence.reset('users')\n *\n * // Clear all scopes\n * presence.reset()\n * ```\n *\n * @public\n */\n reset(scope?: ValuePresenceScope): void {\n if (scope !== undefined) {\n this.#map.get(scope)?.clear()\n } else {\n this.#map.clear()\n }\n }\n}\n\nexport default ValuePresence\n","import type {\n ChangeArray,\n ComponentViewBuilderArgs,\n IdentifyBuilderArgs,\n Json,\n MergeTagEntry,\n OptimizationData,\n PageViewBuilderArgs,\n Profile,\n ScreenViewBuilderArgs,\n SelectedPersonalizationArray,\n TrackBuilderArgs,\n} from '@contentful/optimization-api-client'\nimport type { ChainModifiers, Entry, EntrySkeletonType, LocaleCode } from 'contentful'\nimport ProductBase from '../ProductBase'\nimport {\n FlagsResolver,\n MergeTagValueResolver,\n PersonalizedEntryResolver,\n type ResolvedData,\n} from './resolvers'\n\n/**\n * These methods assist in resolving values via Resolvers\n *\n * @internal\n * @privateRemarks\n * This interface exists to document that the included methods should not be\n * considered static.\n */\ninterface ResolverMethods {\n /**\n * Get the specified Custom Flag's value from the supplied changes.\n * @param name - The name or key of the Custom Flag.\n * @param changes - Optional changes array.\n * @returns The current value of the Custom Flag if found.\n * @remarks\n * The changes array can be sourced from the data returned when emitting any\n * personalization event.\n * */\n getCustomFlag: (name: string, changes?: ChangeArray) => Json\n\n /**\n * Resolve a Contentful entry to a personalized variant using the current\n * or provided selected personalizations.\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam M - Chain modifiers.\n * @typeParam L - Locale code.\n * @param entry - The entry to personalize.\n * @param personalizations - Optional selections.\n * @returns The resolved entry data.\n * @remarks\n * Selected personalizations can be sourced from the data returned when emitting any\n * personalization event.\n */\n personalizeEntry: <S extends EntrySkeletonType, M extends ChainModifiers, L extends LocaleCode>(\n entry: Entry<S, M, L>,\n personalizations?: SelectedPersonalizationArray,\n ) => ResolvedData<S, M, L>\n\n /**\n * Resolve a merge tag to a value based on the current (or provided) profile.\n *\n * @param embeddedEntryNodeTarget - The merge‑tag entry node to resolve.\n * @param profile - Optional profile.\n * @returns The resolved value (type depends on the tag).\n * @remarks\n * Merge tags are references to profile data that can be substituted into content. The\n * profile can be sourced from the data returned when emitting any personalization event.\n */\n getMergeTagValue: (embeddedEntryNodeTarget: MergeTagEntry, profile?: Profile) => unknown\n}\n\n/**\n * Internal base for personalization products.\n *\n * @internal\n * @remarks\n * Concrete implementations should extend this class to expose public methods for\n * identify, page, and track events. This base wires in shared singleton\n * resolvers used to fetch/resolve personalized data.\n */\nabstract class PersonalizationBase extends ProductBase implements ResolverMethods {\n /**\n * Static {@link FlagsResolver | resolver} for evaluating personalized\n * custom flags.\n */\n readonly flagsResolver = FlagsResolver\n\n /**\n * Static {@link MergeTagValueResolver | resolver} that returns values\n * sourced from a user profile based on a Contentful Merge Tag entry.\n */\n readonly mergeTagValueResolver = MergeTagValueResolver\n\n /**\n * Static {@link PersonalizedEntryResolver | resolver } for personalized\n * Contentful entries (e.g., entry variants targeted to a profile audience).\n *\n * @remarks\n * Used by higher-level personalization flows to materialize entry content\n * prior to event emission.\n */\n readonly personalizedEntryResolver = PersonalizedEntryResolver\n\n /**\n * Get the specified Custom Flag's value from the supplied changes.\n * @param name - The name/key of the Custom Flag.\n * @param changes - Optional changes array.\n * @returns The current value of the Custom Flag if found.\n * @remarks\n * The changes array can be sourced from the data returned when emitting any\n * personalization event.\n * */\n getCustomFlag(name: string, changes?: ChangeArray): Json {\n return FlagsResolver.resolve(changes)[name]\n }\n\n /**\n * Resolve a Contentful entry to a personalized variant using the current\n * or provided selected personalizations.\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam M - Chain modifiers.\n * @typeParam L - Locale code.\n * @param entry - The entry to personalize.\n * @param personalizations - Optional selected personalizations.\n * @returns The resolved entry data.\n * @remarks\n * Selected personalizations can be sourced from the data returned when emitting any\n * personalization event.\n */\n personalizeEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(entry: Entry<S, M, L>, personalizations?: SelectedPersonalizationArray): ResolvedData<S, M, L> {\n return PersonalizedEntryResolver.resolve<S, M, L>(entry, personalizations)\n }\n\n /**\n * Resolve a merge tag to a value based on the current (or provided) profile.\n *\n * @param embeddedEntryNodeTarget - The merge tag entry node to resolve.\n * @param profile - Optional profile.\n * @returns The resolved value (type depends on the tag).\n * @remarks\n * Merge tags are references to profile data that can be substituted into content. The\n * profile can be sourced from the data returned when emitting any personalization event.\n */\n getMergeTagValue(embeddedEntryNodeTarget: MergeTagEntry, profile?: Profile): unknown {\n return MergeTagValueResolver.resolve(embeddedEntryNodeTarget, profile)\n }\n\n /**\n * Identify the current profile/visitor to associate traits with a profile.\n *\n * @param payload - Identify builder payload.\n * @returns The resulting {@link OptimizationData} for the identified user if the device is online.\n */\n abstract identify(payload: IdentifyBuilderArgs): Promise<OptimizationData | undefined>\n\n /**\n * Record a page view.\n *\n * @param payload - Page view builder payload.\n * @returns The evaluated {@link OptimizationData} for this page view if the device is online.\n */\n abstract page(payload: PageViewBuilderArgs): Promise<OptimizationData | undefined>\n\n /**\n * Record a screen view.\n *\n * @param payload - Screen view builder payload.\n * @returns The evaluated {@link OptimizationData} for this screen view if the device is online.\n */\n abstract screen(payload: ScreenViewBuilderArgs): Promise<OptimizationData | undefined>\n\n /**\n * Record a custom track event.\n *\n * @param payload - Track builder payload.\n * @returns The evaluated {@link OptimizationData} for this event if the device is online.\n */\n abstract track(payload: TrackBuilderArgs): Promise<OptimizationData | undefined>\n\n /**\n * Record a \"sticky\" component view.\n *\n * @param payload - \"Sticky\" component view builder payload.\n * @returns The evaluated {@link OptimizationData} for this component view if the device is online.\n * @remarks\n * This method is intended to be called only when a component is considered\n * \"sticky\".\n * @privateRemarks\n * Duplication prevention should be handled in Stateful implementations.\n */\n abstract trackComponentView(\n payload: ComponentViewBuilderArgs,\n duplicationScope?: string,\n ): Promise<OptimizationData | undefined>\n}\n\nexport default PersonalizationBase\n","import {\n type InsightsEvent as AnalyticsEvent,\n type ChangeArray,\n type ComponentViewBuilderArgs,\n type Flags,\n type IdentifyBuilderArgs,\n type Json,\n type MergeTagEntry,\n type OptimizationData,\n type PageViewBuilderArgs,\n ExperienceEvent as PersonalizationEvent,\n type ExperienceEventArray as PersonalizationEventArray,\n type Profile,\n type ScreenViewBuilderArgs,\n type SelectedPersonalizationArray,\n type TrackBuilderArgs,\n} from '@contentful/optimization-api-client'\nimport type { ChainModifiers, Entry, EntrySkeletonType, LocaleCode } from 'contentful'\nimport { isEqual } from 'es-toolkit'\nimport { createScopedLogger } from 'logger'\nimport type { ConsentGuard } from '../Consent'\nimport { guardedBy } from '../lib/decorators'\nimport type { ProductBaseOptions, ProductConfig } from '../ProductBase'\nimport {\n batch,\n changes as changesSignal,\n consent as consentSignal,\n effect,\n event as eventSignal,\n flags as flagsSignal,\n type Observable,\n online as onlineSignal,\n personalizations as personalizationsSignal,\n profile as profileSignal,\n toObservable,\n} from '../signals'\nimport PersonalizationBase from './PersonalizationBase'\nimport type { ResolvedData } from './resolvers'\n\nconst logger = createScopedLogger('Personalization')\n\n/**\n * Default state values for {@link PersonalizationStateful} applied at construction time.\n *\n * @public\n */\nexport interface PersonalizationProductConfigDefaults {\n /** Whether personalization is allowed by default. */\n consent?: boolean\n /** Initial diff of changes produced by the service. */\n changes?: ChangeArray\n /** Default active profile used for personalization. */\n profile?: Profile\n /** Preselected personalization variants (e.g., winning treatments). */\n personalizations?: SelectedPersonalizationArray\n}\n\n/**\n * Configuration for {@link PersonalizationStateful}.\n *\n * @public\n */\nexport interface PersonalizationProductConfig extends ProductConfig {\n /** Default signal values applied during initialization. */\n defaults?: PersonalizationProductConfigDefaults\n\n /**\n * Function used to obtain an anonymous user identifier.\n *\n * @remarks\n * If a `getAnonymousId` function has been provided, the returned value will\n * take precedence over the `id` property of the current {@link Profile}\n * signal value\n *\n * @returns A string identifier, or `undefined` if no anonymous ID is available.\n */\n getAnonymousId?: () => string | undefined\n}\n\n/**\n * Observables exposed by {@link PersonalizationStateful} that mirror internal signals.\n *\n * @public\n */\nexport interface PersonalizationStates {\n /** Observable stream of the latest {@link AnalyticsEvent} or {@link PersonalizationEvent} (or `undefined`). */\n eventStream: Observable<AnalyticsEvent | PersonalizationEvent | undefined>\n /** Live view of effective flags for the current profile (if available). */\n flags: Observable<Flags | undefined>\n /** Live view of the current profile. */\n profile: Observable<Profile | undefined>\n /** Live view of selected personalizations (variants). */\n personalizations: Observable<SelectedPersonalizationArray | undefined>\n}\n\n/**\n * Options for configuring {@link PersonalizationStateful} functionality.\n *\n * @public\n * @see {@link ProductBaseOptions}\n */\nexport type PersonalizationStatefulOptions = ProductBaseOptions & {\n /** Configuration specific to the Personalization product */\n config?: PersonalizationProductConfig\n}\n\n/**\n * Stateful personalization product that manages consent, profile, flags, and\n * selected variants while emitting Experience events and updating state.\n *\n * @public\n * @remarks\n * The class maintains reactive signals and exposes read‑only observables via\n * {@link PersonalizationStateful.states}. Events are validated via schema parsers and\n * run through interceptors before being submitted. Resulting state is merged\n * back into signals.\n */\nclass PersonalizationStateful extends PersonalizationBase implements ConsentGuard {\n /** In‑memory queue for offline events keyed by profile. */\n private readonly offlineQueue = new Set<PersonalizationEvent>()\n\n /** Exposed observable state references. */\n readonly states: PersonalizationStates = {\n eventStream: toObservable(eventSignal),\n flags: toObservable(flagsSignal),\n profile: toObservable(profileSignal),\n personalizations: toObservable(personalizationsSignal),\n }\n\n /**\n * Function that provides an anonymous ID when available.\n *\n * @internal\n */\n getAnonymousId: () => string | undefined\n\n /**\n * Create a new stateful personalization instance.\n *\n * @param options - Options to configure the personalization product for stateful environments.\n */\n constructor(options: PersonalizationStatefulOptions) {\n const { api, builder, config, interceptors } = options\n\n super({ api, builder, config, interceptors })\n\n const { defaults, getAnonymousId } = config ?? {}\n\n if (defaults) {\n const {\n changes: defaultChanges,\n personalizations: defaultPersonalizations,\n profile: defaultProfile,\n } = defaults\n\n batch(() => {\n changesSignal.value = defaultChanges\n personalizationsSignal.value = defaultPersonalizations\n profileSignal.value = defaultProfile\n })\n }\n\n if (defaults?.consent !== undefined) {\n const { consent: defaultConsent } = defaults\n consentSignal.value = defaultConsent\n }\n\n this.getAnonymousId = getAnonymousId ?? (() => undefined)\n\n // Log signal changes for observability\n effect(() => {\n logger.debug(\n `Profile ${profileSignal.value && `with ID ${profileSignal.value.id}`} has been ${profileSignal.value ? 'set' : 'cleared'}`,\n )\n })\n\n effect(() => {\n logger.debug(\n `Variants have been ${personalizationsSignal.value?.length ? 'populated' : 'cleared'}`,\n )\n })\n\n effect(() => {\n logger.info(\n `Personalization ${consentSignal.value ? 'will' : 'will not'} take effect due to consent (${consentSignal.value})`,\n )\n })\n\n effect(() => {\n if (onlineSignal.value) void this.flush()\n })\n }\n\n /**\n * Reset stateful signals managed by this product.\n *\n * @remarks\n * Clears `changes`, `profile`, and selected `personalizations`.\n */\n reset(): void {\n batch(() => {\n changesSignal.value = undefined\n eventSignal.value = undefined\n profileSignal.value = undefined\n personalizationsSignal.value = undefined\n })\n }\n\n /**\n * Get the specified Custom Flag's value (derived from the signal).\n * @param name - The name or key of the Custom Flag.\n * @returns The current value of the Custom Flag if found.\n * */\n getCustomFlag(name: string, changes: ChangeArray | undefined = changesSignal.value): Json {\n return super.getCustomFlag(name, changes)\n }\n\n /**\n * Resolve a Contentful entry to a personalized variant using the current\n * or provided selections.\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam M - Chain modifiers.\n * @typeParam L - Locale code.\n * @param entry - The entry to personalize.\n * @param personalizations - Optional selections; defaults to the current signal value.\n * @returns The resolved entry data.\n */\n personalizeEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(\n entry: Entry<S, M, L>,\n personalizations: SelectedPersonalizationArray | undefined = personalizationsSignal.value,\n ): ResolvedData<S, M, L> {\n return super.personalizeEntry<S, M, L>(entry, personalizations)\n }\n\n /**\n * Resolve a merge tag to a value based on the current (or provided) profile.\n *\n * @param embeddedEntryNodeTarget - The merge‑tag entry node to resolve.\n * @param profile - Optional profile; defaults to the current signal value.\n * @returns The resolved value (type depends on the tag).\n * @remarks\n * Merge tags are references to profile data that can be substituted into content.\n */\n getMergeTagValue(\n embeddedEntryNodeTarget: MergeTagEntry,\n profile: Profile | undefined = profileSignal.value,\n ): unknown {\n return super.getMergeTagValue(embeddedEntryNodeTarget, profile)\n }\n\n /**\n * Determine whether the named operation is permitted based on consent and\n * allowed event type configuration.\n *\n * @param name - Method name; `trackComponentView` is normalized to\n * `'component'` for allow‑list checks.\n * @returns `true` if the operation is permitted; otherwise `false`.\n */\n hasConsent(name: string): boolean {\n return (\n !!consentSignal.value ||\n (this.allowedEventTypes ?? []).includes(\n name === 'trackComponentView' || name === 'trackFlagView' ? 'component' : name,\n )\n )\n }\n\n /**\n * Hook invoked when an operation is blocked due to missing consent.\n *\n * @param name - The blocked operation name.\n * @param payload - The original arguments supplied to the operation.\n */\n onBlockedByConsent(name: string, payload: unknown[]): void {\n logger.warn(\n `Event \"${name}\" was blocked due to lack of consent; payload: ${JSON.stringify(payload)}`,\n )\n }\n\n /**\n * Guard used to suppress duplicate component view events for the same\n * component based on a duplication key and the component identifier.\n *\n * @param _name - Operation name (unused).\n * @param payload - Tuple `[builderArgs, duplicationScope]`.\n * @returns `true` if the event is NOT a duplicate and should proceed.\n */\n isNotDuplicated(_name: string, payload: [ComponentViewBuilderArgs, string]): boolean {\n const [{ componentId: value }, duplicationScope] = payload\n\n const isDuplicated = this.duplicationDetector.isPresent(duplicationScope, value)\n\n if (!isDuplicated) this.duplicationDetector.addValue(duplicationScope, value)\n\n return !isDuplicated\n }\n\n /**\n * Hook invoked when an operation is blocked by the duplication guard.\n *\n * @param _name - The blocked operation name (unused).\n * @param payload - The original arguments supplied to the operation.\n */\n onBlockedByDuplication(_name: string, payload: unknown[]): void {\n logger.debug(\n `Duplicate \"component view\" event detected, skipping; payload: ${JSON.stringify(payload)}`,\n )\n }\n\n /**\n * Identify the current profile/visitor to associate traits with a profile\n * and update optimization state.\n *\n * @param payload - Identify builder payload.\n * @returns The resulting {@link OptimizationData} for the identified user.\n */\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async identify(payload: IdentifyBuilderArgs): Promise<OptimizationData | undefined> {\n logger.info('Sending \"identify\" event')\n\n const event = this.builder.buildIdentify(payload)\n\n return await this.sendOrEnqueueEvent(event)\n }\n\n /**\n * Record a page view and update optimization state.\n *\n * @param payload - Page view builder payload.\n * @returns The evaluated {@link OptimizationData} for this page view.\n */\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async page(payload: PageViewBuilderArgs): Promise<OptimizationData | undefined> {\n logger.info('Sending \"page\" event')\n\n const event = this.builder.buildPageView(payload)\n\n return await this.sendOrEnqueueEvent(event)\n }\n\n /**\n * Record a screen view and update optimization state.\n *\n * @param payload - Screen view builder payload.\n * @returns The evaluated {@link OptimizationData} for this screen view.\n */\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async screen(payload: ScreenViewBuilderArgs): Promise<OptimizationData | undefined> {\n logger.info(`Sending \"screen\" event for \"${payload.name}\"`)\n\n const event = this.builder.buildScreenView(payload)\n\n return await this.sendOrEnqueueEvent(event)\n }\n\n /**\n * Record a custom track event and update optimization state.\n *\n * @param payload - Track builder payload.\n * @returns The evaluated {@link OptimizationData} for this event.\n */\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async track(payload: TrackBuilderArgs): Promise<OptimizationData | undefined> {\n logger.info(`Sending \"track\" event \"${payload.event}\"`)\n\n const event = this.builder.buildTrack(payload)\n\n return await this.sendOrEnqueueEvent(event)\n }\n\n @guardedBy('isNotDuplicated', { onBlocked: 'onBlockedByDuplication' })\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n /**\n * Record a \"sticky\" component view and update optimization state.\n *\n * @param payload - Component view builder payload.\n * @param _duplicationScope - Optional duplication scope key used to suppress duplicates.\n * @returns The evaluated {@link OptimizationData} for this component view.\n */\n async trackComponentView(\n payload: ComponentViewBuilderArgs,\n _duplicationScope = '',\n ): Promise<OptimizationData | undefined> {\n logger.info(`Sending \"track personalization\" event for ${payload.componentId}`)\n\n const event = this.builder.buildComponentView(payload)\n\n return await this.sendOrEnqueueEvent(event)\n }\n\n /**\n * Intercept, validate, and place an event into the offline eventd queue; then\n * trigger a size‑based flush if necessary.\n *\n * @param event - The event to enqueue.\n */\n private async sendOrEnqueueEvent(\n event: PersonalizationEvent,\n ): Promise<OptimizationData | undefined> {\n const intercepted = await this.interceptors.event.run(event)\n\n const validEvent = PersonalizationEvent.parse(intercepted)\n\n eventSignal.value = validEvent\n\n if (onlineSignal.value) return await this.upsertProfile([validEvent])\n\n logger.debug(`Queueing ${validEvent.type} event`, validEvent)\n\n this.offlineQueue.add(validEvent)\n\n return undefined\n }\n\n /**\n * Flush the offline queue\n */\n async flush(): Promise<void> {\n if (this.offlineQueue.size === 0) return\n\n logger.debug('Flushing offline event queue')\n\n await this.upsertProfile(Array.from(this.offlineQueue))\n\n this.offlineQueue.clear()\n }\n\n /**\n * Submit events to the Experience API, updating output signals with the\n * returned state.\n *\n * @param events - The events to submit.\n * @returns The {@link OptimizationData} returned by the service.\n * @internal\n * @privateRemarks\n * If a `getAnonymousId` function has been provided, the returned value will\n * take precedence over the `id` property of the current {@link Profile}\n * signal value\n */\n private async upsertProfile(events: PersonalizationEventArray): Promise<OptimizationData> {\n const anonymousId = this.getAnonymousId()\n if (anonymousId) logger.debug(`Anonymous ID found: ${anonymousId}`)\n\n const data = await this.api.experience.upsertProfile({\n profileId: anonymousId ?? profileSignal.value?.id,\n events,\n })\n\n await this.updateOutputSignals(data)\n\n return data\n }\n\n /**\n * Apply returned optimization state to local signals after interceptor processing.\n *\n * @param data - Optimization state returned by the service.\n * @internal\n */\n private async updateOutputSignals(data: OptimizationData): Promise<void> {\n const intercepted = await this.interceptors.state.run(data)\n\n const { changes, personalizations, profile } = 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(personalizationsSignal.value, personalizations))\n personalizationsSignal.value = personalizations\n })\n }\n}\n\nexport default PersonalizationStateful\n","import {\n type ComponentViewBuilderArgs,\n ComponentViewEvent,\n type IdentifyBuilderArgs,\n IdentifyEvent,\n type OptimizationData,\n type PageViewBuilderArgs,\n PageViewEvent,\n type PartialProfile,\n type ExperienceEvent as PersonalizationEvent,\n type ScreenViewBuilderArgs,\n ScreenViewEvent,\n type TrackBuilderArgs,\n TrackEvent,\n} from '@contentful/optimization-api-client'\nimport { createScopedLogger } from 'logger'\nimport PersonalizationBase from './PersonalizationBase'\n\nconst logger = createScopedLogger('Personalization')\n\n/**\n * Stateless personalization implementation that immediately validates and sends\n * a single event to the Experience API, upserting the profile as needed.\n *\n * @public\n * @remarks\n * Each public method constructs a strongly-typed event via the shared builder,\n * runs it through event interceptors, and performs a profile upsert using the\n * Experience API. If an anonymous ID is available from the builder, it will be\n * preferred as the `profileId` unless an explicit profile is provided.\n */\nclass PersonalizationStateless extends PersonalizationBase {\n /**\n * Identify the current profile/visitor to associate traits with a profile.\n *\n * @param payload - Identify builder arguments with an optional partial\n * profile to attach to the upsert request.\n * @returns The resulting {@link OptimizationData} for the identified user.\n */\n async identify(\n payload: IdentifyBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData> {\n logger.info('Sending \"identify\" event')\n\n const { profile, ...builderArgs } = payload\n\n const event = IdentifyEvent.parse(this.builder.buildIdentify(builderArgs))\n\n return await this.upsertProfile(event, profile)\n }\n\n /**\n * Record a page view.\n *\n * @param payload - Page view builder arguments with an optional partial profile.\n * @returns The evaluated {@link OptimizationData} for this page view.\n */\n async page(\n payload: PageViewBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData> {\n logger.info('Sending \"page\" event')\n\n const { profile, ...builderArgs } = payload\n\n const event = PageViewEvent.parse(this.builder.buildPageView(builderArgs))\n\n return await this.upsertProfile(event, profile)\n }\n\n /**\n * Record a screen view.\n *\n * @param payload - Screen view builder arguments with an optional partial profile.\n * @returns The evaluated {@link OptimizationData} for this screen view.\n */\n async screen(\n payload: ScreenViewBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData> {\n logger.info(`Sending \"screen\" event for \"${payload.name}\"`)\n\n const { profile, ...builderArgs } = payload\n\n const event = ScreenViewEvent.parse(this.builder.buildScreenView(builderArgs))\n\n return await this.upsertProfile(event, profile)\n }\n\n /**\n * Record a custom track event.\n *\n * @param payload - Track builder arguments with an optional partial profile.\n * @returns The evaluated {@link OptimizationData} for this event.\n */\n async track(payload: TrackBuilderArgs & { profile?: PartialProfile }): Promise<OptimizationData> {\n logger.info(`Sending \"track\" event \"${payload.event}\"`)\n\n const { profile, ...builderArgs } = payload\n\n const event = TrackEvent.parse(this.builder.buildTrack(builderArgs))\n\n return await this.upsertProfile(event, profile)\n }\n\n /**\n * Record a \"sticky\" component view.\n *\n * @param payload - Component view builder arguments with an optional partial profile.\n * @returns The evaluated {@link OptimizationData} for this component view.\n */\n async trackComponentView(\n payload: ComponentViewBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData> {\n logger.info('Sending \"track personalization\" event')\n\n const { profile, ...builderArgs } = payload\n\n const event = ComponentViewEvent.parse(this.builder.buildComponentView(builderArgs))\n\n return await this.upsertProfile(event, profile)\n }\n\n /**\n * Intercept, validate, and upsert the profile with a single personalization\n * event.\n *\n * @param event - The {@link PersonalizationEvent} to submit.\n * @param profile - Optional partial profile. If omitted, the anonymous ID from\n * the builder (when present) is used as the `profileId`.\n * @returns The {@link OptimizationData} returned by the Experience API.\n * @internal\n */\n private async upsertProfile(\n event: PersonalizationEvent,\n profile?: PartialProfile,\n ): Promise<OptimizationData> {\n const intercepted = await this.interceptors.event.run(event)\n\n const data = await this.api.experience.upsertProfile({\n profileId: profile?.id,\n events: [intercepted],\n })\n\n return data\n }\n}\n\nexport default PersonalizationStateless\n","import type { ChangeArray, Flags } from '@contentful/optimization-api-client'\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 { MergeTagEntry, Profile } from '@contentful/optimization-api-client'\nimport { get } from 'es-toolkit/compat'\nimport { createScopedLogger } from 'logger'\n\nconst logger = createScopedLogger('Personalization')\n\n/** Base string for log messages when merge-tag resolution fails. */\nconst RESOLUTION_WARNING_BASE = 'Could not resolve Merge Tag value:'\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 * Type guard to ensure the input is a {@link MergeTagEntry}.\n *\n * @param embeddedEntryNodeTarget - Unknown value to validate.\n * @returns `true` if the input is a valid merge-tag entry.\n * @example\n * ```ts\n * if (MergeTagValueResolver.isMergeTagEntry(node)) {\n * // safe to read fields\n * }\n * ```\n */\n isMergeTagEntry(embeddedEntryNodeTarget: unknown): embeddedEntryNodeTarget is MergeTagEntry {\n return MergeTagEntry.safeParse(embeddedEntryNodeTarget).success\n },\n\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 * @example\n * ```ts\n * const value = MergeTagValueResolver.getValueFromProfile('user_email', profile)\n * if (value) sendEmailTo(value)\n * ```\n * @remarks\n * Only string/number/boolean primitives are returned; objects/arrays are ignored.\n */\n getValueFromProfile(id: string, profile?: Profile): string | undefined {\n const selectors = MergeTagValueResolver.normalizeSelectors(id)\n const matchingSelector = selectors.find((selector) => get(profile, selector))\n\n if (!matchingSelector) return undefined\n\n const value: unknown = get(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 (!MergeTagValueResolver.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 isPersonalizationEntry,\n isPersonalizedEntry,\n type PersonalizationEntry,\n type PersonalizedEntry,\n type SelectedPersonalization,\n type SelectedPersonalizationArray,\n} from '@contentful/optimization-api-client'\nimport type { ChainModifiers, Entry, EntrySkeletonType, LocaleCode } from 'contentful'\nimport { createScopedLogger } from 'logger'\n\nconst logger = createScopedLogger('Personalization')\n\n/**\n * Result returned by {@link PersonalizedEntryResolver.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 personalization metadata, if a non‑baseline variant was chosen. */\n personalization?: SelectedPersonalization\n}\n\n/** Base string for resolver warning messages. */\nconst RESOLUTION_WARNING_BASE = 'Could not resolve personalized entry variant:'\n\n/**\n * Resolve a personalized Contentful entry to the correct variant for the current\n * selections.\n *\n * @public\n * @remarks\n * Given a baseline {@link PersonalizedEntry} and a set of selected personalizations\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 SelectedPersonalization} is treated as\n * 1‑based (index 1 = first variant). A value of `0` indicates baseline.\n */\nconst PersonalizedEntryResolver = {\n /**\n * Find the personalization entry corresponding to one of the selected experiences.\n *\n * @param params - Object containing the baseline personalized entry and the selections.\n * @param skipValidation - When `true`, skip type/shape validation for perf.\n * @returns The matching {@link PersonalizationEntry}, or `undefined` if not found/invalid.\n * @example\n * ```ts\n * const personalizationEntry = PersonalizedEntryResolver.getPersonalizationEntry({\n * personalizedEntry: entry,\n * selectedPersonalizations\n * })\n * ```\n * @remarks\n * A personalization entry is a personalization configuration object supplied in a\n * `PersonalizedEntry.nt_experiences` array. A personalized entry may relate to\n * multiple personalizations.\n */\n getPersonalizationEntry(\n {\n personalizedEntry,\n selectedPersonalizations,\n }: {\n personalizedEntry: PersonalizedEntry\n selectedPersonalizations: SelectedPersonalizationArray\n },\n skipValidation = false,\n ): PersonalizationEntry | undefined {\n if (\n !skipValidation &&\n (!selectedPersonalizations.length || !isPersonalizedEntry(personalizedEntry))\n )\n return\n\n const personalizationEntry = personalizedEntry.fields.nt_experiences\n .filter((maybePersonalization) => isPersonalizationEntry(maybePersonalization))\n .find((personalizationEntry) =>\n selectedPersonalizations.some(\n ({ experienceId }) => experienceId === personalizationEntry.fields.nt_experience_id,\n ),\n )\n\n return personalizationEntry\n },\n\n /**\n * Look up the selection metadata for a specific personalization entry.\n *\n * @param params - Object with the target personalization entry and selections.\n * @param skipValidation - When `true`, skip type checks.\n * @returns The matching {@link SelectedPersonalization}, if present.\n * @example\n * ```ts\n * const selectedPersonalization = PersonalizedEntryResolver.getSelectedPersonalization({\n * personalizationEntry,\n * selectedPersonalizations\n * })\n * ```\n * @remarks\n * Selected personalizations are supplied by the Experience API in the\n * `experiences` response data property.\n */\n getSelectedPersonalization(\n {\n personalizationEntry,\n selectedPersonalizations,\n }: {\n personalizationEntry: PersonalizationEntry\n selectedPersonalizations: SelectedPersonalizationArray\n },\n skipValidation = false,\n ): SelectedPersonalization | undefined {\n if (\n !skipValidation &&\n (!selectedPersonalizations.length || !isPersonalizationEntry(personalizationEntry))\n )\n return\n\n const selectedPersonalization = selectedPersonalizations.find(\n ({ experienceId }) => experienceId === personalizationEntry.fields.nt_experience_id,\n )\n\n return selectedPersonalization\n },\n\n /**\n * Get the replacement variant config for the given selection index.\n *\n * @param params - Baseline entry, personalization 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 * @example\n * ```ts\n * const selectedVariant = PersonalizedEntryResolver.getSelectedVariant({\n * personalizedEntry: entry,\n * personalizationEntry,\n * selectedVariantIndex: 2 // second variant (1‑based)\n * })\n * ```\n * @remarks\n * Entry replacement variants are variant configurations specified in a\n * personalization configuration component's `variants` array supplied by the\n * personalized entry via its `nt_config` field.\n */\n getSelectedVariant(\n {\n personalizedEntry,\n personalizationEntry,\n selectedVariantIndex,\n }: {\n personalizedEntry: PersonalizedEntry\n personalizationEntry: PersonalizationEntry\n selectedVariantIndex: number\n },\n skipValidation = false,\n ): EntryReplacementVariant | undefined {\n if (\n !skipValidation &&\n (!isPersonalizedEntry(personalizedEntry) || !isPersonalizationEntry(personalizationEntry))\n )\n return\n\n const relevantVariants = personalizationEntry.fields.nt_config?.components\n ?.filter(\n (component): component is EntryReplacementComponent =>\n isEntryReplacementComponent(component) && !component.baseline.hidden,\n )\n .find((component) => component.baseline.id === personalizedEntry.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 - Personalization entry and selected variant.\n * @param skipValidation - When `true`, skip type checks.\n * @returns The resolved entry typed as {@link Entry} or `undefined`.\n * @example\n * ```ts\n * const selectedVariantEntry = PersonalizedEntryResolver.getSelectedVariantEntry<{ fields: unknown }>({\n * personalizationEntry,\n * selectedVariant\n * })\n * ```\n * @remarks\n * A personalized entry will resolve either to the baseline (the entry\n * supplied as `personalizedEntry`) or the selected variant.\n */\n getSelectedVariantEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(\n {\n personalizationEntry,\n selectedVariant,\n }: {\n personalizationEntry: PersonalizationEntry\n selectedVariant: EntryReplacementVariant\n },\n skipValidation = false,\n ): Entry<S, M, L> | undefined {\n if (\n !skipValidation &&\n (!isPersonalizationEntry(personalizationEntry) || !isEntryReplacementVariant(selectedVariant))\n )\n return\n\n const selectedVariantEntry = personalizationEntry.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 /**\n * Resolve the selected entry (baseline or variant) for a personalized entry\n * and optional selected personalizations, returning both the entry and the\n * personalization metadata.\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam M - Chain modifiers.\n * @typeParam L - Locale code.\n * @param entry - The baseline personalized entry.\n * @param selectedPersonalizations - 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: personalizedEntry, personalization } = PersonalizedEntryResolver.resolve(entry, selections)\n * if (personalization) console.log('Variant index', personalization.variantIndex)\n * ```\n */\n resolve<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(\n entry: Entry<S, M, L>,\n selectedPersonalizations?: SelectedPersonalizationArray,\n ): ResolvedData<S, M, L> {\n logger.debug(`Resolving personalized entry for baseline entry ${entry.sys.id}`)\n\n if (!selectedPersonalizations?.length) {\n logger.warn(\n `${RESOLUTION_WARNING_BASE} no selectedPersonalizations exist for the current profile`,\n )\n return { entry }\n }\n\n if (!isPersonalizedEntry(entry)) {\n logger.warn(`${RESOLUTION_WARNING_BASE} entry ${entry.sys.id} is not personalized`)\n return { entry }\n }\n\n const personalizationEntry = PersonalizedEntryResolver.getPersonalizationEntry(\n {\n personalizedEntry: entry,\n selectedPersonalizations,\n },\n true,\n )\n\n if (!personalizationEntry) {\n logger.warn(\n `${RESOLUTION_WARNING_BASE} could not find a personalization entry for ${entry.sys.id}`,\n )\n return { entry }\n }\n\n const selectedPersonalization = PersonalizedEntryResolver.getSelectedPersonalization(\n {\n personalizationEntry,\n selectedPersonalizations,\n },\n true,\n )\n\n const selectedVariantIndex = selectedPersonalization?.variantIndex ?? 0\n\n if (selectedVariantIndex === 0) {\n logger.debug(`Resolved personalization entry for entry ${entry.sys.id} is baseline`)\n\n return { entry }\n }\n\n const selectedVariant = PersonalizedEntryResolver.getSelectedVariant(\n {\n personalizedEntry: entry,\n personalizationEntry,\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 = PersonalizedEntryResolver.getSelectedVariantEntry<S, M, L>(\n {\n personalizationEntry,\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, personalization: selectedPersonalization }\n },\n}\n\nexport default PersonalizedEntryResolver\n","import type {\n InsightsEvent as AnalyticsEvent,\n ChangeArray,\n Flags,\n ExperienceEvent as PersonalizationEvent,\n Profile,\n SelectedPersonalizationArray,\n} from '@contentful/optimization-api-client'\nimport { batch, computed, effect, signal, type Signal } from '@preact/signals-core'\nimport { FlagsResolver } from './personalization/resolvers'\n\nexport const changes: Signal<ChangeArray | undefined> = signal<ChangeArray | undefined>()\n\nexport const consent = signal<boolean | undefined>()\n\nexport const event: Signal<AnalyticsEvent | PersonalizationEvent | undefined> = signal<\n AnalyticsEvent | PersonalizationEvent | undefined\n>()\n\nexport const flags = computed<Flags | undefined>(() => FlagsResolver.resolve(changes.value ?? []))\n\nexport const online = signal<boolean | undefined>(true)\n\nexport const personalizations = signal<SelectedPersonalizationArray | undefined>()\n\nexport const profile: Signal<Profile | undefined> = signal<Profile | undefined>()\n\nexport interface Signals {\n changes: typeof changes\n consent: typeof consent\n event: typeof event\n flags: typeof flags\n online: typeof online\n personalizations: typeof personalizations\n profile: typeof profile\n}\n\nexport interface Subscription {\n unsubscribe: () => void\n}\n\nexport interface Observable<T> {\n subscribe: (next: (v: T) => void) => Subscription\n}\n\nexport function toObservable<T>(s: { value: T }): Observable<T> {\n return {\n subscribe(next) {\n const dispose = effect(() => {\n next(s.value)\n })\n\n return { unsubscribe: dispose }\n },\n }\n}\n\nexport const signals: Signals = {\n changes,\n consent,\n event,\n flags,\n online,\n personalizations,\n profile,\n}\n\nexport { batch, effect, type Signal }\n","import { diary, enable, type Diary, type LogEvent } from 'diary'\n\nimport type LogSink from './LogSink'\n\nexport class Logger {\n readonly name = '@contentful/optimization'\n\n private readonly PREFIX_PARTS = ['Ctfl', 'O10n']\n private readonly DELIMITER = ':'\n private readonly diary: Diary\n private sinks: LogSink[] = []\n\n constructor() {\n this.diary = diary(this.name, this.onLogEvent.bind(this))\n enable(this.name)\n }\n\n private assembleLocationPrefix(logLocation: string): string {\n return `[${[...this.PREFIX_PARTS, logLocation].join(this.DELIMITER)}]`\n }\n\n public addSink(sink: LogSink): void {\n this.sinks = [...this.sinks.filter((existingSink) => existingSink.name !== sink.name), sink]\n }\n\n public removeSink(name: string): void {\n this.sinks = this.sinks.filter((sink) => sink.name !== name)\n }\n\n public removeSinks(): void {\n this.sinks = []\n }\n\n public debug(logLocation: string, message: string, ...args: unknown[]): void {\n this.diary.debug(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args)\n }\n\n public info(logLocation: string, message: string, ...args: unknown[]): void {\n this.diary.info(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args)\n }\n\n public log(logLocation: string, message: string, ...args: unknown[]): void {\n this.diary.log(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args)\n }\n\n public warn(logLocation: string, message: string, ...args: unknown[]): void {\n this.diary.warn(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args)\n }\n\n public error(logLocation: string, message: string | Error, ...args: unknown[]): void {\n this.diary.error(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args)\n }\n\n public fatal(logLocation: string, message: string | Error, ...args: unknown[]): void {\n this.diary.fatal(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args)\n }\n\n private onLogEvent(event: LogEvent): void {\n this.sinks.forEach((sink) => {\n sink.ingest(event)\n })\n }\n}\n\nexport const logger = new Logger()\n\nexport interface ScopedLogger {\n debug: (message: string, ...args: unknown[]) => void\n info: (message: string, ...args: unknown[]) => void\n log: (message: string, ...args: unknown[]) => void\n warn: (message: string, ...args: unknown[]) => void\n error: (message: string | Error, ...args: unknown[]) => void\n fatal: (message: string | Error, ...args: unknown[]) => void\n}\n\nexport function createScopedLogger(location: string): ScopedLogger {\n return {\n debug: (message: string, ...args: unknown[]) => {\n logger.debug(location, message, ...args)\n },\n info: (message: string, ...args: unknown[]) => {\n logger.info(location, message, ...args)\n },\n log: (message: string, ...args: unknown[]) => {\n logger.log(location, message, ...args)\n },\n warn: (message: string, ...args: unknown[]) => {\n logger.warn(location, message, ...args)\n },\n error: (message: string | Error, ...args: unknown[]) => {\n logger.error(location, message, ...args)\n },\n fatal: (message: string | Error, ...args: unknown[]) => {\n logger.fatal(location, message, ...args)\n },\n }\n}\n","import type { LogEvent } from 'diary'\n\nexport type { LogEvent }\n\nabstract class LogSink {\n abstract name: string\n\n abstract ingest(event: LogEvent): void\n}\n\nexport default LogSink\n","/* eslint-disable no-console -- using console */\nimport type { LogEvent, LogLevels } from 'diary'\nimport { compare } from 'diary/utils'\nimport LogSink from './LogSink'\n\nconst consoleMap = {\n debug: (...args: unknown[]) => {\n console.debug(...args)\n },\n info: (...args: unknown[]) => {\n console.info(...args)\n },\n log: (...args: unknown[]) => {\n console.log(...args)\n },\n warn: (...args: unknown[]) => {\n console.warn(...args)\n },\n error: (...args: unknown[]) => {\n console.error(...args)\n },\n fatal: (...args: unknown[]) => {\n console.error(...args)\n },\n}\n\nconst COMPARISON_EQUALITY = 0\n\nexport class ConsoleLogSink extends LogSink {\n public name = 'ConsoleLogSink'\n\n readonly verbosity: LogLevels\n\n constructor(verbosity?: LogLevels) {\n super()\n\n this.verbosity = verbosity ?? 'error'\n }\n\n ingest(event: LogEvent): void {\n if (compare(this.verbosity, event.level) > COMPARISON_EQUALITY) return\n\n consoleMap[event.level](...event.messages)\n }\n}\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};"],"names":["CoreBase","InterceptorManager","config","analytics","personalization","eventBuilder","logLevel","environment","clientId","logger","ConsoleLogSink","apiConfig","ApiClient","EventBuilder","OPTIMIZATION_CORE_SDK_VERSION","name","changes","entry","personalizations","embeddedEntryNodeTarget","profile","payload","duplicationScope","CoreStateful","allowedEventTypes","defaults","getAnonymousId","preventedComponentEvents","undefined","defaultConsent","consent","AnalyticsStateful","PersonalizationStateful","toObservable","event","flags","batch","accept","isOnline","online","previewPanel","signals","CoreStateless","AnalyticsStateless","PersonalizationStateless","defaultAllowedEvents","ProductBase","options","api","builder","interceptors","ValuePresence","AnalyticsBase","createScopedLogger","MAX_QUEUED_EVENTS","guardedBy","Map","eventSignal","profileSignal","defaultProfile","effect","id","onlineSignal","JSON","_name","value","isDuplicated","componentType","_duplicationScope","intercepted","validEvent","AnalyticsEvent","profileEventQueue","batches","events","sendSuccess","args","builderArgs","parsed","ComponentViewEvent","batchEvent","BatchInsightsEventArray","__OPTIMIZATION_VERSION__","ANONYMOUS_ID_COOKIE","isFunction","v","nameToString","String","isOnBlockedKey","isAsyncFunction","fn","Object","predicateName","opts","_value","context","decoratedName","originalUnknown","Reflect","original","originalIsAsync","resolvePredicate","self","cand","TypeError","computeAllowed","pred","ok","Boolean","runOnBlocked","onBlocked","handlerCandidate","blockedReturn","Promise","wrapped","interceptor","input","fns","Array","acc","defaultMap","map","scope","values","Set","PersonalizationBase","FlagsResolver","MergeTagValueResolver","PersonalizedEntryResolver","flagsSignal","personalizationsSignal","defaultChanges","defaultPersonalizations","changesSignal","consentSignal","PersonalizationEvent","anonymousId","data","isEqual","IdentifyEvent","PageViewEvent","ScreenViewEvent","TrackEvent","key","actualValue","RESOLUTION_WARNING_BASE","MergeTagEntry","_path","index","paths","dotPath","underScorePath","path","selectors","matchingSelector","selector","get","mergeTagEntry","fallback","Profile","personalizedEntry","selectedPersonalizations","skipValidation","isPersonalizedEntry","personalizationEntry","maybePersonalization","isPersonalizationEntry","experienceId","selectedPersonalization","selectedVariantIndex","relevantVariants","component","isEntryReplacementComponent","selectedVariant","isEntryReplacementVariant","selectedVariantEntry","variant","isEntry","signal","computed","s","next","dispose","Logger","diary","enable","logLocation","sink","existingSink","message","location","LogSink","consoleMap","console","COMPARISON_EQUALITY","verbosity","compare","__webpack_require__","module","getter","definition","obj","prop","Symbol"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/constants.ts","../src/symbols.ts","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../src/personalization/resolvers/FlagsResolver.ts","../src/personalization/resolvers/MergeTagValueResolver.ts","../src/personalization/resolvers/PersonalizedEntryResolver.ts","../src/signals.ts","../src/lib/decorators/guardedBy.ts","../src/lib/number/number.ts","../src/lib/queue/flushPolicy.ts","../src/lib/queue/QueueFlushRuntime.ts","../src/ProductBase.ts","../src/analytics/AnalyticsBase.ts","../src/analytics/AnalyticsStateful.ts","../src/analytics/AnalyticsStateless.ts","../src/lib/interceptor/InterceptorManager.ts","../src/CoreBase.ts","../src/lib/singleton/StatefulRuntimeSingleton.ts","../src/personalization/PersonalizationBase.ts","../src/personalization/PersonalizationStateful.ts","../src/personalization/PersonalizationStateless.ts","../src/CoreStateful.ts","../src/CoreStateless.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 personalization and analytics\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 personalizations.\n *\n * @internal\n */\nexport const PERSONALIZATIONS_CACHE_KEY = '__ctfl_opt_personalizations__'\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","__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 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('Personalization')\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 isPersonalizationEntry,\n isPersonalizedEntry,\n type PersonalizationEntry,\n type PersonalizedEntry,\n type SelectedPersonalization,\n type SelectedPersonalizationArray,\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('Personalization')\n\n/**\n * Result returned by {@link PersonalizedEntryResolver.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 personalization metadata, if a non‑baseline variant was chosen. */\n personalization?: SelectedPersonalization\n}\n\n/**\n * Base string for resolver warning messages.\n *\n * @internal\n */\nconst RESOLUTION_WARNING_BASE = 'Could not resolve personalized entry variant:'\n\n/**\n * Resolve a personalized Contentful entry to the correct variant for the current\n * selections.\n *\n * @public\n * @remarks\n * Given a baseline {@link PersonalizedEntry} and a set of selected personalizations\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 SelectedPersonalization} is treated as\n * 1‑based (index 1 = first variant). A value of `0` indicates baseline.\n */\nconst PersonalizedEntryResolver = {\n /**\n * Find the personalization entry corresponding to one of the selected experiences.\n *\n * @param params - Object containing the baseline personalized entry and the selections.\n * @param skipValidation - When `true`, skip type/shape validation for perf.\n * @returns The matching {@link PersonalizationEntry}, or `undefined` if not found/invalid.\n * @remarks\n * A personalization entry is a personalization configuration object supplied in a\n * `PersonalizedEntry.nt_experiences` array. A personalized entry may relate to\n * multiple personalizations.\n * @example\n * ```ts\n * const personalizationEntry = PersonalizedEntryResolver.getPersonalizationEntry({\n * personalizedEntry: entry,\n * selectedPersonalizations\n * })\n * ```\n */\n getPersonalizationEntry(\n {\n personalizedEntry,\n selectedPersonalizations,\n }: {\n personalizedEntry: PersonalizedEntry\n selectedPersonalizations: SelectedPersonalizationArray\n },\n skipValidation = false,\n ): PersonalizationEntry | undefined {\n if (\n !skipValidation &&\n (!selectedPersonalizations.length || !isPersonalizedEntry(personalizedEntry))\n )\n return\n\n const personalizationEntry = personalizedEntry.fields.nt_experiences\n .filter((maybePersonalization) => isPersonalizationEntry(maybePersonalization))\n .find((personalizationEntry) =>\n selectedPersonalizations.some(\n ({ experienceId }) => experienceId === personalizationEntry.fields.nt_experience_id,\n ),\n )\n\n return personalizationEntry\n },\n\n /**\n * Look up the selection metadata for a specific personalization entry.\n *\n * @param params - Object with the target personalization entry and selections.\n * @param skipValidation - When `true`, skip type checks.\n * @returns The matching {@link SelectedPersonalization}, if present.\n * @remarks\n * Selected personalizations are supplied by the Experience API in the\n * `experiences` response data property.\n * @example\n * ```ts\n * const selectedPersonalization = PersonalizedEntryResolver.getSelectedPersonalization({\n * personalizationEntry,\n * selectedPersonalizations\n * })\n * ```\n */\n getSelectedPersonalization(\n {\n personalizationEntry,\n selectedPersonalizations,\n }: {\n personalizationEntry: PersonalizationEntry\n selectedPersonalizations: SelectedPersonalizationArray\n },\n skipValidation = false,\n ): SelectedPersonalization | undefined {\n if (\n !skipValidation &&\n (!selectedPersonalizations.length || !isPersonalizationEntry(personalizationEntry))\n )\n return\n\n const selectedPersonalization = selectedPersonalizations.find(\n ({ experienceId }) => experienceId === personalizationEntry.fields.nt_experience_id,\n )\n\n return selectedPersonalization\n },\n\n /**\n * Get the replacement variant config for the given selection index.\n *\n * @param params - Baseline entry, personalization 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 * personalization configuration component's `variants` array supplied by the\n * personalized entry via its `nt_config` field.\n * @example\n * ```ts\n * const selectedVariant = PersonalizedEntryResolver.getSelectedVariant({\n * personalizedEntry: entry,\n * personalizationEntry,\n * selectedVariantIndex: 2 // second variant (1‑based)\n * })\n * ```\n */\n getSelectedVariant(\n {\n personalizedEntry,\n personalizationEntry,\n selectedVariantIndex,\n }: {\n personalizedEntry: PersonalizedEntry\n personalizationEntry: PersonalizationEntry\n selectedVariantIndex: number\n },\n skipValidation = false,\n ): EntryReplacementVariant | undefined {\n if (\n !skipValidation &&\n (!isPersonalizedEntry(personalizedEntry) || !isPersonalizationEntry(personalizationEntry))\n )\n return\n\n const relevantVariants = personalizationEntry.fields.nt_config?.components\n ?.filter(\n (component): component is EntryReplacementComponent =>\n isEntryReplacementComponent(component) && !component.baseline.hidden,\n )\n .find((component) => component.baseline.id === personalizedEntry.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 - Personalization 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 * A personalized entry will resolve either to the baseline (the entry\n * supplied as `personalizedEntry`) or the selected variant.\n * @example\n * ```ts\n * const selectedVariantEntry = PersonalizedEntryResolver.getSelectedVariantEntry<{ fields: unknown }>({\n * personalizationEntry,\n * selectedVariant\n * })\n * ```\n */\n getSelectedVariantEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(\n {\n personalizationEntry,\n selectedVariant,\n }: {\n personalizationEntry: PersonalizationEntry\n selectedVariant: EntryReplacementVariant\n },\n skipValidation = false,\n ): Entry<S, M, L> | undefined {\n if (\n !skipValidation &&\n (!isPersonalizationEntry(personalizationEntry) || !isEntryReplacementVariant(selectedVariant))\n )\n return\n\n const selectedVariantEntry = personalizationEntry.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 /**\n * Resolve the selected entry (baseline or variant) for a personalized entry\n * and optional selected personalizations, returning both the entry and the\n * personalization metadata.\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam M - Chain modifiers.\n * @typeParam L - Locale code.\n * @param entry - The baseline personalized entry.\n * @param selectedPersonalizations - 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: personalizedEntry, personalization } = PersonalizedEntryResolver.resolve(entry, selections)\n * if (personalization) console.log('Variant index', personalization.variantIndex)\n * ```\n */\n resolve<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(\n entry: Entry<S, M, L>,\n selectedPersonalizations?: SelectedPersonalizationArray,\n ): ResolvedData<S, M, L> {\n logger.debug(`Resolving personalized entry for baseline entry ${entry.sys.id}`)\n\n if (!selectedPersonalizations?.length) {\n logger.warn(\n `${RESOLUTION_WARNING_BASE} no selectedPersonalizations exist for the current profile`,\n )\n return { entry }\n }\n\n if (!isPersonalizedEntry(entry)) {\n logger.warn(`${RESOLUTION_WARNING_BASE} entry ${entry.sys.id} is not personalized`)\n return { entry }\n }\n\n const personalizationEntry = PersonalizedEntryResolver.getPersonalizationEntry(\n {\n personalizedEntry: entry,\n selectedPersonalizations,\n },\n true,\n )\n\n if (!personalizationEntry) {\n logger.warn(\n `${RESOLUTION_WARNING_BASE} could not find a personalization entry for ${entry.sys.id}`,\n )\n return { entry }\n }\n\n const selectedPersonalization = PersonalizedEntryResolver.getSelectedPersonalization(\n {\n personalizationEntry,\n selectedPersonalizations,\n },\n true,\n )\n\n const selectedVariantIndex = selectedPersonalization?.variantIndex ?? 0\n\n if (selectedVariantIndex === 0) {\n logger.debug(`Resolved personalization entry for entry ${entry.sys.id} is baseline`)\n\n return { entry }\n }\n\n const selectedVariant = PersonalizedEntryResolver.getSelectedVariant(\n {\n personalizedEntry: entry,\n personalizationEntry,\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 = PersonalizedEntryResolver.getSelectedVariantEntry<S, M, L>(\n {\n personalizationEntry,\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, personalization: selectedPersonalization }\n },\n}\n\nexport default PersonalizedEntryResolver\n","import type {\n InsightsEvent as AnalyticsEvent,\n ChangeArray,\n Flags,\n ExperienceEvent as PersonalizationEvent,\n Profile,\n SelectedPersonalizationArray,\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'\nimport { FlagsResolver } from './personalization/resolvers'\n\nexport const changes: Signal<ChangeArray | undefined> = signal<ChangeArray | undefined>()\n\nexport const blockedEvent: Signal<BlockedEvent | undefined> = signal<BlockedEvent | undefined>()\n\nexport const consent = signal<boolean | undefined>()\n\nexport const event: Signal<AnalyticsEvent | PersonalizationEvent | undefined> = signal<\n AnalyticsEvent | PersonalizationEvent | undefined\n>()\n\nexport const flags = computed<Flags | undefined>(() => FlagsResolver.resolve(changes.value ?? []))\n\nexport const online = signal<boolean | undefined>(true)\n\nexport const previewPanelAttached = signal<boolean>(false)\n\nexport const previewPanelOpen = signal<boolean>(false)\n\nexport const personalizations = signal<SelectedPersonalizationArray | undefined>()\n\nexport const profile: Signal<Profile | undefined> = signal<Profile | undefined>()\n\nexport interface Signals {\n blockedEvent: typeof blockedEvent\n changes: typeof changes\n consent: typeof consent\n event: typeof event\n flags: typeof flags\n online: typeof online\n previewPanelAttached: typeof previewPanelAttached\n previewPanelOpen: typeof previewPanelOpen\n personalizations: typeof personalizations\n profile: typeof profile\n}\n\nexport interface SignalFns {\n batch: typeof batch\n computed: typeof computed\n effect: typeof effect\n untracked: typeof untracked\n}\n\nexport interface Subscription {\n unsubscribe: () => void\n}\n\nexport interface Observable<T> {\n subscribe: (next: (v: T) => void) => Subscription\n}\n\nexport function toObservable<T>(s: { value: T }): Observable<T> {\n return {\n subscribe(next) {\n const dispose = effect(() => {\n next(s.value)\n })\n\n return { unsubscribe: dispose }\n },\n }\n}\n\nexport const signals: Signals = {\n blockedEvent,\n changes,\n consent,\n event,\n flags,\n online,\n previewPanelAttached,\n previewPanelOpen,\n personalizations,\n profile,\n}\n\nexport const signalFns: SignalFns = {\n batch,\n computed,\n effect,\n untracked,\n}\n\nexport { batch, effect, type Signal }\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 */\ntype 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 */\ntype 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 {@link GuardedByOptions | options} 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","/**\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 * 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 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 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 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 baseBackoffMs = toPositiveInt(policy?.baseBackoffMs, defaults.baseBackoffMs)\n const maxBackoffMs = Math.max(\n baseBackoffMs,\n toPositiveInt(policy?.maxBackoffMs, defaults.maxBackoffMs),\n )\n\n return {\n baseBackoffMs,\n maxBackoffMs,\n jitterRatio: toRatio(policy?.jitterRatio, defaults.jitterRatio),\n maxConsecutiveFailures: toPositiveInt(\n policy?.maxConsecutiveFailures,\n defaults.maxConsecutiveFailures,\n ),\n circuitOpenMs: toPositiveInt(policy?.circuitOpenMs, defaults.circuitOpenMs),\n onCircuitOpen: policy?.onCircuitOpen,\n onFlushFailure: policy?.onFlushFailure,\n onFlushRecovered: policy?.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","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 type { ApiClient, EventBuilder } from '@contentful/optimization-api-client'\nimport type {\n InsightsEventType as AnalyticsEventType,\n ExperienceEventType as PersonalizationEventType,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger } from '@contentful/optimization-api-client/logger'\nimport type { BlockedEvent, BlockedEventProduct, BlockedEventReason } from './BlockedEvent'\nimport type { LifecycleInterceptors } from './CoreBase'\nimport { blockedEvent } from './signals'\n\nconst logger = createScopedLogger('ProductBase')\n\n/**\n * Union of all event {@link AnalyticsEventType | type keys} that this package may emit.\n *\n * @public\n */\nexport type EventType = AnalyticsEventType | PersonalizationEventType\n\n/**\n * Default allow‑list of event types that can be emitted without explicit consent.\n *\n * @internal\n * @privateRemarks These defaults are only applied when a consumer does not provide\n * {@link ProductConfig.allowedEventTypes}.\n */\nconst defaultAllowedEvents: EventType[] = ['identify', 'page', 'screen']\n\n/**\n * Common configuration for all product implementations.\n *\n * @public\n */\nexport interface ProductConfig {\n /**\n * The set of event type strings that are allowed to be sent even if consent is\n * not granted.\n *\n * @defaultValue `['identify', 'page', 'screen']`\n * @remarks These types are compared against the `type` property of events.\n */\n allowedEventTypes?: EventType[]\n\n /**\n * Callback invoked whenever an event call is blocked by guards.\n *\n * @remarks\n * This callback is best-effort. Any exception thrown by the callback is\n * swallowed to keep event handling fault tolerant.\n */\n onEventBlocked?: (event: BlockedEvent) => void\n}\n\n/**\n * Options for configuring the common functionality of {@link ProductBase} descendents.\n *\n * @public\n */\nexport interface ProductBaseOptions {\n /** Optimization API client. */\n api: ApiClient\n /** Event builder for constructing events. */\n builder: EventBuilder\n /** Optional configuration for allow‑lists and guard callbacks. */\n config?: ProductConfig\n /** Lifecycle container for event and state interceptors. */\n interceptors: LifecycleInterceptors\n}\n\n/**\n * Shared base for all product implementations.\n *\n * @internal\n * @remarks\n * This abstract class is not exported as part of the public API surface.\n * Concrete implementations (e.g., analytics) should extend this class and\n * expose their own public methods.\n */\nabstract class ProductBase {\n /**\n * Allow‑list of event {@link AnalyticsEventType | type keys} permitted when consent is not present.\n */\n protected readonly allowedEventTypes?: string[]\n\n /** Event builder used to construct strongly‑typed events. */\n protected readonly builder: EventBuilder\n\n /** Optimization API client used to send events to the Experience and Insights APIs. */\n protected readonly api: ApiClient\n\n /** Interceptors that can mutate/augment outgoing events or optimization state. */\n readonly interceptors: LifecycleInterceptors\n\n /** Optional callback invoked when an event call is blocked. */\n protected readonly onEventBlocked?: ProductConfig['onEventBlocked']\n\n /**\n * Creates a new product base instance.\n *\n * @param options - Options for configuring the functionality common among products.\n */\n constructor(options: ProductBaseOptions) {\n const { api, builder, config, interceptors } = options\n this.allowedEventTypes = config?.allowedEventTypes ?? defaultAllowedEvents\n this.api = api\n this.builder = builder\n this.interceptors = interceptors\n this.onEventBlocked = config?.onEventBlocked\n }\n\n /**\n * Publish blocked event metadata to both callback and blocked event signal.\n *\n * @param reason - Reason the method call was blocked.\n * @param product - Product that blocked the method call.\n * @param method - Name of the blocked method.\n * @param args - Original blocked call arguments.\n */\n protected reportBlockedEvent(\n reason: BlockedEventReason,\n product: BlockedEventProduct,\n method: string,\n args: readonly unknown[],\n ): void {\n const event: BlockedEvent = { reason, product, method, args }\n\n try {\n this.onEventBlocked?.(event)\n } catch (error) {\n logger.warn(`onEventBlocked callback failed for method \"${method}\"`, error)\n }\n\n blockedEvent.value = event\n }\n}\n\nexport default ProductBase\n","import type {\n ComponentClickBuilderArgs,\n ComponentHoverBuilderArgs,\n ComponentViewBuilderArgs,\n} from '@contentful/optimization-api-client'\nimport ProductBase from '../ProductBase'\n\n/**\n * Base class for analytics implementations (internal).\n *\n * @internal\n * @remarks\n * Concrete analytics classes should implement the component/flag view tracking\n * methods below. This base is not part of the public API.\n */\nabstract class AnalyticsBase extends ProductBase {\n /**\n * Track a UI component view event.\n *\n * @param payload - Component view builder arguments.\n * @returns A promise that resolves when processing is complete (or `void`).\n */\n abstract trackComponentView(payload: ComponentViewBuilderArgs): Promise<void> | void\n\n /**\n * Track a UI component click event.\n *\n * @param payload - Component click builder arguments.\n * @returns A promise that resolves when processing is complete (or `void`).\n */\n abstract trackComponentClick(payload: ComponentClickBuilderArgs): Promise<void> | void\n\n /**\n * Track a UI component hover event.\n *\n * @param payload - Component hover builder arguments.\n * @returns A promise that resolves when processing is complete (or `void`).\n */\n abstract trackComponentHover(payload: ComponentHoverBuilderArgs): Promise<void> | void\n\n /**\n * Track a flag (feature) view event.\n *\n * @param payload - Flag view builder arguments.\n * @returns A promise that resolves when processing is complete (or `void`).\n */\n abstract trackFlagView(payload: ComponentViewBuilderArgs): Promise<void> | void\n}\n\nexport default AnalyticsBase\n","import type {\n ComponentClickBuilderArgs,\n ComponentHoverBuilderArgs,\n ComponentViewBuilderArgs,\n} from '@contentful/optimization-api-client'\nimport {\n InsightsEvent as AnalyticsEvent,\n parseWithFriendlyError,\n type BatchInsightsEventArray,\n type InsightsEventArray,\n type ExperienceEvent as PersonalizationEvent,\n type Profile,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger } from '@contentful/optimization-api-client/logger'\nimport type { BlockedEvent } from '../BlockedEvent'\nimport type { ConsentGuard } from '../Consent'\nimport { guardedBy } from '../lib/decorators'\nimport { QueueFlushRuntime, resolveQueueFlushPolicy, type QueueFlushPolicy } from '../lib/queue'\nimport type { ProductBaseOptions, ProductConfig } from '../ProductBase'\nimport {\n batch,\n blockedEvent as blockedEventSignal,\n consent,\n effect,\n event as eventSignal,\n online as onlineSignal,\n profile as profileSignal,\n toObservable,\n type Observable,\n} from '../signals'\nimport AnalyticsBase from './AnalyticsBase'\n\nconst logger = createScopedLogger('Analytics')\n\n/**\n * Default analytics state values applied at construction time.\n *\n * @public\n */\nexport interface AnalyticsProductConfigDefaults {\n /** Whether analytics collection is allowed by default. */\n consent?: boolean\n /** Default profile to associate with events. */\n profile?: Profile\n}\n\n/**\n * Configuration for the stateful analytics implementation.\n *\n * @public\n */\nexport interface AnalyticsProductConfig extends ProductConfig {\n /**\n * Default signal values applied on initialization.\n */\n defaults?: AnalyticsProductConfigDefaults\n\n /**\n * Policy that controls stateful queue flush retries, backoff, and circuit\n * behavior after repeated failures.\n */\n queuePolicy?: QueueFlushPolicy\n}\n\n/**\n * Observables exposed by the stateful analytics product.\n *\n * @public\n */\nexport interface AnalyticsStates {\n /** Observable stream of the latest blocked event payload (or `undefined`). */\n blockedEventStream: Observable<BlockedEvent | undefined>\n /** Observable stream of the latest {@link AnalyticsEvent} or {@link PersonalizationEvent} (or `undefined`). */\n eventStream: Observable<AnalyticsEvent | PersonalizationEvent | undefined>\n /** Observable stream of the active {@link Profile} (or `undefined`). */\n profile: Observable<Profile | undefined>\n}\n\n/**\n * Options for configuring {@link AnalyticsStateful} functionality.\n *\n * @public\n * @see {@link ProductBaseOptions}\n */\nexport type AnalyticsStatefulOptions = ProductBaseOptions & {\n /** Configuration specific to the Analytics product */\n config?: AnalyticsProductConfig\n}\n\n/**\n * Maximum number of queued events before an automatic flush is triggered.\n *\n * @internal\n */\nconst MAX_QUEUED_EVENTS = 25\nconst ANALYTICS_METHOD_EVENT_TYPE_MAP: Readonly<Record<string, string>> = {\n trackComponentView: 'component',\n trackFlagView: 'component',\n trackComponentClick: 'component_click',\n trackComponentHover: 'component_hover',\n}\n\ninterface QueuedProfileEvents {\n profile: Profile\n events: InsightsEventArray\n}\n\n/**\n * Analytics implementation that maintains local state (consent, profile) and\n * queues events until flushed or the queue reaches a maximum size.\n *\n * @remarks\n * Repeated flush failures are managed by the configured {@link QueueFlushPolicy}\n * using bounded backoff and a temporary circuit-open window.\n *\n * @public\n */\nclass AnalyticsStateful extends AnalyticsBase implements ConsentGuard {\n /** In-memory queue keyed by stable profile identifier. */\n private readonly queue = new Map<Profile['id'], QueuedProfileEvents>()\n /** Shared queue flush retry runtime state machine. */\n private readonly flushRuntime: QueueFlushRuntime\n\n /** Exposed observable state references. */\n readonly states: AnalyticsStates = {\n blockedEventStream: toObservable(blockedEventSignal),\n eventStream: toObservable(eventSignal),\n profile: toObservable(profileSignal),\n }\n\n /**\n * Create a new stateful analytics instance.\n *\n * @param options - Options to configure the analytics product for stateful environments.\n * @example\n * ```ts\n * const analytics = new AnalyticsStateful({ api, builder, config: { defaults: { consent: true } }, interceptors })\n * ```\n */\n constructor(options: AnalyticsStatefulOptions) {\n const { api, builder, config, interceptors } = options\n\n super({ api, builder, config, interceptors })\n\n this.applyDefaults(config?.defaults)\n\n this.flushRuntime = new QueueFlushRuntime({\n policy: resolveQueueFlushPolicy(config?.queuePolicy),\n onRetry: () => {\n void this.flush()\n },\n onCallbackError: (callbackName, error) => {\n logger.warn(`Analytics flush policy callback \"${callbackName}\" failed`, error)\n },\n })\n this.initializeEffects()\n }\n\n /**\n * Reset analytics‑related signals and the last emitted event.\n *\n * @example\n * ```ts\n * analytics.reset()\n * ```\n */\n reset(): void {\n this.flushRuntime.reset()\n\n batch(() => {\n blockedEventSignal.value = undefined\n eventSignal.value = undefined\n profileSignal.value = undefined\n })\n }\n\n /**\n * Determine whether the named operation is permitted based on consent and\n * allowed event type configuration.\n *\n * @param name - The method name; component view/flag methods are normalized\n * to `'component'`, component click methods are normalized to `'component_click'`,\n * and component hover methods are normalized to `'component_hover'` for\n * allow‑list checks.\n * @returns `true` if the operation is permitted; otherwise `false`.\n * @example\n * ```ts\n * if (analytics.hasConsent('track')) { ... }\n * ```\n */\n hasConsent(name: string): boolean {\n const mappedEventType = ANALYTICS_METHOD_EVENT_TYPE_MAP[name] ?? name\n\n return !!consent.value || (this.allowedEventTypes ?? []).includes(mappedEventType)\n }\n\n /**\n * Hook invoked when an operation is blocked due to missing consent.\n *\n * @param name - The blocked operation name.\n * @param payload - The original arguments supplied to the operation.\n * @example\n * ```ts\n * analytics.onBlockedByConsent('track', [payload])\n * ```\n */\n onBlockedByConsent(name: string, payload: readonly unknown[]): void {\n logger.warn(\n `Event \"${name}\" was blocked due to lack of consent; payload: ${JSON.stringify(payload)}`,\n )\n\n this.reportBlockedEvent('consent', 'analytics', name, payload)\n }\n\n /**\n * Queue a component view event for the active profile.\n *\n * @param payload - Component view builder arguments.\n * @returns A promise that resolves when the event has been queued.\n * @example\n * ```ts\n * await analytics.trackComponentView({ componentId: 'hero-banner' })\n * ```\n */\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async trackComponentView(payload: ComponentViewBuilderArgs): Promise<void> {\n logger.info(`Processing \"component view\" event for ${payload.componentId}`)\n\n await this.enqueueEvent(this.builder.buildComponentView(payload))\n }\n\n /**\n * Queue a component click event for the active profile.\n *\n * @param payload - Component click builder arguments.\n * @returns A promise that resolves when the event has been queued.\n * @example\n * ```ts\n * await analytics.trackComponentClick({ componentId: 'hero-banner' })\n * ```\n */\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async trackComponentClick(payload: ComponentClickBuilderArgs): Promise<void> {\n logger.info(`Processing \"component click\" event for ${payload.componentId}`)\n\n await this.enqueueEvent(this.builder.buildComponentClick(payload))\n }\n\n /**\n * Queue a component hover event for the active profile.\n *\n * @param payload - Component hover builder arguments.\n * @returns A promise that resolves when the event has been queued.\n * @example\n * ```ts\n * await analytics.trackComponentHover({ componentId: 'hero-banner' })\n * ```\n */\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async trackComponentHover(payload: ComponentHoverBuilderArgs): Promise<void> {\n logger.info(`Processing \"component hover\" event for ${payload.componentId}`)\n\n await this.enqueueEvent(this.builder.buildComponentHover(payload))\n }\n\n /**\n * Queue a flag view event for the active profile.\n *\n * @param payload - Flag view builder arguments.\n * @returns A promise that resolves when the event has been queued.\n * @example\n * ```ts\n * await analytics.trackFlagView({ componentId: 'feature-flag-123' })\n * ```\n */\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async trackFlagView(payload: ComponentViewBuilderArgs): Promise<void> {\n logger.debug(`Processing \"flag view\" event for ${payload.componentId}`)\n\n await this.enqueueEvent(this.builder.buildFlagView(payload))\n }\n\n /**\n * Intercept, validate, and place an event into the profile‑scoped queue; then\n * trigger a size‑based flush if necessary.\n *\n * @param event - The event to enqueue.\n */\n private async enqueueEvent(event: AnalyticsEvent): Promise<void> {\n const { value: profile } = profileSignal\n\n if (!profile) {\n logger.warn('Attempting to emit an event without an Optimization profile')\n\n return\n }\n\n const intercepted = await this.interceptors.event.run(event)\n\n const validEvent = parseWithFriendlyError(AnalyticsEvent, intercepted)\n\n logger.debug(`Queueing ${validEvent.type} event for profile ${profile.id}`, validEvent)\n\n const { id: profileId } = profile\n const queuedProfileEvents = this.queue.get(profileId)\n\n eventSignal.value = validEvent\n\n if (queuedProfileEvents) {\n // Keep the latest profile snapshot for this ID while appending events.\n queuedProfileEvents.profile = profile\n queuedProfileEvents.events.push(validEvent)\n } else {\n this.queue.set(profileId, { profile, events: [validEvent] })\n }\n\n await this.flushMaxEvents()\n }\n\n /**\n * Flush the queue automatically when the total number of queued events\n * reaches {@link MAX_QUEUED_EVENTS}.\n */\n private async flushMaxEvents(): Promise<void> {\n if (this.getQueuedEventCount() >= MAX_QUEUED_EVENTS) await this.flush()\n }\n\n /**\n * Send all queued events grouped by profile and clear the queue.\n *\n * @param options - Optional flush controls.\n * @param options.force - When `true`, bypass offline/backoff/circuit gates and attempt immediately.\n * @remarks Only under rare circumstances should there be more than one\n * profile in a stateful application.\n * @example\n * ```ts\n * await analytics.flush()\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 logger.debug('Flushing event queue')\n\n const batches = this.createBatches()\n\n if (!batches.length) {\n this.flushRuntime.clearScheduledRetry()\n return\n }\n\n this.flushRuntime.markFlushStarted()\n\n try {\n const sendSuccess = await this.trySendBatches(batches)\n\n if (sendSuccess) {\n this.queue.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 }\n }\n\n /**\n * Apply default stateful analytics values when provided.\n *\n * @param defaults - Optional defaults for analytics state.\n */\n private applyDefaults(defaults: AnalyticsProductConfigDefaults | undefined): void {\n if (defaults?.profile === undefined) return\n\n const { profile: defaultProfile } = defaults\n profileSignal.value = defaultProfile\n }\n\n /**\n * Initialize reactive effects for consent/profile logging and online flushes.\n */\n private initializeEffects(): void {\n effect(() => {\n const id = profileSignal.value?.id\n\n logger.info(\n `Analytics ${consent.value ? 'will' : 'will not'} be collected due to consent (${consent.value})`,\n )\n\n logger.debug(`Profile ${id && `with ID ${id}`} has been ${id ? 'set' : 'cleared'}`)\n })\n\n effect(() => {\n if (!onlineSignal.value) return\n\n this.flushRuntime.clearScheduledRetry()\n void this.flush({ force: true })\n })\n }\n\n /**\n * Build batch payloads grouped by profile from the in-memory queue.\n *\n * @returns Grouped batch payloads.\n */\n private createBatches(): BatchInsightsEventArray {\n const batches: BatchInsightsEventArray = []\n\n this.queue.forEach(({ profile, events }) => {\n batches.push({ profile, events })\n })\n\n return batches\n }\n\n /**\n * Attempt to send queued batches to the Insights API.\n *\n * @param batches - Batches to send.\n * @returns `true` when send succeeds; otherwise `false`.\n */\n private async trySendBatches(batches: BatchInsightsEventArray): Promise<boolean> {\n try {\n return await this.api.insights.sendBatchEvents(batches)\n } catch (error) {\n logger.warn('Analytics queue flush request threw an error', error)\n return false\n }\n }\n\n /**\n * Compute the total number of queued events across all profiles.\n *\n * @returns Total queued event count.\n */\n private getQueuedEventCount(): number {\n let queuedCount = 0\n\n this.queue.forEach(({ events }) => {\n queuedCount += events.length\n })\n\n return queuedCount\n }\n}\n\nexport default AnalyticsStateful\n","import type {\n ComponentClickBuilderArgs,\n ComponentHoverBuilderArgs,\n ComponentViewBuilderArgs,\n} from '@contentful/optimization-api-client'\nimport {\n InsightsEvent as AnalyticsEvent,\n BatchInsightsEventArray,\n parseWithFriendlyError,\n type PartialProfile,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger } from '@contentful/optimization-api-client/logger'\nimport AnalyticsBase from './AnalyticsBase'\n\nconst logger = createScopedLogger('Analytics')\n\n/**\n * Arguments for tracking a component/flag view in stateless mode.\n *\n * @public\n * @remarks\n * The `profile` is optional; when omitted, the APIs may infer identity via\n * other means.\n */\nexport type TrackComponentViewArgs = ComponentViewBuilderArgs & { profile?: PartialProfile }\nexport type TrackComponentClickArgs = ComponentClickBuilderArgs & { profile?: PartialProfile }\nexport type TrackComponentHoverArgs = ComponentHoverBuilderArgs & { profile?: PartialProfile }\n\n/**\n * Stateless analytics implementation that sends each event immediately in a\n * single‑event batch.\n *\n * @public\n */\nclass AnalyticsStateless extends AnalyticsBase {\n /**\n * Build, intercept, validate, and send a component view event.\n *\n * @param args - {@link TrackComponentViewArgs} used to build the event. Includes an\n * optional partial profile.\n * @returns A promise that resolves once the batch has been sent.\n * @example\n * ```ts\n * await analytics.trackComponentView({ componentId: 'hero-banner', profile: { id: 'user-1' } })\n * ```\n */\n async trackComponentView(args: TrackComponentViewArgs): Promise<void> {\n logger.info('Processing \"component view\" event')\n\n const { profile, ...builderArgs } = args\n\n const event = this.builder.buildComponentView(builderArgs)\n\n await this.sendBatchEvent(event, profile)\n }\n\n /**\n * Build, intercept, validate, and send a component click event.\n *\n * @param args - {@link TrackComponentClickArgs} used to build the event. Includes an\n * optional partial profile.\n * @returns A promise that resolves once the batch has been sent.\n * @example\n * ```ts\n * await analytics.trackComponentClick({ componentId: 'hero-banner', profile: { id: 'user-1' } })\n * ```\n */\n async trackComponentClick(args: TrackComponentClickArgs): Promise<void> {\n logger.info('Processing \"component click\" event')\n\n const { profile, ...builderArgs } = args\n\n const event = this.builder.buildComponentClick(builderArgs)\n\n await this.sendBatchEvent(event, profile)\n }\n\n /**\n * Build, intercept, validate, and send a component hover event.\n *\n * @param args - {@link TrackComponentHoverArgs} used to build the event. Includes an\n * optional partial profile.\n * @returns A promise that resolves once the batch has been sent.\n * @example\n * ```ts\n * await analytics.trackComponentHover({ componentId: 'hero-banner', profile: { id: 'user-1' } })\n * ```\n */\n async trackComponentHover(args: TrackComponentHoverArgs): Promise<void> {\n logger.info('Processing \"component hover\" event')\n\n const { profile, ...builderArgs } = args\n\n const event = this.builder.buildComponentHover(builderArgs)\n\n await this.sendBatchEvent(event, profile)\n }\n\n /**\n * Build, intercept, validate, and send a flag view event.\n *\n * @param args - {@link TrackComponentViewArgs} used to build the event. Includes an\n * optional partial profile.\n * @returns A promise that resolves once the batch has been sent.\n * @example\n * ```ts\n * await analytics.trackFlagView({ componentId: 'feature-flag-123' })\n * ```\n */\n async trackFlagView(args: TrackComponentViewArgs): Promise<void> {\n logger.debug('Processing \"flag view\" event')\n\n const { profile, ...builderArgs } = args\n\n const event = this.builder.buildFlagView(builderArgs)\n\n await this.sendBatchEvent(event, profile)\n }\n\n /**\n * Send a single {@link AnalyticsEvent} wrapped in a one‑item batch.\n *\n * @param event - The event to send.\n * @param profile - Optional partial profile to attach to the batch.\n * @returns A promise that resolves when the API call completes.\n * @internal\n */\n private async sendBatchEvent(event: AnalyticsEvent, profile?: PartialProfile): Promise<void> {\n const intercepted = await this.interceptors.event.run(event)\n\n const parsed = parseWithFriendlyError(AnalyticsEvent, intercepted)\n\n const batchEvent: BatchInsightsEventArray = parseWithFriendlyError(BatchInsightsEventArray, [\n {\n profile,\n events: [parsed],\n },\n ])\n\n await this.api.insights.sendBatchEvents(batchEvent)\n }\n}\n\nexport default AnalyticsStateless\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 */\ntype 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 readonly view to discourage mutation of intermediate values.\n // Each interceptor must return a T (or Promise<T>).\n acc = await fn(acc as Readonly<T>)\n }\n\n return acc\n }\n}\n","import {\n ApiClient,\n EventBuilder,\n type ApiClientConfig,\n type ComponentClickBuilderArgs,\n type ComponentHoverBuilderArgs,\n type ComponentViewBuilderArgs,\n type EventBuilderConfig,\n type ExperienceApiClientConfig,\n type GlobalApiConfigProperties,\n type IdentifyBuilderArgs,\n type InsightsApiClientConfig,\n type PageViewBuilderArgs,\n type ScreenViewBuilderArgs,\n type TrackBuilderArgs,\n} from '@contentful/optimization-api-client'\nimport type {\n InsightsEvent as AnalyticsEvent,\n ChangeArray,\n Flags,\n Json,\n MergeTagEntry,\n OptimizationData,\n PartialProfile,\n ExperienceEvent as PersonalizationEvent,\n Profile,\n SelectedPersonalizationArray,\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 type AnalyticsBase from './analytics/AnalyticsBase'\nimport { OPTIMIZATION_CORE_SDK_NAME, OPTIMIZATION_CORE_SDK_VERSION } from './constants'\nimport { InterceptorManager } from './lib/interceptor'\nimport type {\n FlagsResolver,\n MergeTagValueResolver,\n PersonalizationBase,\n PersonalizedEntryResolver,\n ResolvedData,\n ResolverMethods,\n} from './personalization'\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<AnalyticsEvent | PersonalizationEvent>\n /** Interceptors invoked before optimization state updates. */\n state: InterceptorManager<OptimizationData>\n}\n\n/**\n * Options for configuring the {@link CoreBase} runtime and underlying clients.\n *\n * @public\n */\nexport interface CoreConfig extends Pick<ApiClientConfig, GlobalApiConfigProperties> {\n /**\n * Configuration for the personalization (Experience) API client.\n */\n personalization?: Omit<ExperienceApiClientConfig, GlobalApiConfigProperties>\n\n /**\n * Configuration for the analytics (Insights) API client.\n */\n analytics?: Omit<InsightsApiClientConfig, GlobalApiConfigProperties>\n\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\n/**\n * Internal base that wires the API client, event builder, and logging.\n *\n * @internal\n */\nabstract class CoreBase implements ResolverMethods {\n /** Product implementation for analytics. */\n protected abstract _analytics: AnalyticsBase\n /** Product implementation for personalization. */\n protected abstract _personalization: PersonalizationBase\n\n /** Shared Optimization API client instance. */\n readonly api: ApiClient\n /** Shared event builder instance. */\n readonly eventBuilder: EventBuilder\n /** Resolved core configuration (minus any name metadata). */\n readonly config: Omit<CoreConfig, 'name'>\n\n /** Lifecycle interceptors for events and state updates. */\n readonly interceptors: LifecycleInterceptors = {\n event: new InterceptorManager<AnalyticsEvent | PersonalizationEvent>(),\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: CoreConfig) {\n this.config = config\n\n const {\n analytics,\n personalization,\n eventBuilder,\n logLevel,\n environment,\n clientId,\n fetchOptions,\n } = config\n\n logger.addSink(new ConsoleLogSink(logLevel))\n\n const apiConfig: ApiClientConfig = {\n clientId,\n environment,\n fetchOptions,\n analytics,\n personalization,\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 * Static {@link FlagsResolver | resolver} for evaluating personalized\n * custom flags.\n */\n get flagsResolver(): typeof FlagsResolver {\n return this._personalization.flagsResolver\n }\n\n /**\n * Static {@link MergeTagValueResolver | resolver} that returns values\n * sourced from a user profile based on a Contentful Merge Tag entry.\n */\n get mergeTagValueResolver(): typeof MergeTagValueResolver {\n return this._personalization.mergeTagValueResolver\n }\n\n /**\n * Static {@link PersonalizedEntryResolver | resolver } for personalized\n * Contentful entries (e.g., entry variants targeted to a profile audience).\n *\n * @remarks\n * Used by higher-level personalization flows to materialize entry content\n * prior to event emission.\n */\n get personalizedEntryResolver(): typeof PersonalizedEntryResolver {\n return this._personalization.personalizedEntryResolver\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 personalization’s flag resolution.\n * @example\n * ```ts\n * const darkMode = core.getCustomFlag('dark-mode', data.changes)\n * ```\n */\n getCustomFlag(name: string, changes?: ChangeArray): Json {\n return this._personalization.getCustomFlag(name, changes)\n }\n\n /**\n * Get all resolved custom flags derived from a set of optimization changes.\n *\n * @param changes - Optional change list to resolve from.\n * @returns The resolved custom flag map.\n * @remarks\n * This is a convenience wrapper around personalization’s flag resolution.\n * @example\n * ```ts\n * const flags = core.getCustomFlags(data.changes)\n * ```\n */\n getCustomFlags(changes?: ChangeArray): Flags {\n return this._personalization.getCustomFlags(changes)\n }\n\n /**\n * Resolve a Contentful entry to the appropriate personalized 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 personalizations - Optional selection array for the current profile.\n * @returns {@link ResolvedData} containing the resolved entry and\n * personalization metadata (if any).\n * @example\n * ```ts\n * const { entry, personalization } = core.personalizeEntry(baselineEntry, data.personalizations)\n * ```\n */\n personalizeEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(entry: Entry<S, M, L>, personalizations?: SelectedPersonalizationArray): ResolvedData<S, M, L> {\n return this._personalization.personalizeEntry<S, M, L>(entry, personalizations)\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._personalization.getMergeTagValue(embeddedEntryNodeTarget, profile)\n }\n\n /**\n * Convenience wrapper for sending an `identify` event via personalization.\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 return await this._personalization.identify(payload)\n }\n\n /**\n * Convenience wrapper for sending a `page` event via personalization.\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 return await this._personalization.page(payload)\n }\n\n /**\n * Convenience wrapper for sending a `screen` event via personalization.\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 return await this._personalization.screen(payload)\n }\n\n /**\n * Convenience wrapper for sending a custom `track` event via personalization.\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 return await this._personalization.track(payload)\n }\n\n /**\n * Track a component view in both personalization and analytics.\n *\n * @param payload - Component view builder arguments. When `payload.sticky` is\n * `true`, the event will also be sent via personalization as a sticky\n * component view.\n * @returns A promise that resolves when all delegated calls complete.\n * @remarks\n * The sticky behavior is delegated to personalization; analytics is always\n * invoked regardless of `sticky`.\n * @example\n * ```ts\n * await core.trackComponentView({ componentId: 'hero-banner', sticky: true })\n * ```\n */\n async trackComponentView(\n payload: ComponentViewBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData | undefined> {\n if (payload.sticky) {\n return await this._personalization.trackComponentView(payload)\n }\n\n await this._analytics.trackComponentView(payload)\n }\n\n /**\n * Track a component click via analytics.\n *\n * @param payload - Component click builder arguments.\n * @returns A promise that resolves when processing completes.\n * @example\n * ```ts\n * await core.trackComponentClick({ componentId: 'hero-banner' })\n * ```\n */\n async trackComponentClick(payload: ComponentClickBuilderArgs): Promise<void> {\n await this._analytics.trackComponentClick(payload)\n }\n\n /**\n * Track a component hover via analytics.\n *\n * @param payload - Component hover builder arguments.\n * @returns A promise that resolves when processing completes.\n * @example\n * ```ts\n * await core.trackComponentHover({ componentId: 'hero-banner' })\n * ```\n */\n async trackComponentHover(payload: ComponentHoverBuilderArgs): Promise<void> {\n await this._analytics.trackComponentHover(payload)\n }\n\n /**\n * Track a feature flag view via analytics.\n *\n * @param payload - Component 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: ComponentViewBuilderArgs): Promise<void> {\n await this._analytics.trackFlagView(payload)\n }\n}\n\nexport default CoreBase\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 type {\n ComponentViewBuilderArgs,\n IdentifyBuilderArgs,\n PageViewBuilderArgs,\n ScreenViewBuilderArgs,\n TrackBuilderArgs,\n} from '@contentful/optimization-api-client'\nimport type {\n ChangeArray,\n Flags,\n Json,\n MergeTagEntry,\n OptimizationData,\n Profile,\n SelectedPersonalizationArray,\n} from '@contentful/optimization-api-client/api-schemas'\nimport type { ChainModifiers, Entry, EntrySkeletonType, LocaleCode } from 'contentful'\nimport ProductBase from '../ProductBase'\nimport {\n FlagsResolver,\n MergeTagValueResolver,\n PersonalizedEntryResolver,\n type ResolvedData,\n} from './resolvers'\n\n/**\n * These methods assist in resolving values via Resolvers\n *\n * @internal\n * @privateRemarks\n * This interface exists to document that the included methods should not be\n * considered static.\n */\nexport interface ResolverMethods {\n /**\n * Get the specified Custom Flag's value from the supplied changes.\n * @param name - The name or key of the Custom Flag.\n * @param changes - Optional changes array.\n * @returns The current value of the Custom Flag if found.\n * @remarks\n * The changes array can be sourced from the data returned when emitting any\n * personalization event.\n * */\n getCustomFlag: (name: string, changes?: ChangeArray) => Json\n\n /**\n * Get all resolved Custom Flags from the supplied changes.\n * @param changes - Optional changes array.\n * @returns The resolved Custom Flag map.\n * @remarks\n * The changes array can be sourced from the data returned when emitting any\n * personalization event.\n * */\n getCustomFlags: (changes?: ChangeArray) => Flags\n\n /**\n * Resolve a Contentful entry to a personalized variant using the current\n * or provided selected personalizations.\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam M - Chain modifiers.\n * @typeParam L - Locale code.\n * @param entry - The entry to personalize.\n * @param personalizations - Optional selections.\n * @returns The resolved entry data.\n * @remarks\n * Selected personalizations can be sourced from the data returned when emitting any\n * personalization event.\n */\n personalizeEntry: <S extends EntrySkeletonType, M extends ChainModifiers, L extends LocaleCode>(\n entry: Entry<S, M, L>,\n personalizations?: SelectedPersonalizationArray,\n ) => ResolvedData<S, M, L>\n\n /**\n * Resolve a merge tag to a value based on the current (or provided) profile.\n *\n * @param embeddedEntryNodeTarget - The merge‑tag entry node to resolve.\n * @param profile - Optional profile.\n * @returns The resolved value (type depends on the tag).\n * @remarks\n * Merge tags are references to profile data that can be substituted into content. The\n * profile can be sourced from the data returned when emitting any personalization event.\n */\n getMergeTagValue: (\n embeddedEntryNodeTarget: MergeTagEntry,\n profile?: Profile,\n ) => string | undefined\n}\n\n/**\n * Internal base for personalization products.\n *\n * @internal\n * @remarks\n * Concrete implementations should extend this class to expose public methods for\n * identify, page, and track events. This base wires in shared singleton\n * resolvers used to fetch/resolve personalized data.\n */\nabstract class PersonalizationBase extends ProductBase implements ResolverMethods {\n /**\n * Static {@link FlagsResolver | resolver} for evaluating personalized\n * custom flags.\n */\n readonly flagsResolver = FlagsResolver\n\n /**\n * Static {@link MergeTagValueResolver | resolver} that returns values\n * sourced from a user profile based on a Contentful Merge Tag entry.\n */\n readonly mergeTagValueResolver = MergeTagValueResolver\n\n /**\n * Static {@link PersonalizedEntryResolver | resolver } for personalized\n * Contentful entries (e.g., entry variants targeted to a profile audience).\n *\n * @remarks\n * Used by higher-level personalization flows to materialize entry content\n * prior to event emission.\n */\n readonly personalizedEntryResolver = PersonalizedEntryResolver\n\n /**\n * Get the specified Custom Flag's value from the supplied changes.\n * @param name - The name/key of the Custom Flag.\n * @param changes - Optional changes array.\n * @returns The current value of the Custom Flag if found.\n * @remarks\n * The changes array can be sourced from the data returned when emitting any\n * personalization event.\n * */\n getCustomFlag(name: string, changes?: ChangeArray): Json {\n return this.getCustomFlags(changes)[name]\n }\n\n /**\n * Get all resolved Custom Flags from the supplied changes.\n * @param changes - Optional changes array.\n * @returns The resolved Custom Flag map.\n * @remarks\n * The changes array can be sourced from the data returned when emitting any\n * personalization event.\n * */\n getCustomFlags(changes?: ChangeArray): Flags {\n return FlagsResolver.resolve(changes)\n }\n\n /**\n * Resolve a Contentful entry to a personalized variant using the current\n * or provided selected personalizations.\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam M - Chain modifiers.\n * @typeParam L - Locale code.\n * @param entry - The entry to personalize.\n * @param personalizations - Optional selected personalizations.\n * @returns The resolved entry data.\n * @remarks\n * Selected personalizations can be sourced from the data returned when emitting any\n * personalization event.\n */\n personalizeEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(entry: Entry<S, M, L>, personalizations?: SelectedPersonalizationArray): ResolvedData<S, M, L> {\n return PersonalizedEntryResolver.resolve<S, M, L>(entry, personalizations)\n }\n\n /**\n * Resolve a merge tag to a value based on the current (or provided) profile.\n *\n * @param embeddedEntryNodeTarget - The merge tag entry node to resolve.\n * @param profile - Optional profile.\n * @returns The resolved value (type depends on the tag).\n * @remarks\n * Merge tags are references to profile data that can be substituted into content. The\n * profile can be sourced from the data returned when emitting any personalization event.\n */\n getMergeTagValue(embeddedEntryNodeTarget: MergeTagEntry, profile?: Profile): string | undefined {\n return MergeTagValueResolver.resolve(embeddedEntryNodeTarget, profile)\n }\n\n /**\n * Identify the current profile/visitor to associate traits with a profile.\n *\n * @param payload - Identify builder payload.\n * @returns The resulting {@link OptimizationData} for the identified user if the device is online.\n */\n abstract identify(payload: IdentifyBuilderArgs): Promise<OptimizationData | undefined>\n\n /**\n * Record a page view.\n *\n * @param payload - Page view builder payload.\n * @returns The evaluated {@link OptimizationData} for this page view if the device is online.\n */\n abstract page(payload: PageViewBuilderArgs): Promise<OptimizationData | undefined>\n\n /**\n * Record a screen view.\n *\n * @param payload - Screen view builder payload.\n * @returns The evaluated {@link OptimizationData} for this screen view if the device is online.\n */\n abstract screen(payload: ScreenViewBuilderArgs): Promise<OptimizationData | undefined>\n\n /**\n * Record a custom track event.\n *\n * @param payload - Track builder payload.\n * @returns The evaluated {@link OptimizationData} for this event if the device is online.\n */\n abstract track(payload: TrackBuilderArgs): Promise<OptimizationData | undefined>\n\n /**\n * Record a \"sticky\" component view.\n *\n * @param payload - \"Sticky\" component view builder payload.\n * @returns The evaluated {@link OptimizationData} for this component view if the device is online.\n * @remarks\n * This method is intended to be called only when a component is considered\n * \"sticky\".\n */\n abstract trackComponentView(\n payload: ComponentViewBuilderArgs,\n ): Promise<OptimizationData | undefined>\n}\n\nexport default PersonalizationBase\n","import type {\n ComponentViewBuilderArgs,\n IdentifyBuilderArgs,\n PageViewBuilderArgs,\n ScreenViewBuilderArgs,\n TrackBuilderArgs,\n} from '@contentful/optimization-api-client'\nimport {\n type InsightsEvent as AnalyticsEvent,\n type ChangeArray,\n type Flags,\n type Json,\n type MergeTagEntry,\n type OptimizationData,\n parseWithFriendlyError,\n ExperienceEvent as PersonalizationEvent,\n type ExperienceEventArray as PersonalizationEventArray,\n type Profile,\n type SelectedPersonalizationArray,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger } 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 { guardedBy } from '../lib/decorators'\nimport { toPositiveInt } from '../lib/number'\nimport {\n type QueueFlushPolicy,\n QueueFlushRuntime,\n type ResolvedQueueFlushPolicy,\n resolveQueueFlushPolicy,\n} from '../lib/queue'\nimport type { ProductBaseOptions, ProductConfig } from '../ProductBase'\nimport {\n batch,\n blockedEvent as blockedEventSignal,\n changes as changesSignal,\n consent as consentSignal,\n effect,\n event as eventSignal,\n flags as flagsSignal,\n type Observable,\n online as onlineSignal,\n personalizations as personalizationsSignal,\n profile as profileSignal,\n toObservable,\n} from '../signals'\nimport PersonalizationBase from './PersonalizationBase'\nimport type { ResolvedData } from './resolvers'\n\nconst logger = createScopedLogger('Personalization')\n\n/**\n * Default state values for {@link PersonalizationStateful} applied at construction time.\n *\n * @public\n */\nexport interface PersonalizationProductConfigDefaults {\n /** Whether personalization is allowed by default. */\n consent?: boolean\n /** Initial diff of changes produced by the service. */\n changes?: ChangeArray\n /** Default active profile used for personalization. */\n profile?: Profile\n /** Preselected personalization variants (e.g., winning treatments). */\n personalizations?: SelectedPersonalizationArray\n}\n\n/**\n * Configuration for {@link PersonalizationStateful}.\n *\n * @public\n */\nexport interface PersonalizationProductConfig extends ProductConfig {\n /** Default signal values applied during initialization. */\n defaults?: PersonalizationProductConfigDefaults\n\n /**\n * Policy that controls the offline personalization queue size and drop telemetry.\n */\n queuePolicy?: PersonalizationQueuePolicy\n\n /**\n * Function used to obtain an anonymous user identifier.\n *\n * @remarks\n * If a `getAnonymousId` function has been provided, the returned value will\n * take precedence over the `id` property of the current {@link Profile}\n * signal value\n *\n * @returns A string identifier, or `undefined` if no anonymous ID is available.\n */\n getAnonymousId?: () => string | undefined\n}\n\n/**\n * Context payload emitted when offline personalization events are dropped due to queue bounds.\n *\n * @public\n */\nexport interface PersonalizationOfflineQueueDropContext {\n /** Number of dropped events. */\n droppedCount: number\n /** Dropped events in oldest-first order. */\n droppedEvents: PersonalizationEventArray\n /** Configured queue max size. */\n maxEvents: number\n /** Queue size after enqueueing the current event. */\n queuedEvents: number\n}\n\n/**\n * Policy options for the stateful personalization offline queue.\n *\n * @public\n */\nexport interface PersonalizationQueuePolicy {\n /**\n * Maximum number of personalization events retained while offline.\n */\n maxEvents?: number\n\n /**\n * Callback invoked whenever oldest events are dropped due to queue bounds.\n */\n onDrop?: (context: PersonalizationOfflineQueueDropContext) => void\n\n /**\n * Policy that controls offline queue flush retries, backoff, and circuit\n * behavior after repeated failures.\n */\n flushPolicy?: QueueFlushPolicy\n}\n\n/**\n * Observables exposed by {@link PersonalizationStateful} that mirror internal signals.\n *\n * @public\n */\nexport interface PersonalizationStates {\n /** Observable stream of the latest blocked event payload (or `undefined`). */\n blockedEventStream: Observable<BlockedEvent | undefined>\n /** Observable stream of the latest {@link AnalyticsEvent} or {@link PersonalizationEvent} (or `undefined`). */\n eventStream: Observable<AnalyticsEvent | PersonalizationEvent | undefined>\n /** Live view of effective flags for the current profile (if available). */\n flags: Observable<Flags | undefined>\n /** Live view of the current profile. */\n profile: Observable<Profile | undefined>\n /** Live view of selected personalizations (variants). */\n personalizations: Observable<SelectedPersonalizationArray | undefined>\n}\n\n/**\n * Options for configuring {@link PersonalizationStateful} functionality.\n *\n * @public\n * @see {@link ProductBaseOptions}\n */\nexport type PersonalizationStatefulOptions = ProductBaseOptions & {\n /** Configuration specific to the Personalization product */\n config?: PersonalizationProductConfig\n}\n\nconst OFFLINE_QUEUE_MAX_EVENTS = 100\n\ninterface ResolvedQueuePolicy {\n maxEvents: number\n onDrop?: PersonalizationQueuePolicy['onDrop']\n flushPolicy: ResolvedQueueFlushPolicy\n}\n\nconst resolvePersonalizationQueuePolicy = (\n policy: PersonalizationQueuePolicy | undefined,\n): ResolvedQueuePolicy => ({\n maxEvents: toPositiveInt(policy?.maxEvents, OFFLINE_QUEUE_MAX_EVENTS),\n onDrop: policy?.onDrop,\n flushPolicy: resolveQueueFlushPolicy(policy?.flushPolicy),\n})\n\n/**\n * Stateful personalization product that manages consent, profile, flags, and\n * selected variants while emitting Experience events and updating state.\n *\n * @public\n * @remarks\n * The class maintains reactive signals and exposes read‑only observables via\n * {@link PersonalizationStateful.states}. Events are validated via schema parsers and\n * run through interceptors before being submitted. Resulting state is merged\n * back into signals.\n */\nclass PersonalizationStateful extends PersonalizationBase implements ConsentGuard {\n /** In-memory ordered queue for offline personalization events. */\n private readonly offlineQueue = new Set<PersonalizationEvent>()\n /** Resolved offline queue policy values. */\n private readonly queuePolicy: ResolvedQueuePolicy\n /** Shared queue flush retry runtime state machine. */\n private readonly flushRuntime: QueueFlushRuntime\n\n /** Exposed observable state references. */\n readonly states: PersonalizationStates = {\n blockedEventStream: toObservable(blockedEventSignal),\n eventStream: toObservable(eventSignal),\n flags: toObservable(flagsSignal),\n profile: toObservable(profileSignal),\n personalizations: toObservable(personalizationsSignal),\n }\n\n /**\n * Function that provides an anonymous ID when available.\n *\n * @internal\n */\n getAnonymousId: () => string | undefined\n\n /**\n * Create a new stateful personalization instance.\n *\n * @param options - Options to configure the personalization product for stateful environments.\n * @example\n * ```ts\n * const personalization = new PersonalizationStateful({ api, builder, config: { getAnonymousId }, interceptors })\n * ```\n */\n constructor(options: PersonalizationStatefulOptions) {\n const { api, builder, config, interceptors } = options\n\n super({ api, builder, config, interceptors })\n\n const { defaults, getAnonymousId, queuePolicy } = config ?? {}\n\n this.queuePolicy = resolvePersonalizationQueuePolicy(queuePolicy)\n this.flushRuntime = new QueueFlushRuntime({\n policy: this.queuePolicy.flushPolicy,\n onRetry: () => {\n void this.flush()\n },\n onCallbackError: (callbackName, error) => {\n logger.warn(`Personalization flush policy callback \"${callbackName}\" failed`, error)\n },\n })\n\n if (defaults) {\n const {\n changes: defaultChanges,\n personalizations: defaultPersonalizations,\n profile: defaultProfile,\n } = defaults\n\n batch(() => {\n changesSignal.value = defaultChanges\n personalizationsSignal.value = defaultPersonalizations\n profileSignal.value = defaultProfile\n })\n }\n\n if (defaults?.consent !== undefined) {\n const { consent: defaultConsent } = defaults\n consentSignal.value = defaultConsent\n }\n\n this.getAnonymousId = getAnonymousId ?? (() => undefined)\n\n // Log signal changes for observability\n effect(() => {\n logger.debug(\n `Profile ${profileSignal.value && `with ID ${profileSignal.value.id}`} has been ${profileSignal.value ? 'set' : 'cleared'}`,\n )\n })\n\n effect(() => {\n logger.debug(\n `Variants have been ${personalizationsSignal.value?.length ? 'populated' : 'cleared'}`,\n )\n })\n\n effect(() => {\n logger.info(\n `Personalization ${consentSignal.value ? 'will' : 'will not'} take effect due to consent (${consentSignal.value})`,\n )\n })\n\n effect(() => {\n if (!onlineSignal.value) return\n\n this.flushRuntime.clearScheduledRetry()\n void this.flush({ force: true })\n })\n }\n\n /**\n * Reset stateful signals managed by this product.\n *\n * @remarks\n * Clears `changes`, `profile`, and selected `personalizations`.\n * @example\n * ```ts\n * personalization.reset()\n * ```\n */\n reset(): void {\n this.flushRuntime.reset()\n\n batch(() => {\n changesSignal.value = undefined\n blockedEventSignal.value = undefined\n eventSignal.value = undefined\n profileSignal.value = undefined\n personalizationsSignal.value = undefined\n })\n }\n\n /**\n * Get the specified Custom Flag's value (derived from the signal).\n * @param name - The name or key of the Custom Flag.\n * @returns The current value of the Custom Flag if found.\n * @example\n * ```ts\n * const flagValue = personalization.getCustomFlag('dark-mode')\n * ```\n * */\n getCustomFlag(name: string, changes: ChangeArray | undefined = changesSignal.value): Json {\n return super.getCustomFlag(name, changes)\n }\n\n /**\n * Get all resolved Custom Flags (derived from the signal).\n * @param changes - Optional changes array; defaults to the current signal value.\n * @returns The resolved Custom Flag map.\n * @example\n * ```ts\n * const flags = personalization.getCustomFlags()\n * ```\n */\n getCustomFlags(changes: ChangeArray | undefined = changesSignal.value): Flags {\n return super.getCustomFlags(changes)\n }\n\n /**\n * Resolve a Contentful entry to a personalized variant using the current\n * or provided selections.\n *\n * @typeParam S - Entry skeleton type.\n * @typeParam M - Chain modifiers.\n * @typeParam L - Locale code.\n * @param entry - The entry to personalize.\n * @param personalizations - Optional selections; defaults to the current signal value.\n * @returns The resolved entry data.\n * @example\n * ```ts\n * const { entry } = personalization.personalizeEntry(baselineEntry)\n * ```\n */\n personalizeEntry<\n S extends EntrySkeletonType,\n M extends ChainModifiers = ChainModifiers,\n L extends LocaleCode = LocaleCode,\n >(\n entry: Entry<S, M, L>,\n personalizations: SelectedPersonalizationArray | undefined = personalizationsSignal.value,\n ): ResolvedData<S, M, L> {\n return super.personalizeEntry<S, M, L>(entry, personalizations)\n }\n\n /**\n * Resolve a merge tag to a value based on the current (or provided) profile.\n *\n * @param embeddedEntryNodeTarget - The merge‑tag entry node to resolve.\n * @param profile - Optional profile; defaults to the current signal value.\n * @returns The resolved value (type depends on the tag).\n * @remarks\n * Merge tags are references to profile data that can be substituted into content.\n * @example\n * ```ts\n * const name = personalization.getMergeTagValue(mergeTagNode)\n * ```\n */\n getMergeTagValue(\n embeddedEntryNodeTarget: MergeTagEntry,\n profile: Profile | undefined = profileSignal.value,\n ): string | undefined {\n return super.getMergeTagValue(embeddedEntryNodeTarget, profile)\n }\n\n /**\n * Determine whether the named operation is permitted based on consent and\n * allowed event type configuration.\n *\n * @param name - Method name; `trackComponentView` is normalized to\n * `'component'` for allow‑list checks.\n * @returns `true` if the operation is permitted; otherwise `false`.\n * @example\n * ```ts\n * if (personalization.hasConsent('track')) { ... }\n * ```\n */\n hasConsent(name: string): boolean {\n return (\n !!consentSignal.value ||\n (this.allowedEventTypes ?? []).includes(\n name === 'trackComponentView' || name === 'trackFlagView' ? 'component' : name,\n )\n )\n }\n\n /**\n * Hook invoked when an operation is blocked due to missing consent.\n *\n * @param name - The blocked operation name.\n * @param payload - The original arguments supplied to the operation.\n * @example\n * ```ts\n * personalization.onBlockedByConsent('track', [payload])\n * ```\n */\n onBlockedByConsent(name: string, payload: readonly unknown[]): void {\n logger.warn(\n `Event \"${name}\" was blocked due to lack of consent; payload: ${JSON.stringify(payload)}`,\n )\n this.reportBlockedEvent('consent', 'personalization', name, payload)\n }\n\n /**\n * Identify the current profile/visitor to associate traits with a profile\n * and update optimization state.\n *\n * @param payload - Identify builder payload.\n * @returns The resulting {@link OptimizationData} for the identified user.\n * @example\n * ```ts\n * const data = await personalization.identify({ userId: 'user-123' })\n * ```\n */\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async identify(payload: IdentifyBuilderArgs): Promise<OptimizationData | undefined> {\n logger.info('Sending \"identify\" event')\n\n const event = this.builder.buildIdentify(payload)\n\n return await this.sendOrEnqueueEvent(event)\n }\n\n /**\n * Record a page view and update optimization state.\n *\n * @param payload - Page view builder payload.\n * @returns The evaluated {@link OptimizationData} for this page view.\n * @example\n * ```ts\n * const data = await personalization.page({ properties: { title: 'Home' } })\n * ```\n */\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async page(payload: PageViewBuilderArgs): Promise<OptimizationData | undefined> {\n logger.info('Sending \"page\" event')\n\n const event = this.builder.buildPageView(payload)\n\n return await this.sendOrEnqueueEvent(event)\n }\n\n /**\n * Record a screen view and update optimization state.\n *\n * @param payload - Screen view builder payload.\n * @returns The evaluated {@link OptimizationData} for this screen view.\n * @example\n * ```ts\n * const data = await personalization.screen({ name: 'HomeScreen' })\n * ```\n */\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async screen(payload: ScreenViewBuilderArgs): Promise<OptimizationData | undefined> {\n logger.info(`Sending \"screen\" event for \"${payload.name}\"`)\n\n const event = this.builder.buildScreenView(payload)\n\n return await this.sendOrEnqueueEvent(event)\n }\n\n /**\n * Record a custom track event and update optimization state.\n *\n * @param payload - Track builder payload.\n * @returns The evaluated {@link OptimizationData} for this event.\n * @example\n * ```ts\n * const data = await personalization.track({ event: 'button_click' })\n * ```\n */\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async track(payload: TrackBuilderArgs): Promise<OptimizationData | undefined> {\n logger.info(`Sending \"track\" event \"${payload.event}\"`)\n\n const event = this.builder.buildTrack(payload)\n\n return await this.sendOrEnqueueEvent(event)\n }\n\n /**\n * Record a \"sticky\" component view and update optimization state.\n *\n * @param payload - Component view builder payload.\n * @returns The evaluated {@link OptimizationData} for this component view.\n * @example\n * ```ts\n * const data = await personalization.trackComponentView({ componentId: 'hero-banner' })\n * ```\n */\n @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })\n async trackComponentView(\n payload: ComponentViewBuilderArgs,\n ): Promise<OptimizationData | undefined> {\n logger.info(`Sending \"track personalization\" event for ${payload.componentId}`)\n\n const event = this.builder.buildComponentView(payload)\n\n return await this.sendOrEnqueueEvent(event)\n }\n\n /**\n * Intercept, validate, and place an event into the offline event queue; then\n * trigger a size‑based flush if necessary.\n *\n * @param event - The event to enqueue.\n */\n private async sendOrEnqueueEvent(\n event: PersonalizationEvent,\n ): Promise<OptimizationData | undefined> {\n const intercepted = await this.interceptors.event.run(event)\n\n const validEvent = parseWithFriendlyError(PersonalizationEvent, intercepted)\n\n eventSignal.value = validEvent\n\n if (onlineSignal.value) return await this.upsertProfile([validEvent])\n\n logger.debug(`Queueing ${validEvent.type} event`, validEvent)\n\n this.enqueueOfflineEvent(validEvent)\n\n return undefined\n }\n\n /**\n * Enqueue an offline event, dropping oldest events first when queue bounds are reached.\n *\n * @param event - Event to enqueue.\n */\n private enqueueOfflineEvent(event: PersonalizationEvent): void {\n let droppedEvents: PersonalizationEventArray = []\n\n if (this.offlineQueue.size >= this.queuePolicy.maxEvents) {\n const dropCount = this.offlineQueue.size - this.queuePolicy.maxEvents + 1\n droppedEvents = this.dropOldestOfflineEvents(dropCount)\n\n if (droppedEvents.length > 0) {\n logger.warn(\n `Dropped ${droppedEvents.length} oldest personalization offline event(s) due to queue limit (${this.queuePolicy.maxEvents})`,\n )\n }\n }\n\n this.offlineQueue.add(event)\n\n if (droppedEvents.length > 0) {\n this.invokeQueueDropCallback({\n droppedCount: droppedEvents.length,\n droppedEvents,\n maxEvents: this.queuePolicy.maxEvents,\n queuedEvents: this.offlineQueue.size,\n })\n }\n }\n\n /**\n * Drop oldest offline events from the queue.\n *\n * @param count - Number of oldest events to drop.\n * @returns Dropped events in oldest-first order.\n */\n private dropOldestOfflineEvents(count: number): PersonalizationEventArray {\n const droppedEvents: PersonalizationEventArray = []\n\n for (let index = 0; index < count; index += 1) {\n const oldestEvent = this.offlineQueue.values().next()\n if (oldestEvent.done) break\n\n this.offlineQueue.delete(oldestEvent.value)\n droppedEvents.push(oldestEvent.value)\n }\n\n return droppedEvents\n }\n\n /**\n * Invoke offline queue drop callback in a fault-tolerant manner.\n *\n * @param context - Drop callback payload.\n */\n private invokeQueueDropCallback(context: PersonalizationOfflineQueueDropContext): void {\n try {\n this.queuePolicy.onDrop?.(context)\n } catch (error) {\n logger.warn('Personalization offline queue drop callback failed', error)\n }\n }\n\n /**\n * Flush the offline queue\n *\n * @param options - Optional flush controls.\n * @param options.force - When `true`, bypass offline/backoff/circuit gates and attempt immediately.\n *\n * @example\n * ```ts\n * await personalization.flush()\n */\n async flush(options: { force?: boolean } = {}): Promise<void> {\n await this.flushOfflineQueue(options)\n }\n\n /**\n * Flush queued offline events using retry/circuit guards.\n *\n * @param options - Flush controls.\n * @param options.force - When true, bypass online/backoff/circuit gates.\n */\n private async flushOfflineQueue(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.offlineQueue.size === 0) {\n this.flushRuntime.clearScheduledRetry()\n return\n }\n\n logger.debug('Flushing offline event queue')\n\n const queuedEvents = Array.from(this.offlineQueue)\n this.flushRuntime.markFlushStarted()\n\n try {\n const sendSuccess = await this.tryUpsertQueuedEvents(queuedEvents)\n\n if (sendSuccess) {\n queuedEvents.forEach((event) => {\n this.offlineQueue.delete(event)\n })\n this.flushRuntime.handleFlushSuccess()\n } else {\n this.flushRuntime.handleFlushFailure({\n queuedBatches: this.offlineQueue.size > 0 ? 1 : 0,\n queuedEvents: this.offlineQueue.size,\n })\n }\n } finally {\n this.flushRuntime.markFlushFinished()\n }\n }\n\n /**\n * Attempt to send queued events to the Experience API.\n *\n * @param events - Snapshot of queued events to send.\n * @returns `true` when send succeeds; otherwise `false`.\n */\n private async tryUpsertQueuedEvents(events: PersonalizationEventArray): Promise<boolean> {\n try {\n await this.upsertProfile(events)\n return true\n } catch (error) {\n logger.warn('Personalization offline queue flush request threw an error', error)\n return false\n }\n }\n\n /**\n * Submit events to the Experience API, updating output signals with the\n * returned state.\n *\n * @param events - The events to submit.\n * @returns The {@link OptimizationData} returned by the service.\n * @internal\n * @privateRemarks\n * If a `getAnonymousId` function has been provided, the returned value will\n * take precedence over the `id` property of the current {@link Profile}\n * signal value\n */\n private async upsertProfile(events: PersonalizationEventArray): Promise<OptimizationData> {\n const anonymousId = this.getAnonymousId()\n if (anonymousId) logger.debug(`Anonymous ID found: ${anonymousId}`)\n\n const data = await this.api.experience.upsertProfile({\n profileId: anonymousId ?? profileSignal.value?.id,\n events,\n })\n\n await this.updateOutputSignals(data)\n\n return data\n }\n\n /**\n * Apply returned optimization state to local signals after interceptor processing.\n *\n * @param data - Optimization state returned by the service.\n * @internal\n */\n private async updateOutputSignals(data: OptimizationData): Promise<void> {\n const intercepted = await this.interceptors.state.run(data)\n\n const { changes, personalizations, profile } = 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(personalizationsSignal.value, personalizations))\n personalizationsSignal.value = personalizations\n })\n }\n}\n\nexport default PersonalizationStateful\n","import type {\n ComponentViewBuilderArgs,\n IdentifyBuilderArgs,\n PageViewBuilderArgs,\n ScreenViewBuilderArgs,\n TrackBuilderArgs,\n} from '@contentful/optimization-api-client'\nimport {\n ComponentViewEvent,\n IdentifyEvent,\n type OptimizationData,\n PageViewEvent,\n parseWithFriendlyError,\n type PartialProfile,\n ExperienceEvent as PersonalizationEvent,\n ScreenViewEvent,\n TrackEvent,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { createScopedLogger } from '@contentful/optimization-api-client/logger'\nimport PersonalizationBase from './PersonalizationBase'\n\nconst logger = createScopedLogger('Personalization')\n\n/**\n * Stateless personalization implementation that immediately validates and sends\n * a single event to the Experience API, upserting the profile as needed.\n *\n * @public\n * @remarks\n * Each public method constructs a strongly-typed event via the shared builder,\n * runs it through event interceptors, and performs a profile upsert using the\n * Experience API. If an anonymous ID is available from the builder, it will be\n * preferred as the `profileId` unless an explicit profile is provided.\n */\nclass PersonalizationStateless extends PersonalizationBase {\n /**\n * Identify the current profile/visitor to associate traits with a profile.\n *\n * @param payload - Identify builder arguments with an optional partial\n * profile to attach to the upsert request.\n * @returns The resulting {@link OptimizationData} for the identified user.\n * @example\n * ```ts\n * const data = await personalization.identify({ userId: 'user-123', profile: { id: 'anon-1' } })\n * ```\n */\n async identify(\n payload: IdentifyBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData> {\n logger.info('Sending \"identify\" event')\n\n const { profile, ...builderArgs } = payload\n\n const event = parseWithFriendlyError(IdentifyEvent, this.builder.buildIdentify(builderArgs))\n\n return await this.upsertProfile(event, profile)\n }\n\n /**\n * Record a page view.\n *\n * @param payload - Page view builder arguments with an optional partial profile.\n * @returns The evaluated {@link OptimizationData} for this page view.\n * @example\n * ```ts\n * const data = await personalization.page({ properties: { title: 'Home' }, profile: { id: 'anon-1' } })\n * ```\n */\n async page(\n payload: PageViewBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData> {\n logger.info('Sending \"page\" event')\n\n const { profile, ...builderArgs } = payload\n\n const event = parseWithFriendlyError(PageViewEvent, this.builder.buildPageView(builderArgs))\n\n return await this.upsertProfile(event, profile)\n }\n\n /**\n * Record a screen view.\n *\n * @param payload - Screen view builder arguments with an optional partial profile.\n * @returns The evaluated {@link OptimizationData} for this screen view.\n * @example\n * ```ts\n * const data = await personalization.screen({ name: 'HomeScreen', profile: { id: 'anon-1' } })\n * ```\n */\n async screen(\n payload: ScreenViewBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData> {\n logger.info(`Sending \"screen\" event for \"${payload.name}\"`)\n\n const { profile, ...builderArgs } = payload\n\n const event = parseWithFriendlyError(ScreenViewEvent, this.builder.buildScreenView(builderArgs))\n\n return await this.upsertProfile(event, profile)\n }\n\n /**\n * Record a custom track event.\n *\n * @param payload - Track builder arguments with an optional partial profile.\n * @returns The evaluated {@link OptimizationData} for this event.\n * @example\n * ```ts\n * const data = await personalization.track({ event: 'purchase', profile: { id: 'anon-1' } })\n * ```\n */\n async track(payload: TrackBuilderArgs & { profile?: PartialProfile }): Promise<OptimizationData> {\n logger.info(`Sending \"track\" event \"${payload.event}\"`)\n\n const { profile, ...builderArgs } = payload\n\n const event = parseWithFriendlyError(TrackEvent, this.builder.buildTrack(builderArgs))\n\n return await this.upsertProfile(event, profile)\n }\n\n /**\n * Record a \"sticky\" component view.\n *\n * @param payload - Component view builder arguments with an optional partial profile.\n * @returns The evaluated {@link OptimizationData} for this component view.\n * @example\n * ```ts\n * const data = await personalization.trackComponentView({ componentId: 'hero', profile: { id: 'anon-1' } })\n * ```\n */\n async trackComponentView(\n payload: ComponentViewBuilderArgs & { profile?: PartialProfile },\n ): Promise<OptimizationData> {\n logger.info('Sending \"track personalization\" event')\n\n const { profile, ...builderArgs } = payload\n\n const event = parseWithFriendlyError(\n ComponentViewEvent,\n this.builder.buildComponentView(builderArgs),\n )\n\n return await this.upsertProfile(event, profile)\n }\n\n /**\n * Intercept, validate, and upsert the profile with a single personalization\n * event.\n *\n * @param event - The {@link PersonalizationEvent} to submit.\n * @param profile - Optional partial profile. If omitted, the anonymous ID from\n * the builder (when present) is used as the `profileId`.\n * @returns The {@link OptimizationData} returned by the Experience API.\n * @internal\n */\n private async upsertProfile(\n event: PersonalizationEvent,\n profile?: PartialProfile,\n ): Promise<OptimizationData> {\n const intercepted = await this.interceptors.event.run(event)\n const validEvent = parseWithFriendlyError(PersonalizationEvent, intercepted)\n\n const data = await this.api.experience.upsertProfile({\n profileId: profile?.id,\n events: [validEvent],\n })\n\n return data\n }\n}\n\nexport default PersonalizationStateless\n","import type {\n InsightsEvent as AnalyticsEvent,\n ChangeArray,\n ExperienceEvent as PersonalizationEvent,\n Profile,\n SelectedPersonalizationArray,\n} from '@contentful/optimization-api-client/api-schemas'\nimport { AnalyticsStateful, type AnalyticsProductConfig, type AnalyticsStates } from './analytics'\nimport type { BlockedEvent } from './BlockedEvent'\nimport type { ConsentController } from './Consent'\nimport CoreBase, { type CoreConfig } from './CoreBase'\nimport {\n acquireStatefulRuntimeSingleton,\n releaseStatefulRuntimeSingleton,\n} from './lib/singleton/StatefulRuntimeSingleton'\nimport {\n PersonalizationStateful,\n type PersonalizationProductConfig,\n type PersonalizationStates,\n} from './personalization'\nimport type { ProductConfig } from './ProductBase'\nimport {\n batch,\n blockedEvent,\n changes,\n consent,\n event,\n flags,\n online,\n personalizations,\n previewPanelAttached,\n previewPanelOpen,\n profile,\n signalFns,\n signals,\n toObservable,\n type Observable,\n type SignalFns,\n type Signals,\n} from './signals'\nimport { PREVIEW_PANEL_SIGNAL_FNS_SYMBOL, PREVIEW_PANEL_SIGNALS_SYMBOL } from './symbols'\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 * @see {@link AnalyticsStates}\n * @see {@link PersonalizationStates}\n */\nexport interface CoreStates extends AnalyticsStates, PersonalizationStates {\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 (analytics or personalization). */\n eventStream: Observable<AnalyticsEvent | PersonalizationEvent | undefined>\n}\n\n/**\n * Default values used to preconfigure the stateful core and products.\n *\n * @public\n */\nexport interface CoreConfigDefaults {\n /** Global consent default applied at construction time. */\n consent?: boolean\n /** Default active profile used for personalization and analytics. */\n profile?: Profile\n /** Initial diff of changes produced by the service. */\n changes?: ChangeArray\n /** Preselected personalization variants (e.g., winning treatments). */\n personalizations?: SelectedPersonalizationArray\n}\n\n/**\n * Stateful analytics configuration.\n *\n * @public\n */\nexport type CoreStatefulAnalyticsConfig = NonNullable<CoreConfig['analytics']> & {\n /**\n * Queue policy for stateful analytics event buffering and flush retries.\n *\n * @see {@link AnalyticsProductConfig.queuePolicy}\n */\n queuePolicy?: AnalyticsProductConfig['queuePolicy']\n}\n\n/**\n * Stateful personalization configuration.\n *\n * @public\n */\nexport type CoreStatefulPersonalizationConfig = NonNullable<CoreConfig['personalization']> & {\n /**\n * Queue policy for stateful personalization offline event buffering.\n *\n * @see {@link PersonalizationProductConfig.queuePolicy}\n */\n queuePolicy?: PersonalizationProductConfig['queuePolicy']\n}\n\nconst splitScopedQueuePolicy = <\n TQueuePolicy,\n TScopedConfig extends {\n queuePolicy?: TQueuePolicy\n },\n>(\n config: TScopedConfig | undefined,\n): {\n apiConfig: Omit<TScopedConfig, 'queuePolicy'> | undefined\n queuePolicy: TQueuePolicy | undefined\n} => {\n if (config === undefined) {\n return {\n apiConfig: undefined,\n queuePolicy: undefined,\n }\n }\n\n const { queuePolicy, ...apiConfig } = config\n const resolvedApiConfig = Object.keys(apiConfig).length > 0 ? apiConfig : undefined\n\n return {\n apiConfig: resolvedApiConfig,\n queuePolicy,\n }\n}\n\n/**\n * Configuration for {@link CoreStateful}.\n *\n * @public\n * @see {@link CoreConfig}\n */\nexport interface CoreStatefulConfig extends CoreConfig {\n /**\n * Configuration for the analytics (Insights) API client plus stateful queue behavior.\n */\n analytics?: CoreStatefulAnalyticsConfig\n\n /**\n * Configuration for the personalization (Experience) API client plus stateful queue behavior.\n */\n personalization?: CoreStatefulPersonalizationConfig\n\n /**\n * Allow-listed event type strings permitted when consent is not set.\n *\n * @see {@link ProductConfig.allowedEventTypes}\n */\n allowedEventTypes?: ProductConfig['allowedEventTypes']\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?: PersonalizationProductConfig['getAnonymousId']\n\n /**\n * Callback invoked whenever an event call is blocked by checks.\n */\n onEventBlocked?: ProductConfig['onEventBlocked']\n}\n\nlet statefulInstanceCounter = 0\n\n/**\n * Core runtime that constructs stateful product instances and exposes shared\n * states, including consent, blocked events, and the event stream.\n *\n * @remarks\n * Extends {@link CoreBase} with stateful capabilities, including\n * consent management via {@link ConsentController}.\n * @see {@link CoreBase}\n * @see {@link ConsentController}\n * @public\n */\nclass CoreStateful extends CoreBase implements ConsentController {\n private readonly singletonOwner: string\n private destroyed = false\n\n /** Stateful analytics product. */\n protected _analytics: AnalyticsStateful\n /** Stateful personalization product. */\n protected _personalization: PersonalizationStateful\n\n /**\n * Create a stateful core with optional default consent and product defaults.\n *\n * @param config - Core and defaults configuration.\n * @example\n * ```ts\n * const core = new CoreStateful({\n * clientId: 'app',\n * environment: 'prod',\n * defaults: { consent: true }\n * })\n * core.consent(true)\n * ```\n */\n constructor(config: CoreStatefulConfig) {\n const { apiConfig: analyticsApiConfig, queuePolicy: analyticsRuntimeQueuePolicy } =\n splitScopedQueuePolicy<AnalyticsProductConfig['queuePolicy'], CoreStatefulAnalyticsConfig>(\n config.analytics,\n )\n const { apiConfig: personalizationApiConfig, queuePolicy: personalizationRuntimeQueuePolicy } =\n splitScopedQueuePolicy<\n PersonalizationProductConfig['queuePolicy'],\n CoreStatefulPersonalizationConfig\n >(config.personalization)\n const baseConfig: CoreConfig = {\n ...config,\n analytics: analyticsApiConfig,\n personalization: personalizationApiConfig,\n }\n\n super(baseConfig)\n\n this.singletonOwner = `CoreStateful#${++statefulInstanceCounter}`\n acquireStatefulRuntimeSingleton(this.singletonOwner)\n\n try {\n const { allowedEventTypes, defaults, getAnonymousId, onEventBlocked } = config\n\n if (defaults?.consent !== undefined) {\n const { consent: defaultConsent } = defaults\n consent.value = defaultConsent\n }\n\n this._analytics = new AnalyticsStateful({\n api: this.api,\n builder: this.eventBuilder,\n config: {\n allowedEventTypes,\n queuePolicy: analyticsRuntimeQueuePolicy,\n onEventBlocked,\n defaults: {\n consent: defaults?.consent,\n profile: defaults?.profile,\n },\n },\n interceptors: this.interceptors,\n })\n\n this._personalization = new PersonalizationStateful({\n api: this.api,\n builder: this.eventBuilder,\n config: {\n allowedEventTypes,\n getAnonymousId,\n queuePolicy: personalizationRuntimeQueuePolicy,\n onEventBlocked,\n defaults: {\n consent: defaults?.consent,\n changes: defaults?.changes,\n profile: defaults?.profile,\n personalizations: defaults?.personalizations,\n },\n },\n interceptors: this.interceptors,\n })\n } catch (error) {\n releaseStatefulRuntimeSingleton(this.singletonOwner)\n throw error\n }\n }\n\n /**\n * Release singleton ownership for stateful runtime usage.\n *\n * @remarks\n * This method is idempotent and should be called when a stateful SDK instance\n * is no longer needed (e.g. tests, hot reload, explicit teardown).\n */\n destroy(): void {\n if (this.destroyed) return\n\n this.destroyed = true\n releaseStatefulRuntimeSingleton(this.singletonOwner)\n }\n\n /**\n * Expose merged observable state for consumers.\n *\n * @returns The combined {@link CoreStates} observable object.\n */\n get states(): CoreStates {\n return {\n blockedEventStream: toObservable(blockedEvent),\n consent: toObservable(consent),\n eventStream: toObservable(event),\n flags: toObservable(flags),\n personalizations: toObservable(personalizations),\n previewPanelAttached: toObservable(previewPanelAttached),\n previewPanelOpen: toObservable(previewPanelOpen),\n profile: toObservable(profile),\n }\n }\n\n /**\n * Reset internal state. Consent and preview panel state are intentionally preserved.\n *\n * @remarks\n * Resetting personalization also resets analytics dependencies as a\n * consequence of the current shared-state design.\n * @example\n * ```ts\n * core.reset()\n * ```\n */\n reset(): void {\n batch(() => {\n blockedEvent.value = undefined\n event.value = undefined\n changes.value = undefined\n profile.value = undefined\n personalizations.value = undefined\n })\n }\n\n /**\n * Flush the queues for both the analytics and personalization products.\n * @remarks\n * The personalization queue is only populated if events have been triggered\n * while a device is offline.\n * @example\n * ```ts\n * await core.flush()\n * ```\n */\n async flush(): Promise<void> {\n await this._analytics.flush()\n await this._personalization.flush()\n }\n\n /**\n * Update consent state\n *\n * @param accept - `true` if the user has granted consent; `false` otherwise.\n * @example\n * ```ts\n * core.consent(true)\n * ```\n */\n consent(accept: boolean): void {\n consent.value = accept\n }\n\n /**\n * Read current online state.\n *\n * @example\n * ```ts\n * if (this.online) {\n * await this.flush()\n * }\n * ```\n */\n protected get online(): boolean {\n return online.value ?? false\n }\n\n /**\n * Update online state.\n *\n * @param isOnline - `true` if the runtime is online; `false` otherwise.\n * @example\n * ```ts\n * this.online = navigator.onLine\n * ```\n */\n protected set online(isOnline: boolean) {\n online.value = isOnline\n }\n\n /**\n * Register a preview panel compatible object to receive direct signal access.\n * This enables the preview panel to modify SDK state for testing and simulation.\n *\n * @param previewPanel - An object implementing PreviewPanelSignalObject\n * @remarks\n * This method is intended for use by the Preview Panel component.\n * Direct signal access allows immediate state updates without API calls.\n * @example\n * ```ts\n * const previewBridge: PreviewPanelSignalObject = {}\n * core.registerPreviewPanel(previewBridge)\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 { EventBuilderConfig } from '@contentful/optimization-api-client'\nimport { AnalyticsStateless } from './analytics'\nimport CoreBase, { type CoreConfig } from './CoreBase'\nimport { PersonalizationStateless } from './personalization'\n\n/**\n * Configuration for the Node-specific Optimization SDK.\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 * Override configuration for the analytics (Insights) API client. Omits\n * `beaconHandler`.\n */\n analytics?: Omit<CoreConfig['analytics'], 'beaconHandler'>\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\n/**\n * Core runtime that constructs product instances for stateless environments.\n *\n * @public\n * @see {@link CoreBase}\n */\nclass CoreStateless extends CoreBase {\n /** Stateless analytics product. */\n protected _analytics: AnalyticsStateless\n /** Stateless personalization product. */\n protected _personalization: PersonalizationStateless\n\n /**\n * Create a stateless core. Product instances share the same API client and\n * event builder configured in {@link CoreBase}.\n *\n * @param config - Stateless Core configuration.\n * @example\n * ```ts\n * const sdk = new CoreStateless({ clientId: 'app', environment: 'prod' })\n * core.trackFlagView({ componentId: 'hero' })\n * ```\n */\n constructor(config: CoreStatelessConfig) {\n super(config)\n\n this._analytics = new AnalyticsStateless({\n api: this.api,\n builder: this.eventBuilder,\n interceptors: this.interceptors,\n })\n\n this._personalization = new PersonalizationStateless({\n api: this.api,\n builder: this.eventBuilder,\n interceptors: this.interceptors,\n })\n }\n}\n\nexport default CoreStateless\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","PERSONALIZATIONS_CACHE_KEY","ANONYMOUS_ID_COOKIE_LEGACY","ANONYMOUS_ID_KEY_LEGACY","PREVIEW_PANEL_SIGNALS_SYMBOL","Symbol","PREVIEW_PANEL_SIGNAL_FNS_SYMBOL","__webpack_require__","definition","key","Object","obj","prop","FlagsResolver","changes","acc","value","actualValue","logger","createScopedLogger","RESOLUTION_WARNING_BASE","getAtPath","path","current","segments","Boolean","segment","Reflect","MergeTagValueResolver","id","_path","index","paths","dotPath","underScorePath","profile","selectors","matchingSelector","selector","mergeTagEntry","isMergeTagEntry","fallback","Profile","PersonalizedEntryResolver","personalizedEntry","selectedPersonalizations","skipValidation","isPersonalizedEntry","personalizationEntry","maybePersonalization","isPersonalizationEntry","experienceId","selectedPersonalization","selectedVariantIndex","relevantVariants","component","isEntryReplacementComponent","selectedVariant","isEntryReplacementVariant","selectedVariantEntry","variant","isEntry","undefined","entry","signal","blockedEvent","consent","event","flags","computed","online","previewPanelAttached","previewPanelOpen","personalizations","toObservable","s","next","dispose","effect","signals","signalFns","batch","untracked","isFunction","v","nameToString","name","String","isOnBlockedKey","isAsyncFunction","fn","guardedBy","predicateName","opts","_value","context","decoratedName","originalUnknown","original","originalIsAsync","resolvePredicate","self","cand","TypeError","computeAllowed","args","pred","ok","runOnBlocked","onBlocked","handlerCandidate","blockedReturn","Promise","wrapped","toPositiveInt","Number","Math","toRatio","DEFAULT_QUEUE_FLUSH_POLICY","resolveQueueFlushPolicy","policy","defaults","baseBackoffMs","maxBackoffMs","computeQueueFlushRetryDelayMs","options","consecutiveFailures","jitterRatio","exponential","capped","jitter","createQueueFlushFailureWindow","failureTimestamp","retryDelayMs","maxConsecutiveFailures","circuitOpenMs","circuitOpenUntil","QueueFlushRuntime","onCallbackError","onRetry","clearTimeout","force","isOnline","now","Date","previousConsecutiveFailures","queuedBatches","queuedEvents","failureContext","failureWindow","nextFlushAllowedAt","openedCircuit","scheduledRetryDelayMs","delayMs","setTimeout","callbackName","payload","error","defaultAllowedEvents","ProductBase","api","builder","config","interceptors","reason","product","method","AnalyticsBase","MAX_QUEUED_EVENTS","ANALYTICS_METHOD_EVENT_TYPE_MAP","AnalyticsStateful","Map","blockedEventSignal","eventSignal","profileSignal","mappedEventType","JSON","intercepted","validEvent","parseWithFriendlyError","AnalyticsEvent","profileId","queuedProfileEvents","onlineSignal","batches","sendSuccess","defaultProfile","events","queuedCount","AnalyticsStateless","builderArgs","parsed","batchEvent","BatchInsightsEventArray","InterceptorManager","interceptor","input","fns","Array","CoreBase","analytics","personalization","eventBuilder","logLevel","environment","clientId","fetchOptions","ConsoleLogSink","apiConfig","ApiClient","EventBuilder","embeddedEntryNodeTarget","STATEFUL_RUNTIME_LOCK_KEY","getStatefulRuntimeLock","singletonGlobal","globalThis","acquireStatefulRuntimeSingleton","owner","lock","Error","releaseStatefulRuntimeSingleton","PersonalizationBase","OFFLINE_QUEUE_MAX_EVENTS","resolvePersonalizationQueuePolicy","PersonalizationStateful","Set","flagsSignal","personalizationsSignal","getAnonymousId","queuePolicy","defaultChanges","defaultPersonalizations","changesSignal","defaultConsent","consentSignal","PersonalizationEvent","droppedEvents","dropCount","count","oldestEvent","anonymousId","data","isEqual","PersonalizationStateless","IdentifyEvent","PageViewEvent","ScreenViewEvent","TrackEvent","ComponentViewEvent","splitScopedQueuePolicy","resolvedApiConfig","statefulInstanceCounter","CoreStateful","analyticsApiConfig","analyticsRuntimeQueuePolicy","personalizationApiConfig","personalizationRuntimeQueuePolicy","baseConfig","allowedEventTypes","onEventBlocked","accept","previewPanel","CoreStateless"],"mappings":"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"}
|