@contentful/optimization-core 0.1.0-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +408 -0
  3. package/dist/Consent.d.ts +44 -0
  4. package/dist/Consent.d.ts.map +1 -0
  5. package/dist/Consent.js +2 -0
  6. package/dist/Consent.js.map +1 -0
  7. package/dist/CoreBase.d.ts +161 -0
  8. package/dist/CoreBase.d.ts.map +1 -0
  9. package/dist/CoreBase.js +151 -0
  10. package/dist/CoreBase.js.map +1 -0
  11. package/dist/CoreStateful.d.ts +142 -0
  12. package/dist/CoreStateful.d.ts.map +1 -0
  13. package/dist/CoreStateful.js +137 -0
  14. package/dist/CoreStateful.js.map +1 -0
  15. package/dist/CoreStateless.d.ts +53 -0
  16. package/dist/CoreStateless.d.ts.map +1 -0
  17. package/dist/CoreStateless.js +43 -0
  18. package/dist/CoreStateless.js.map +1 -0
  19. package/dist/ProductBase.d.ts +83 -0
  20. package/dist/ProductBase.d.ts.map +1 -0
  21. package/dist/ProductBase.js +50 -0
  22. package/dist/ProductBase.js.map +1 -0
  23. package/dist/analytics/AnalyticsBase.d.ts +35 -0
  24. package/dist/analytics/AnalyticsBase.d.ts.map +1 -0
  25. package/dist/analytics/AnalyticsBase.js +13 -0
  26. package/dist/analytics/AnalyticsBase.js.map +1 -0
  27. package/dist/analytics/AnalyticsStateful.d.ts +138 -0
  28. package/dist/analytics/AnalyticsStateful.d.ts.map +1 -0
  29. package/dist/analytics/AnalyticsStateful.js +179 -0
  30. package/dist/analytics/AnalyticsStateful.js.map +1 -0
  31. package/dist/analytics/AnalyticsStateless.d.ts +48 -0
  32. package/dist/analytics/AnalyticsStateless.d.ts.map +1 -0
  33. package/dist/analytics/AnalyticsStateless.js +61 -0
  34. package/dist/analytics/AnalyticsStateless.js.map +1 -0
  35. package/dist/analytics/index.d.ts +5 -0
  36. package/dist/analytics/index.d.ts.map +1 -0
  37. package/dist/analytics/index.js +5 -0
  38. package/dist/analytics/index.js.map +1 -0
  39. package/dist/global-constants.d.ts +18 -0
  40. package/dist/global-constants.d.ts.map +1 -0
  41. package/dist/global-constants.js +18 -0
  42. package/dist/global-constants.js.map +1 -0
  43. package/dist/index.cjs +1808 -0
  44. package/dist/index.cjs.map +1 -0
  45. package/dist/index.d.ts +15 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +15 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/index.mjs +1535 -0
  50. package/dist/index.mjs.map +1 -0
  51. package/dist/lib/decorators/guardedBy.d.ts +113 -0
  52. package/dist/lib/decorators/guardedBy.d.ts.map +1 -0
  53. package/dist/lib/decorators/guardedBy.js +143 -0
  54. package/dist/lib/decorators/guardedBy.js.map +1 -0
  55. package/dist/lib/decorators/index.d.ts +2 -0
  56. package/dist/lib/decorators/index.d.ts.map +1 -0
  57. package/dist/lib/decorators/index.js +2 -0
  58. package/dist/lib/decorators/index.js.map +1 -0
  59. package/dist/lib/interceptor/InterceptorManager.d.ts +127 -0
  60. package/dist/lib/interceptor/InterceptorManager.d.ts.map +1 -0
  61. package/dist/lib/interceptor/InterceptorManager.js +125 -0
  62. package/dist/lib/interceptor/InterceptorManager.js.map +1 -0
  63. package/dist/lib/interceptor/index.d.ts +2 -0
  64. package/dist/lib/interceptor/index.d.ts.map +1 -0
  65. package/dist/lib/interceptor/index.js +2 -0
  66. package/dist/lib/interceptor/index.js.map +1 -0
  67. package/dist/lib/value-presence/ValuePresence.d.ts +123 -0
  68. package/dist/lib/value-presence/ValuePresence.d.ts.map +1 -0
  69. package/dist/lib/value-presence/ValuePresence.js +141 -0
  70. package/dist/lib/value-presence/ValuePresence.js.map +1 -0
  71. package/dist/lib/value-presence/index.d.ts +2 -0
  72. package/dist/lib/value-presence/index.d.ts.map +1 -0
  73. package/dist/lib/value-presence/index.js +2 -0
  74. package/dist/lib/value-presence/index.js.map +1 -0
  75. package/dist/personalization/PersonalizationBase.d.ts +184 -0
  76. package/dist/personalization/PersonalizationBase.d.ts.map +1 -0
  77. package/dist/personalization/PersonalizationBase.js +76 -0
  78. package/dist/personalization/PersonalizationBase.js.map +1 -0
  79. package/dist/personalization/PersonalizationStateful.d.ts +226 -0
  80. package/dist/personalization/PersonalizationStateful.d.ts.map +1 -0
  81. package/dist/personalization/PersonalizationStateful.js +297 -0
  82. package/dist/personalization/PersonalizationStateful.js.map +1 -0
  83. package/dist/personalization/PersonalizationStateless.d.ts +74 -0
  84. package/dist/personalization/PersonalizationStateless.d.ts.map +1 -0
  85. package/dist/personalization/PersonalizationStateless.js +98 -0
  86. package/dist/personalization/PersonalizationStateless.js.map +1 -0
  87. package/dist/personalization/index.d.ts +6 -0
  88. package/dist/personalization/index.d.ts.map +1 -0
  89. package/dist/personalization/index.js +6 -0
  90. package/dist/personalization/index.js.map +1 -0
  91. package/dist/personalization/resolvers/FlagsResolver.d.ts +35 -0
  92. package/dist/personalization/resolvers/FlagsResolver.d.ts.map +1 -0
  93. package/dist/personalization/resolvers/FlagsResolver.js +47 -0
  94. package/dist/personalization/resolvers/FlagsResolver.js.map +1 -0
  95. package/dist/personalization/resolvers/MergeTagValueResolver.d.ts +74 -0
  96. package/dist/personalization/resolvers/MergeTagValueResolver.d.ts.map +1 -0
  97. package/dist/personalization/resolvers/MergeTagValueResolver.js +109 -0
  98. package/dist/personalization/resolvers/MergeTagValueResolver.js.map +1 -0
  99. package/dist/personalization/resolvers/PersonalizedEntryResolver.d.ts +142 -0
  100. package/dist/personalization/resolvers/PersonalizedEntryResolver.d.ts.map +1 -0
  101. package/dist/personalization/resolvers/PersonalizedEntryResolver.js +196 -0
  102. package/dist/personalization/resolvers/PersonalizedEntryResolver.js.map +1 -0
  103. package/dist/personalization/resolvers/index.d.ts +7 -0
  104. package/dist/personalization/resolvers/index.d.ts.map +1 -0
  105. package/dist/personalization/resolvers/index.js +7 -0
  106. package/dist/personalization/resolvers/index.js.map +1 -0
  107. package/dist/signals.d.ts +35 -0
  108. package/dist/signals.d.ts.map +1 -0
  109. package/dist/signals.js +30 -0
  110. package/dist/signals.js.map +1 -0
  111. package/package.json +29 -0
@@ -0,0 +1,297 @@
1
+ import { ExperienceEvent as PersonalizationEvent, } from '@contentful/optimization-api-client';
2
+ import { isEqual } from 'es-toolkit';
3
+ import { createScopedLogger } from 'logger';
4
+ import { guardedBy } from '../lib/decorators';
5
+ import { batch, changes as changesSignal, consent as consentSignal, effect, event as eventSignal, flags as flagsSignal, online as onlineSignal, personalizations as personalizationsSignal, profile as profileSignal, toObservable, } from '../signals';
6
+ import PersonalizationBase from './PersonalizationBase';
7
+ const logger = createScopedLogger('Personalization');
8
+ /**
9
+ * Stateful personalization product that manages consent, profile, flags, and
10
+ * selected variants while emitting Experience events and updating state.
11
+ *
12
+ * @public
13
+ * @remarks
14
+ * The class maintains reactive signals and exposes read‑only observables via
15
+ * {@link PersonalizationStateful.states}. Events are validated via schema parsers and
16
+ * run through interceptors before being submitted. Resulting state is merged
17
+ * back into signals.
18
+ */
19
+ class PersonalizationStateful extends PersonalizationBase {
20
+ /** In‑memory queue for offline events keyed by profile. */
21
+ offlineQueue = new Set();
22
+ /** Exposed observable state references. */
23
+ states = {
24
+ eventStream: toObservable(eventSignal),
25
+ flags: toObservable(flagsSignal),
26
+ profile: toObservable(profileSignal),
27
+ personalizations: toObservable(personalizationsSignal),
28
+ };
29
+ /**
30
+ * Function that provides an anonymous ID when available.
31
+ *
32
+ * @internal
33
+ */
34
+ getAnonymousId;
35
+ /**
36
+ * Create a new stateful personalization instance.
37
+ *
38
+ * @param options - Options to configure the personalization product for stateful environments.
39
+ */
40
+ constructor(options) {
41
+ const { api, builder, config, interceptors } = options;
42
+ super({ api, builder, config, interceptors });
43
+ const { defaults, getAnonymousId } = config ?? {};
44
+ if (defaults) {
45
+ const { changes: defaultChanges, personalizations: defaultPersonalizations, profile: defaultProfile, } = defaults;
46
+ batch(() => {
47
+ changesSignal.value = defaultChanges;
48
+ personalizationsSignal.value = defaultPersonalizations;
49
+ profileSignal.value = defaultProfile;
50
+ });
51
+ }
52
+ if (defaults?.consent !== undefined) {
53
+ const { consent: defaultConsent } = defaults;
54
+ consentSignal.value = defaultConsent;
55
+ }
56
+ this.getAnonymousId = getAnonymousId ?? (() => undefined);
57
+ // Log signal changes for observability
58
+ effect(() => {
59
+ logger.debug(`Profile ${profileSignal.value && `with ID ${profileSignal.value.id}`} has been ${profileSignal.value ? 'set' : 'cleared'}`);
60
+ });
61
+ effect(() => {
62
+ logger.debug(`Variants have been ${personalizationsSignal.value?.length ? 'populated' : 'cleared'}`);
63
+ });
64
+ effect(() => {
65
+ logger.info(`Personalization ${consentSignal.value ? 'will' : 'will not'} take effect due to consent (${consentSignal.value})`);
66
+ });
67
+ effect(() => {
68
+ if (onlineSignal.value)
69
+ void this.flush();
70
+ });
71
+ }
72
+ /**
73
+ * Reset stateful signals managed by this product.
74
+ *
75
+ * @remarks
76
+ * Clears `changes`, `profile`, and selected `personalizations`.
77
+ */
78
+ reset() {
79
+ batch(() => {
80
+ changesSignal.value = undefined;
81
+ eventSignal.value = undefined;
82
+ profileSignal.value = undefined;
83
+ personalizationsSignal.value = undefined;
84
+ });
85
+ }
86
+ /**
87
+ * Get the specified Custom Flag's value (derived from the signal).
88
+ * @param name - The name or key of the Custom Flag.
89
+ * @returns The current value of the Custom Flag if found.
90
+ * */
91
+ getCustomFlag(name, changes = changesSignal.value) {
92
+ return super.getCustomFlag(name, changes);
93
+ }
94
+ /**
95
+ * Resolve a Contentful entry to a personalized variant using the current
96
+ * or provided selections.
97
+ *
98
+ * @typeParam S - Entry skeleton type.
99
+ * @typeParam M - Chain modifiers.
100
+ * @typeParam L - Locale code.
101
+ * @param entry - The entry to personalize.
102
+ * @param personalizations - Optional selections; defaults to the current signal value.
103
+ * @returns The resolved entry data.
104
+ */
105
+ personalizeEntry(entry, personalizations = personalizationsSignal.value) {
106
+ return super.personalizeEntry(entry, personalizations);
107
+ }
108
+ /**
109
+ * Resolve a merge tag to a value based on the current (or provided) profile.
110
+ *
111
+ * @param embeddedEntryNodeTarget - The merge‑tag entry node to resolve.
112
+ * @param profile - Optional profile; defaults to the current signal value.
113
+ * @returns The resolved value (type depends on the tag).
114
+ * @remarks
115
+ * Merge tags are references to profile data that can be substituted into content.
116
+ */
117
+ getMergeTagValue(embeddedEntryNodeTarget, profile = profileSignal.value) {
118
+ return super.getMergeTagValue(embeddedEntryNodeTarget, profile);
119
+ }
120
+ /**
121
+ * Determine whether the named operation is permitted based on consent and
122
+ * allowed event type configuration.
123
+ *
124
+ * @param name - Method name; `trackComponentView` is normalized to
125
+ * `'component'` for allow‑list checks.
126
+ * @returns `true` if the operation is permitted; otherwise `false`.
127
+ */
128
+ hasConsent(name) {
129
+ return (!!consentSignal.value ||
130
+ (this.allowedEventTypes ?? []).includes(name === 'trackComponentView' || name === 'trackFlagView' ? 'component' : name));
131
+ }
132
+ /**
133
+ * Hook invoked when an operation is blocked due to missing consent.
134
+ *
135
+ * @param name - The blocked operation name.
136
+ * @param payload - The original arguments supplied to the operation.
137
+ */
138
+ onBlockedByConsent(name, payload) {
139
+ logger.warn(`Event "${name}" was blocked due to lack of consent; payload: ${JSON.stringify(payload)}`);
140
+ }
141
+ /**
142
+ * Guard used to suppress duplicate component view events for the same
143
+ * component based on a duplication key and the component identifier.
144
+ *
145
+ * @param _name - Operation name (unused).
146
+ * @param payload - Tuple `[builderArgs, duplicationScope]`.
147
+ * @returns `true` if the event is NOT a duplicate and should proceed.
148
+ */
149
+ isNotDuplicated(_name, payload) {
150
+ const [{ componentId: value }, duplicationScope] = payload;
151
+ const isDuplicated = this.duplicationDetector.isPresent(duplicationScope, value);
152
+ if (!isDuplicated)
153
+ this.duplicationDetector.addValue(duplicationScope, value);
154
+ return !isDuplicated;
155
+ }
156
+ /**
157
+ * Hook invoked when an operation is blocked by the duplication guard.
158
+ *
159
+ * @param _name - The blocked operation name (unused).
160
+ * @param payload - The original arguments supplied to the operation.
161
+ */
162
+ onBlockedByDuplication(_name, payload) {
163
+ logger.debug(`Duplicate "component view" event detected, skipping; payload: ${JSON.stringify(payload)}`);
164
+ }
165
+ /**
166
+ * Identify the current profile/visitor to associate traits with a profile
167
+ * and update optimization state.
168
+ *
169
+ * @param payload - Identify builder payload.
170
+ * @returns The resulting {@link OptimizationData} for the identified user.
171
+ */
172
+ @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })
173
+ async identify(payload) {
174
+ logger.info('Sending "identify" event');
175
+ const event = this.builder.buildIdentify(payload);
176
+ return await this.sendOrEnqueueEvent(event);
177
+ }
178
+ /**
179
+ * Record a page view and update optimization state.
180
+ *
181
+ * @param payload - Page view builder payload.
182
+ * @returns The evaluated {@link OptimizationData} for this page view.
183
+ */
184
+ @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })
185
+ async page(payload) {
186
+ logger.info('Sending "page" event');
187
+ const event = this.builder.buildPageView(payload);
188
+ return await this.sendOrEnqueueEvent(event);
189
+ }
190
+ /**
191
+ * Record a screen view and update optimization state.
192
+ *
193
+ * @param payload - Screen view builder payload.
194
+ * @returns The evaluated {@link OptimizationData} for this screen view.
195
+ */
196
+ @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })
197
+ async screen(payload) {
198
+ logger.info(`Sending "screen" event for "${payload.name}"`);
199
+ const event = this.builder.buildScreenView(payload);
200
+ return await this.sendOrEnqueueEvent(event);
201
+ }
202
+ /**
203
+ * Record a custom track event and update optimization state.
204
+ *
205
+ * @param payload - Track builder payload.
206
+ * @returns The evaluated {@link OptimizationData} for this event.
207
+ */
208
+ @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })
209
+ async track(payload) {
210
+ logger.info(`Sending "track" event "${payload.event}"`);
211
+ const event = this.builder.buildTrack(payload);
212
+ return await this.sendOrEnqueueEvent(event);
213
+ }
214
+ @guardedBy('isNotDuplicated', { onBlocked: 'onBlockedByDuplication' })
215
+ @guardedBy('hasConsent', { onBlocked: 'onBlockedByConsent' })
216
+ /**
217
+ * Record a "sticky" component view and update optimization state.
218
+ *
219
+ * @param payload - Component view builder payload.
220
+ * @param _duplicationScope - Optional duplication scope key used to suppress duplicates.
221
+ * @returns The evaluated {@link OptimizationData} for this component view.
222
+ */
223
+ async trackComponentView(payload, _duplicationScope = '') {
224
+ logger.info(`Sending "track personalization" event for ${payload.componentId}`);
225
+ const event = this.builder.buildComponentView(payload);
226
+ return await this.sendOrEnqueueEvent(event);
227
+ }
228
+ /**
229
+ * Intercept, validate, and place an event into the offline eventd queue; then
230
+ * trigger a size‑based flush if necessary.
231
+ *
232
+ * @param event - The event to enqueue.
233
+ */
234
+ async sendOrEnqueueEvent(event) {
235
+ const intercepted = await this.interceptors.event.run(event);
236
+ const validEvent = PersonalizationEvent.parse(intercepted);
237
+ eventSignal.value = validEvent;
238
+ if (onlineSignal.value)
239
+ return await this.upsertProfile([validEvent]);
240
+ logger.debug(`Queueing ${validEvent.type} event`, validEvent);
241
+ this.offlineQueue.add(validEvent);
242
+ return undefined;
243
+ }
244
+ /**
245
+ * Flush the offline queue
246
+ */
247
+ async flush() {
248
+ if (this.offlineQueue.size === 0)
249
+ return;
250
+ logger.debug('Flushing offline event queue');
251
+ await this.upsertProfile(Array.from(this.offlineQueue));
252
+ this.offlineQueue.clear();
253
+ }
254
+ /**
255
+ * Submit events to the Experience API, updating output signals with the
256
+ * returned state.
257
+ *
258
+ * @param events - The events to submit.
259
+ * @returns The {@link OptimizationData} returned by the service.
260
+ * @internal
261
+ * @privateRemarks
262
+ * If a `getAnonymousId` function has been provided, the returned value will
263
+ * take precedence over the `id` property of the current {@link Profile}
264
+ * signal value
265
+ */
266
+ async upsertProfile(events) {
267
+ const anonymousId = this.getAnonymousId();
268
+ if (anonymousId)
269
+ logger.debug(`Anonymous ID found: ${anonymousId}`);
270
+ const data = await this.api.experience.upsertProfile({
271
+ profileId: anonymousId ?? profileSignal.value?.id,
272
+ events,
273
+ });
274
+ await this.updateOutputSignals(data);
275
+ return data;
276
+ }
277
+ /**
278
+ * Apply returned optimization state to local signals after interceptor processing.
279
+ *
280
+ * @param data - Optimization state returned by the service.
281
+ * @internal
282
+ */
283
+ async updateOutputSignals(data) {
284
+ const intercepted = await this.interceptors.state.run(data);
285
+ const { changes, personalizations, profile } = intercepted;
286
+ batch(() => {
287
+ if (!isEqual(changesSignal.value, changes))
288
+ changesSignal.value = changes;
289
+ if (!isEqual(profileSignal.value, profile))
290
+ profileSignal.value = profile;
291
+ if (!isEqual(personalizationsSignal.value, personalizations))
292
+ personalizationsSignal.value = personalizations;
293
+ });
294
+ }
295
+ }
296
+ export default PersonalizationStateful;
297
+ //# sourceMappingURL=PersonalizationStateful.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PersonalizationStateful.js","sourceRoot":"","sources":["../../src/personalization/PersonalizationStateful.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import { type ComponentViewBuilderArgs, type IdentifyBuilderArgs, type OptimizationData, type PageViewBuilderArgs, type PartialProfile, type ScreenViewBuilderArgs, type TrackBuilderArgs } from '@contentful/optimization-api-client';
2
+ import PersonalizationBase from './PersonalizationBase';
3
+ /**
4
+ * Stateless personalization implementation that immediately validates and sends
5
+ * a single event to the Experience API, upserting the profile as needed.
6
+ *
7
+ * @public
8
+ * @remarks
9
+ * Each public method constructs a strongly-typed event via the shared builder,
10
+ * runs it through event interceptors, and performs a profile upsert using the
11
+ * Experience API. If an anonymous ID is available from the builder, it will be
12
+ * preferred as the `profileId` unless an explicit profile is provided.
13
+ */
14
+ declare class PersonalizationStateless extends PersonalizationBase {
15
+ /**
16
+ * Identify the current profile/visitor to associate traits with a profile.
17
+ *
18
+ * @param payload - Identify builder arguments with an optional partial
19
+ * profile to attach to the upsert request.
20
+ * @returns The resulting {@link OptimizationData} for the identified user.
21
+ */
22
+ identify(payload: IdentifyBuilderArgs & {
23
+ profile?: PartialProfile;
24
+ }): Promise<OptimizationData>;
25
+ /**
26
+ * Record a page view.
27
+ *
28
+ * @param payload - Page view builder arguments with an optional partial profile.
29
+ * @returns The evaluated {@link OptimizationData} for this page view.
30
+ */
31
+ page(payload: PageViewBuilderArgs & {
32
+ profile?: PartialProfile;
33
+ }): Promise<OptimizationData>;
34
+ /**
35
+ * Record a screen view.
36
+ *
37
+ * @param payload - Screen view builder arguments with an optional partial profile.
38
+ * @returns The evaluated {@link OptimizationData} for this screen view.
39
+ */
40
+ screen(payload: ScreenViewBuilderArgs & {
41
+ profile?: PartialProfile;
42
+ }): Promise<OptimizationData>;
43
+ /**
44
+ * Record a custom track event.
45
+ *
46
+ * @param payload - Track builder arguments with an optional partial profile.
47
+ * @returns The evaluated {@link OptimizationData} for this event.
48
+ */
49
+ track(payload: TrackBuilderArgs & {
50
+ profile?: PartialProfile;
51
+ }): Promise<OptimizationData>;
52
+ /**
53
+ * Record a "sticky" component view.
54
+ *
55
+ * @param payload - Component view builder arguments with an optional partial profile.
56
+ * @returns The evaluated {@link OptimizationData} for this component view.
57
+ */
58
+ trackComponentView(payload: ComponentViewBuilderArgs & {
59
+ profile?: PartialProfile;
60
+ }): Promise<OptimizationData>;
61
+ /**
62
+ * Intercept, validate, and upsert the profile with a single personalization
63
+ * event.
64
+ *
65
+ * @param event - The {@link PersonalizationEvent} to submit.
66
+ * @param profile - Optional partial profile. If omitted, the anonymous ID from
67
+ * the builder (when present) is used as the `profileId`.
68
+ * @returns The {@link OptimizationData} returned by the Experience API.
69
+ * @internal
70
+ */
71
+ private upsertProfile;
72
+ }
73
+ export default PersonalizationStateless;
74
+ //# sourceMappingURL=PersonalizationStateless.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PersonalizationStateless.d.ts","sourceRoot":"","sources":["../../src/personalization/PersonalizationStateless.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,wBAAwB,EAE7B,KAAK,mBAAmB,EAExB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EAExB,KAAK,cAAc,EAEnB,KAAK,qBAAqB,EAE1B,KAAK,gBAAgB,EAEtB,MAAM,qCAAqC,CAAA;AAE5C,OAAO,mBAAmB,MAAM,uBAAuB,CAAA;AAIvD;;;;;;;;;;GAUG;AACH,cAAM,wBAAyB,SAAQ,mBAAmB;IACxD;;;;;;OAMG;IACG,QAAQ,CACZ,OAAO,EAAE,mBAAmB,GAAG;QAAE,OAAO,CAAC,EAAE,cAAc,CAAA;KAAE,GAC1D,OAAO,CAAC,gBAAgB,CAAC;IAU5B;;;;;OAKG;IACG,IAAI,CACR,OAAO,EAAE,mBAAmB,GAAG;QAAE,OAAO,CAAC,EAAE,cAAc,CAAA;KAAE,GAC1D,OAAO,CAAC,gBAAgB,CAAC;IAU5B;;;;;OAKG;IACG,MAAM,CACV,OAAO,EAAE,qBAAqB,GAAG;QAAE,OAAO,CAAC,EAAE,cAAc,CAAA;KAAE,GAC5D,OAAO,CAAC,gBAAgB,CAAC;IAU5B;;;;;OAKG;IACG,KAAK,CAAC,OAAO,EAAE,gBAAgB,GAAG;QAAE,OAAO,CAAC,EAAE,cAAc,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAUhG;;;;;OAKG;IACG,kBAAkB,CACtB,OAAO,EAAE,wBAAwB,GAAG;QAAE,OAAO,CAAC,EAAE,cAAc,CAAA;KAAE,GAC/D,OAAO,CAAC,gBAAgB,CAAC;IAU5B;;;;;;;;;OASG;YACW,aAAa;CAa5B;AAED,eAAe,wBAAwB,CAAA"}
@@ -0,0 +1,98 @@
1
+ import { ComponentViewEvent, IdentifyEvent, PageViewEvent, ScreenViewEvent, TrackEvent, } from '@contentful/optimization-api-client';
2
+ import { createScopedLogger } from 'logger';
3
+ import PersonalizationBase from './PersonalizationBase';
4
+ const logger = createScopedLogger('Personalization');
5
+ /**
6
+ * Stateless personalization implementation that immediately validates and sends
7
+ * a single event to the Experience API, upserting the profile as needed.
8
+ *
9
+ * @public
10
+ * @remarks
11
+ * Each public method constructs a strongly-typed event via the shared builder,
12
+ * runs it through event interceptors, and performs a profile upsert using the
13
+ * Experience API. If an anonymous ID is available from the builder, it will be
14
+ * preferred as the `profileId` unless an explicit profile is provided.
15
+ */
16
+ class PersonalizationStateless extends PersonalizationBase {
17
+ /**
18
+ * Identify the current profile/visitor to associate traits with a profile.
19
+ *
20
+ * @param payload - Identify builder arguments with an optional partial
21
+ * profile to attach to the upsert request.
22
+ * @returns The resulting {@link OptimizationData} for the identified user.
23
+ */
24
+ async identify(payload) {
25
+ logger.info('Sending "identify" event');
26
+ const { profile, ...builderArgs } = payload;
27
+ const event = IdentifyEvent.parse(this.builder.buildIdentify(builderArgs));
28
+ return await this.upsertProfile(event, profile);
29
+ }
30
+ /**
31
+ * Record a page view.
32
+ *
33
+ * @param payload - Page view builder arguments with an optional partial profile.
34
+ * @returns The evaluated {@link OptimizationData} for this page view.
35
+ */
36
+ async page(payload) {
37
+ logger.info('Sending "page" event');
38
+ const { profile, ...builderArgs } = payload;
39
+ const event = PageViewEvent.parse(this.builder.buildPageView(builderArgs));
40
+ return await this.upsertProfile(event, profile);
41
+ }
42
+ /**
43
+ * Record a screen view.
44
+ *
45
+ * @param payload - Screen view builder arguments with an optional partial profile.
46
+ * @returns The evaluated {@link OptimizationData} for this screen view.
47
+ */
48
+ async screen(payload) {
49
+ logger.info(`Sending "screen" event for "${payload.name}"`);
50
+ const { profile, ...builderArgs } = payload;
51
+ const event = ScreenViewEvent.parse(this.builder.buildScreenView(builderArgs));
52
+ return await this.upsertProfile(event, profile);
53
+ }
54
+ /**
55
+ * Record a custom track event.
56
+ *
57
+ * @param payload - Track builder arguments with an optional partial profile.
58
+ * @returns The evaluated {@link OptimizationData} for this event.
59
+ */
60
+ async track(payload) {
61
+ logger.info(`Sending "track" event "${payload.event}"`);
62
+ const { profile, ...builderArgs } = payload;
63
+ const event = TrackEvent.parse(this.builder.buildTrack(builderArgs));
64
+ return await this.upsertProfile(event, profile);
65
+ }
66
+ /**
67
+ * Record a "sticky" component view.
68
+ *
69
+ * @param payload - Component view builder arguments with an optional partial profile.
70
+ * @returns The evaluated {@link OptimizationData} for this component view.
71
+ */
72
+ async trackComponentView(payload) {
73
+ logger.info('Sending "track personalization" event');
74
+ const { profile, ...builderArgs } = payload;
75
+ const event = ComponentViewEvent.parse(this.builder.buildComponentView(builderArgs));
76
+ return await this.upsertProfile(event, profile);
77
+ }
78
+ /**
79
+ * Intercept, validate, and upsert the profile with a single personalization
80
+ * event.
81
+ *
82
+ * @param event - The {@link PersonalizationEvent} to submit.
83
+ * @param profile - Optional partial profile. If omitted, the anonymous ID from
84
+ * the builder (when present) is used as the `profileId`.
85
+ * @returns The {@link OptimizationData} returned by the Experience API.
86
+ * @internal
87
+ */
88
+ async upsertProfile(event, profile) {
89
+ const intercepted = await this.interceptors.event.run(event);
90
+ const data = await this.api.experience.upsertProfile({
91
+ profileId: profile?.id,
92
+ events: [intercepted],
93
+ });
94
+ return data;
95
+ }
96
+ }
97
+ export default PersonalizationStateless;
98
+ //# sourceMappingURL=PersonalizationStateless.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PersonalizationStateless.js","sourceRoot":"","sources":["../../src/personalization/PersonalizationStateless.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export * from './resolvers';
2
+ export * from './PersonalizationStateful';
3
+ export { default as PersonalizationStateful } from './PersonalizationStateful';
4
+ export * from './PersonalizationStateless';
5
+ export { default as PersonalizationStateless } from './PersonalizationStateless';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/personalization/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAE3B,cAAc,2BAA2B,CAAA;AACzC,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAA;AAE9E,cAAc,4BAA4B,CAAA;AAC1C,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAA"}
@@ -0,0 +1,6 @@
1
+ export * from './resolvers';
2
+ export * from './PersonalizationStateful';
3
+ export { default as PersonalizationStateful } from './PersonalizationStateful';
4
+ export * from './PersonalizationStateless';
5
+ export { default as PersonalizationStateless } from './PersonalizationStateless';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/personalization/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAE3B,cAAc,2BAA2B,CAAA;AACzC,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAA;AAE9E,cAAc,4BAA4B,CAAA;AAC1C,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAA"}
@@ -0,0 +1,35 @@
1
+ import type { ChangeArray, Flags } from '@contentful/optimization-api-client';
2
+ /**
3
+ * Resolves a {@link Flags} map from a list of optimization changes.
4
+ *
5
+ * @public
6
+ * @remarks
7
+ * Given an Optimization {@link ChangeArray}, this utility flattens the list into a
8
+ * simple key–value object suitable for quick lookups in client code. When `changes`
9
+ * is `undefined`, an empty object is returned. If a change value is wrapped in an
10
+ * object like `{ value: { ... } }`, this resolver unwraps it to the underlying object.
11
+ */
12
+ declare const FlagsResolver: {
13
+ /**
14
+ * Build a flattened map of flag keys to values from a change list.
15
+ *
16
+ * @param changes - The change list returned by the optimization service.
17
+ * @returns A map of flag keys to their resolved values.
18
+ * @example
19
+ * ```ts
20
+ * const flags = FlagsResolver.resolve(data.changes)
21
+ * if (flags['theme'] === 'dark') enableDarkMode()
22
+ * ```
23
+ * @example
24
+ * // Handles wrapped values produced by the API
25
+ * ```ts
26
+ * const flags = FlagsResolver.resolve([
27
+ * { type: 'Variable', key: 'price', value: { value: { amount: 10, currency: 'USD' } } }
28
+ * ])
29
+ * console.log(flags.price.amount) // 10
30
+ * ```
31
+ */
32
+ resolve(changes?: ChangeArray): Flags;
33
+ };
34
+ export default FlagsResolver;
35
+ //# sourceMappingURL=FlagsResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FlagsResolver.d.ts","sourceRoot":"","sources":["../../../src/personalization/resolvers/FlagsResolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,qCAAqC,CAAA;AAE7E;;;;;;;;;GASG;AACH,QAAA,MAAM,aAAa;IACjB;;;;;;;;;;;;;;;;;;OAkBG;sBACe,WAAW,GAAG,KAAK;CAiBtC,CAAA;AAED,eAAe,aAAa,CAAA"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Resolves a {@link Flags} map from a list of optimization changes.
3
+ *
4
+ * @public
5
+ * @remarks
6
+ * Given an Optimization {@link ChangeArray}, this utility flattens the list into a
7
+ * simple key–value object suitable for quick lookups in client code. When `changes`
8
+ * is `undefined`, an empty object is returned. If a change value is wrapped in an
9
+ * object like `{ value: { ... } }`, this resolver unwraps it to the underlying object.
10
+ */
11
+ const FlagsResolver = {
12
+ /**
13
+ * Build a flattened map of flag keys to values from a change list.
14
+ *
15
+ * @param changes - The change list returned by the optimization service.
16
+ * @returns A map of flag keys to their resolved values.
17
+ * @example
18
+ * ```ts
19
+ * const flags = FlagsResolver.resolve(data.changes)
20
+ * if (flags['theme'] === 'dark') enableDarkMode()
21
+ * ```
22
+ * @example
23
+ * // Handles wrapped values produced by the API
24
+ * ```ts
25
+ * const flags = FlagsResolver.resolve([
26
+ * { type: 'Variable', key: 'price', value: { value: { amount: 10, currency: 'USD' } } }
27
+ * ])
28
+ * console.log(flags.price.amount) // 10
29
+ * ```
30
+ */
31
+ resolve(changes) {
32
+ if (!changes)
33
+ return {};
34
+ return changes.reduce((acc, { key, value }) => {
35
+ const actualValue = typeof value === 'object' &&
36
+ value !== null &&
37
+ 'value' in value &&
38
+ typeof value.value === 'object'
39
+ ? value.value
40
+ : value;
41
+ acc[key] = actualValue;
42
+ return acc;
43
+ }, {});
44
+ },
45
+ };
46
+ export default FlagsResolver;
47
+ //# sourceMappingURL=FlagsResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FlagsResolver.js","sourceRoot":"","sources":["../../../src/personalization/resolvers/FlagsResolver.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,aAAa,GAAG;IACpB;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,CAAC,OAAqB;QAC3B,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,CAAA;QAEvB,OAAO,OAAO,CAAC,MAAM,CAAQ,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;YACnD,MAAM,WAAW,GACf,OAAO,KAAK,KAAK,QAAQ;gBACzB,KAAK,KAAK,IAAI;gBACd,OAAO,IAAI,KAAK;gBAChB,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;gBAC7B,CAAC,CAAC,KAAK,CAAC,KAAK;gBACb,CAAC,CAAC,KAAK,CAAA;YAEX,GAAG,CAAC,GAAG,CAAC,GAAG,WAAW,CAAA;YAEtB,OAAO,GAAG,CAAA;QACZ,CAAC,EAAE,EAAE,CAAC,CAAA;IACR,CAAC;CACF,CAAA;AAED,eAAe,aAAa,CAAA"}