@contentful/optimization-api-client 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 (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +282 -0
  3. package/dist/ApiClient.d.ts +74 -0
  4. package/dist/ApiClient.d.ts.map +1 -0
  5. package/dist/ApiClient.js +61 -0
  6. package/dist/ApiClient.js.map +1 -0
  7. package/dist/ApiClientBase.d.ts +113 -0
  8. package/dist/ApiClientBase.d.ts.map +1 -0
  9. package/dist/ApiClientBase.js +94 -0
  10. package/dist/ApiClientBase.js.map +1 -0
  11. package/dist/builders/EventBuilder.d.ts +589 -0
  12. package/dist/builders/EventBuilder.d.ts.map +1 -0
  13. package/dist/builders/EventBuilder.js +349 -0
  14. package/dist/builders/EventBuilder.js.map +1 -0
  15. package/dist/builders/index.d.ts +3 -0
  16. package/dist/builders/index.d.ts.map +1 -0
  17. package/dist/builders/index.js +3 -0
  18. package/dist/builders/index.js.map +1 -0
  19. package/dist/experience/ExperienceApiClient.d.ts +267 -0
  20. package/dist/experience/ExperienceApiClient.d.ts.map +1 -0
  21. package/dist/experience/ExperienceApiClient.js +324 -0
  22. package/dist/experience/ExperienceApiClient.js.map +1 -0
  23. package/dist/experience/index.d.ts +4 -0
  24. package/dist/experience/index.d.ts.map +1 -0
  25. package/dist/experience/index.js +4 -0
  26. package/dist/experience/index.js.map +1 -0
  27. package/dist/fetch/Fetch.d.ts +96 -0
  28. package/dist/fetch/Fetch.d.ts.map +1 -0
  29. package/dist/fetch/Fetch.js +27 -0
  30. package/dist/fetch/Fetch.js.map +1 -0
  31. package/dist/fetch/createProtectedFetchMethod.d.ts +40 -0
  32. package/dist/fetch/createProtectedFetchMethod.d.ts.map +1 -0
  33. package/dist/fetch/createProtectedFetchMethod.js +53 -0
  34. package/dist/fetch/createProtectedFetchMethod.js.map +1 -0
  35. package/dist/fetch/createRetryFetchMethod.d.ts +60 -0
  36. package/dist/fetch/createRetryFetchMethod.d.ts.map +1 -0
  37. package/dist/fetch/createRetryFetchMethod.js +138 -0
  38. package/dist/fetch/createRetryFetchMethod.js.map +1 -0
  39. package/dist/fetch/createTimeoutFetchMethod.d.ts +51 -0
  40. package/dist/fetch/createTimeoutFetchMethod.d.ts.map +1 -0
  41. package/dist/fetch/createTimeoutFetchMethod.js +51 -0
  42. package/dist/fetch/createTimeoutFetchMethod.js.map +1 -0
  43. package/dist/fetch/index.d.ts +7 -0
  44. package/dist/fetch/index.d.ts.map +1 -0
  45. package/dist/fetch/index.js +7 -0
  46. package/dist/fetch/index.js.map +1 -0
  47. package/dist/index.cjs +708 -0
  48. package/dist/index.cjs.map +1 -0
  49. package/dist/index.d.ts +8 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +8 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/index.mjs +583 -0
  54. package/dist/index.mjs.map +1 -0
  55. package/dist/insights/InsightsApiClient.d.ts +130 -0
  56. package/dist/insights/InsightsApiClient.d.ts.map +1 -0
  57. package/dist/insights/InsightsApiClient.js +142 -0
  58. package/dist/insights/InsightsApiClient.js.map +1 -0
  59. package/dist/insights/index.d.ts +4 -0
  60. package/dist/insights/index.d.ts.map +1 -0
  61. package/dist/insights/index.js +4 -0
  62. package/dist/insights/index.js.map +1 -0
  63. package/package.json +27 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,583 @@
1
+ import * as __rspack_external__contentful_optimization_api_schemas_66dcf407 from "@contentful/optimization-api-schemas";
2
+ import { diary, enable } from "diary";
3
+ import "diary/utils";
4
+ import p_retry from "p-retry";
5
+ import { merge } from "es-toolkit";
6
+ import { boolean as mini_boolean, extend, number, object, optional, partial, prefault, string } from "zod/mini";
7
+ class Logger {
8
+ name = '@contentful/optimization';
9
+ PREFIX_PARTS = [
10
+ 'Ctfl',
11
+ 'O10n'
12
+ ];
13
+ DELIMITER = ':';
14
+ diary;
15
+ sinks = [];
16
+ constructor(){
17
+ this.diary = diary(this.name, this.onLogEvent.bind(this));
18
+ enable(this.name);
19
+ }
20
+ assembleLocationPrefix(logLocation) {
21
+ return `[${[
22
+ ...this.PREFIX_PARTS,
23
+ logLocation
24
+ ].join(this.DELIMITER)}]`;
25
+ }
26
+ addSink(sink) {
27
+ this.sinks = [
28
+ ...this.sinks.filter((existingSink)=>existingSink.name !== sink.name),
29
+ sink
30
+ ];
31
+ }
32
+ removeSink(name) {
33
+ this.sinks = this.sinks.filter((sink)=>sink.name !== name);
34
+ }
35
+ removeSinks() {
36
+ this.sinks = [];
37
+ }
38
+ debug(logLocation, message, ...args) {
39
+ this.diary.debug(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args);
40
+ }
41
+ info(logLocation, message, ...args) {
42
+ this.diary.info(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args);
43
+ }
44
+ log(logLocation, message, ...args) {
45
+ this.diary.log(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args);
46
+ }
47
+ warn(logLocation, message, ...args) {
48
+ this.diary.warn(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args);
49
+ }
50
+ error(logLocation, message, ...args) {
51
+ this.diary.error(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args);
52
+ }
53
+ fatal(logLocation, message, ...args) {
54
+ this.diary.fatal(`${this.assembleLocationPrefix(logLocation)} ${message}`, ...args);
55
+ }
56
+ onLogEvent(event) {
57
+ this.sinks.forEach((sink)=>{
58
+ sink.ingest(event);
59
+ });
60
+ }
61
+ }
62
+ const logger = new Logger();
63
+ function createScopedLogger(location) {
64
+ return {
65
+ debug: (message, ...args)=>{
66
+ logger.debug(location, message, ...args);
67
+ },
68
+ info: (message, ...args)=>{
69
+ logger.info(location, message, ...args);
70
+ },
71
+ log: (message, ...args)=>{
72
+ logger.log(location, message, ...args);
73
+ },
74
+ warn: (message, ...args)=>{
75
+ logger.warn(location, message, ...args);
76
+ },
77
+ error: (message, ...args)=>{
78
+ logger.error(location, message, ...args);
79
+ },
80
+ fatal: (message, ...args)=>{
81
+ logger.fatal(location, message, ...args);
82
+ }
83
+ };
84
+ }
85
+ const createRetryFetchMethod_logger = createScopedLogger('ApiClient:Retry');
86
+ const DEFAULT_INTERVAL_TIMEOUT = 0;
87
+ const DEFAULT_RETRY_COUNT = 1;
88
+ const RETRY_RESPONSE_STATUS = 503;
89
+ const HTTP_ERROR_RESPONSE_STATUS = 500;
90
+ class HttpError extends Error {
91
+ status;
92
+ constructor(message, status = HTTP_ERROR_RESPONSE_STATUS){
93
+ super(message);
94
+ Object.setPrototypeOf(this, HttpError.prototype);
95
+ this.status = status;
96
+ }
97
+ }
98
+ function createRetryFetchCallback({ apiName = 'Optimization', controller, fetchMethod = fetch, init, url }) {
99
+ return async ()=>{
100
+ try {
101
+ const response = await fetchMethod(url, init);
102
+ if (response.status === RETRY_RESPONSE_STATUS) throw new HttpError(`${apiName} API request to "${url.toString()}" failed with status: "[${response.status}] ${response.statusText}".`, RETRY_RESPONSE_STATUS);
103
+ if (!response.ok) {
104
+ const httpError = new Error(`Request to "${url.toString()}" failed with status: [${response.status}] ${response.statusText} - traceparent: ${response.headers.get('traceparent')}`);
105
+ createRetryFetchMethod_logger.error('Request failed with non-OK status:', httpError);
106
+ controller.abort();
107
+ return;
108
+ }
109
+ createRetryFetchMethod_logger.debug(`Response from "${url.toString()}":`, response);
110
+ return response;
111
+ } catch (error) {
112
+ if (error instanceof HttpError && error.status === RETRY_RESPONSE_STATUS) throw error;
113
+ createRetryFetchMethod_logger.error(`Request to "${url.toString()}" failed:`, error);
114
+ controller.abort();
115
+ }
116
+ };
117
+ }
118
+ function createRetryFetchMethod({ apiName = 'Optimization', fetchMethod = fetch, intervalTimeout = DEFAULT_INTERVAL_TIMEOUT, onFailedAttempt, retries = DEFAULT_RETRY_COUNT } = {}) {
119
+ return async (url, init)=>{
120
+ const controller = new AbortController();
121
+ let retryResponse;
122
+ try {
123
+ retryResponse = await p_retry(createRetryFetchCallback({
124
+ apiName,
125
+ controller,
126
+ fetchMethod,
127
+ init,
128
+ url
129
+ }), {
130
+ minTimeout: intervalTimeout,
131
+ onFailedAttempt: (options)=>onFailedAttempt?.({
132
+ ...options,
133
+ apiName
134
+ }),
135
+ retries,
136
+ signal: controller.signal
137
+ });
138
+ } catch (error) {
139
+ if (!(error instanceof Error) || 'AbortError' !== error.name) throw error;
140
+ }
141
+ if (!retryResponse) throw new Error(`${apiName} API request to "${url.toString()}" may not be retried.`);
142
+ return retryResponse;
143
+ };
144
+ }
145
+ const createTimeoutFetchMethod_logger = createScopedLogger('ApiClient:Timeout');
146
+ const DEFAULT_REQUEST_TIMEOUT = 3000;
147
+ function createTimeoutFetchMethod({ apiName = 'Optimization', fetchMethod = fetch, onRequestTimeout, requestTimeout = DEFAULT_REQUEST_TIMEOUT } = {}) {
148
+ return async (url, init)=>{
149
+ const controller = new AbortController();
150
+ const id = setTimeout(()=>{
151
+ if ('function' == typeof onRequestTimeout) onRequestTimeout({
152
+ apiName
153
+ });
154
+ else createTimeoutFetchMethod_logger.error(`Request to "${url.toString()}" timed out`, new Error('Request timeout'));
155
+ controller.abort();
156
+ }, requestTimeout);
157
+ const response = await fetchMethod(url, {
158
+ ...init,
159
+ signal: controller.signal
160
+ });
161
+ clearTimeout(id);
162
+ return response;
163
+ };
164
+ }
165
+ const createProtectedFetchMethod_logger = createScopedLogger('ApiClient:Fetch');
166
+ function createProtectedFetchMethod(options) {
167
+ try {
168
+ const timeoutFetchMethod = createTimeoutFetchMethod(options);
169
+ const retryFetchMethod = createRetryFetchMethod({
170
+ ...options,
171
+ fetchMethod: timeoutFetchMethod
172
+ });
173
+ return retryFetchMethod;
174
+ } catch (error) {
175
+ if (error instanceof Error) if ('AbortError' === error.name) createProtectedFetchMethod_logger.warn('Request aborted due to network issues. This request may not be retried.');
176
+ else createProtectedFetchMethod_logger.error('Request failed:', error);
177
+ throw error;
178
+ }
179
+ }
180
+ const Fetch = {
181
+ create: createProtectedFetchMethod
182
+ };
183
+ const fetch_Fetch = Fetch;
184
+ const src_fetch = fetch_Fetch;
185
+ const ApiClientBase_logger = createScopedLogger('ApiClient');
186
+ const DEFAULT_ENVIRONMENT = 'main';
187
+ class ApiClientBase {
188
+ name;
189
+ clientId;
190
+ environment;
191
+ fetch;
192
+ constructor(name, { fetchOptions, clientId, environment }){
193
+ this.clientId = clientId;
194
+ this.environment = environment ?? DEFAULT_ENVIRONMENT;
195
+ this.name = name;
196
+ this.fetch = src_fetch.create({
197
+ ...fetchOptions ?? {},
198
+ apiName: name
199
+ });
200
+ }
201
+ logRequestError(error, { requestName }) {
202
+ if (error instanceof Error) if ('AbortError' === error.name) ApiClientBase_logger.warn(`[${this.name}] "${requestName}" request aborted due to network issues. This request may not be retried.`);
203
+ else ApiClientBase_logger.error(`[${this.name}] "${requestName}" request failed:`, error);
204
+ }
205
+ }
206
+ const src_ApiClientBase = ApiClientBase;
207
+ const ExperienceApiClient_logger = createScopedLogger('ApiClient:Experience');
208
+ const EXPERIENCE_BASE_URL = 'https://experience.ninetailed.co/';
209
+ class ExperienceApiClient extends src_ApiClientBase {
210
+ baseUrl;
211
+ enabledFeatures;
212
+ ip;
213
+ locale;
214
+ plainText;
215
+ preflight;
216
+ constructor(config){
217
+ super('Experience', config);
218
+ const { baseUrl, enabledFeatures, ip, locale, plainText, preflight } = config;
219
+ this.baseUrl = baseUrl || EXPERIENCE_BASE_URL;
220
+ this.enabledFeatures = enabledFeatures;
221
+ this.ip = ip;
222
+ this.locale = locale;
223
+ this.plainText = plainText;
224
+ this.preflight = preflight;
225
+ }
226
+ async getProfile(id, options = {}) {
227
+ if (!id) throw new Error('Valid profile ID required.');
228
+ const requestName = 'Get Profile';
229
+ ExperienceApiClient_logger.info(`Sending "${requestName}" request`);
230
+ try {
231
+ const response = await this.fetch(this.constructUrl(`v2/organizations/${this.clientId}/environments/${this.environment}/profiles/${id}`, options), {
232
+ method: 'GET'
233
+ });
234
+ const { data: { changes, experiences, profile } } = __rspack_external__contentful_optimization_api_schemas_66dcf407.ExperienceResponse.parse(await response.json());
235
+ const data = {
236
+ changes,
237
+ personalizations: experiences,
238
+ profile
239
+ };
240
+ ExperienceApiClient_logger.debug(`"${requestName}" request successfully completed`);
241
+ return data;
242
+ } catch (error) {
243
+ this.logRequestError(error, {
244
+ requestName
245
+ });
246
+ throw error;
247
+ }
248
+ }
249
+ async makeProfileMutationRequest({ url, body, options }) {
250
+ return await this.fetch(this.constructUrl(url, options), {
251
+ method: 'POST',
252
+ headers: this.constructHeaders(options),
253
+ body: JSON.stringify(body),
254
+ keepalive: true
255
+ });
256
+ }
257
+ async createProfile({ events }, options = {}) {
258
+ const requestName = 'Create Profile';
259
+ ExperienceApiClient_logger.info(`Sending "${requestName}" request`);
260
+ const body = {
261
+ events: __rspack_external__contentful_optimization_api_schemas_66dcf407.ExperienceEventArray.parse(events),
262
+ options: this.constructBodyOptions(options)
263
+ };
264
+ ExperienceApiClient_logger.debug(`"${requestName}" request body:`, body);
265
+ try {
266
+ const response = await this.makeProfileMutationRequest({
267
+ url: `v2/organizations/${this.clientId}/environments/${this.environment}/profiles`,
268
+ body,
269
+ options
270
+ });
271
+ const { data: { changes, experiences, profile } } = __rspack_external__contentful_optimization_api_schemas_66dcf407.ExperienceResponse.parse(await response.json());
272
+ const data = {
273
+ changes,
274
+ personalizations: experiences,
275
+ profile
276
+ };
277
+ ExperienceApiClient_logger.debug(`"${requestName}" request successfully completed`);
278
+ return data;
279
+ } catch (error) {
280
+ this.logRequestError(error, {
281
+ requestName
282
+ });
283
+ throw error;
284
+ }
285
+ }
286
+ async updateProfile({ profileId, events }, options = {}) {
287
+ if (!profileId) throw new Error('Valid profile ID required.');
288
+ const requestName = 'Update Profile';
289
+ ExperienceApiClient_logger.info(`Sending "${requestName}" request`);
290
+ const body = {
291
+ events: __rspack_external__contentful_optimization_api_schemas_66dcf407.ExperienceEventArray.parse(events),
292
+ options: this.constructBodyOptions(options)
293
+ };
294
+ ExperienceApiClient_logger.debug(`"${requestName}" request body:`, body);
295
+ try {
296
+ const response = await this.makeProfileMutationRequest({
297
+ url: `v2/organizations/${this.clientId}/environments/${this.environment}/profiles/${profileId}`,
298
+ body,
299
+ options
300
+ });
301
+ const { data: { changes, experiences, profile } } = __rspack_external__contentful_optimization_api_schemas_66dcf407.ExperienceResponse.parse(await response.json());
302
+ const data = {
303
+ changes,
304
+ personalizations: experiences,
305
+ profile
306
+ };
307
+ ExperienceApiClient_logger.debug(`"${requestName}" request successfully completed`);
308
+ return data;
309
+ } catch (error) {
310
+ this.logRequestError(error, {
311
+ requestName
312
+ });
313
+ throw error;
314
+ }
315
+ }
316
+ async upsertProfile({ profileId, events }, options) {
317
+ if (!profileId) return await this.createProfile({
318
+ events
319
+ }, options);
320
+ return await this.updateProfile({
321
+ profileId,
322
+ events
323
+ }, options);
324
+ }
325
+ async upsertManyProfiles({ events }, options = {}) {
326
+ const requestName = 'Upsert Many Profiles';
327
+ ExperienceApiClient_logger.info(`Sending "${requestName}" request`);
328
+ const body = {
329
+ events: __rspack_external__contentful_optimization_api_schemas_66dcf407.ExperienceEventArray.parse(events),
330
+ options: this.constructBodyOptions(options)
331
+ };
332
+ ExperienceApiClient_logger.debug(`"${requestName}" request body:`, body);
333
+ try {
334
+ const response = await this.makeProfileMutationRequest({
335
+ url: `v2/organizations/${this.clientId}/environments/${this.environment}/events`,
336
+ body,
337
+ options: {
338
+ plainText: false,
339
+ ...options
340
+ }
341
+ });
342
+ const { data: { profiles } } = __rspack_external__contentful_optimization_api_schemas_66dcf407.BatchExperienceResponse.parse(await response.json());
343
+ ExperienceApiClient_logger.debug(`"${requestName}" request successfully completed`);
344
+ return profiles;
345
+ } catch (error) {
346
+ this.logRequestError(error, {
347
+ requestName
348
+ });
349
+ throw error;
350
+ }
351
+ }
352
+ constructUrl(path, options) {
353
+ const url = new URL(path, this.baseUrl);
354
+ const locale = options.locale ?? this.locale;
355
+ const preflight = options.preflight ?? this.preflight;
356
+ if (locale) url.searchParams.set('locale', locale);
357
+ if (preflight) url.searchParams.set('type', 'preflight');
358
+ return url.toString();
359
+ }
360
+ constructHeaders({ ip = this.ip, plainText = this.plainText }) {
361
+ const headers = new Map();
362
+ if (ip) headers.set('X-Force-IP', ip);
363
+ if (plainText ?? this.plainText ?? true) headers.set('Content-Type', 'text/plain');
364
+ else headers.set('Content-Type', 'application/json');
365
+ return Object.fromEntries(headers);
366
+ }
367
+ constructBodyOptions = ({ enabledFeatures = this.enabledFeatures })=>{
368
+ const bodyOptions = {};
369
+ if (enabledFeatures && Array.isArray(enabledFeatures) && enabledFeatures.length > 0) bodyOptions.features = enabledFeatures;
370
+ else bodyOptions.features = [
371
+ 'ip-enrichment',
372
+ 'location'
373
+ ];
374
+ return bodyOptions;
375
+ };
376
+ }
377
+ const experience = ExperienceApiClient;
378
+ const InsightsApiClient_logger = createScopedLogger('ApiClient:Insights');
379
+ const INSIGHTS_BASE_URL = 'https://ingest.insights.ninetailed.co/';
380
+ class InsightsApiClient extends src_ApiClientBase {
381
+ baseUrl;
382
+ beaconHandler;
383
+ constructor(config){
384
+ super('Insights', config);
385
+ const { baseUrl, beaconHandler } = config;
386
+ this.baseUrl = baseUrl ?? INSIGHTS_BASE_URL;
387
+ this.beaconHandler = beaconHandler;
388
+ }
389
+ async sendBatchEvents(batches, options = {}) {
390
+ const { beaconHandler = this.beaconHandler } = options;
391
+ const url = new URL(`v1/organizations/${this.clientId}/environments/${this.environment}/events`, this.baseUrl);
392
+ const body = __rspack_external__contentful_optimization_api_schemas_66dcf407.BatchInsightsEventArray.parse(batches);
393
+ if ('function' == typeof beaconHandler) {
394
+ InsightsApiClient_logger.debug('Queueing events via beaconHandler');
395
+ const beaconSuccessfullyQueued = beaconHandler(url, body);
396
+ if (beaconSuccessfullyQueued) return true;
397
+ InsightsApiClient_logger.warn('beaconHandler failed to queue events; events will be emitted immediately via fetch');
398
+ }
399
+ const requestName = 'Event Batches';
400
+ InsightsApiClient_logger.info(`Sending "${requestName}" request`);
401
+ InsightsApiClient_logger.debug(`"${requestName}" request body:`, body);
402
+ try {
403
+ await this.fetch(url, {
404
+ method: 'POST',
405
+ headers: {
406
+ 'Content-Type': 'application/json'
407
+ },
408
+ body: JSON.stringify(body),
409
+ keepalive: true
410
+ });
411
+ InsightsApiClient_logger.debug(`"${requestName}" request successfully completed`);
412
+ return true;
413
+ } catch (error) {
414
+ this.logRequestError(error, {
415
+ requestName
416
+ });
417
+ return false;
418
+ }
419
+ }
420
+ }
421
+ const insights = InsightsApiClient;
422
+ class ApiClient {
423
+ config;
424
+ experience;
425
+ insights;
426
+ constructor(config){
427
+ const { personalization, analytics, ...apiConfig } = config;
428
+ this.config = apiConfig;
429
+ this.experience = new experience({
430
+ ...apiConfig,
431
+ ...personalization
432
+ });
433
+ this.insights = new insights({
434
+ ...apiConfig,
435
+ ...analytics
436
+ });
437
+ }
438
+ }
439
+ const UniversalEventBuilderArgs = object({
440
+ campaign: optional(__rspack_external__contentful_optimization_api_schemas_66dcf407.Campaign),
441
+ locale: optional(string()),
442
+ location: optional(__rspack_external__contentful_optimization_api_schemas_66dcf407.GeoLocation),
443
+ page: optional(__rspack_external__contentful_optimization_api_schemas_66dcf407.Page),
444
+ screen: optional(__rspack_external__contentful_optimization_api_schemas_66dcf407.Screen),
445
+ userAgent: optional(string())
446
+ });
447
+ const ComponentViewBuilderArgs = extend(UniversalEventBuilderArgs, {
448
+ componentId: string(),
449
+ experienceId: optional(string()),
450
+ variantIndex: optional(number()),
451
+ sticky: optional(mini_boolean())
452
+ });
453
+ const IdentifyBuilderArgs = extend(UniversalEventBuilderArgs, {
454
+ traits: optional(__rspack_external__contentful_optimization_api_schemas_66dcf407.Traits),
455
+ userId: string()
456
+ });
457
+ const PageViewBuilderArgs = extend(UniversalEventBuilderArgs, {
458
+ properties: optional(partial(__rspack_external__contentful_optimization_api_schemas_66dcf407.Page))
459
+ });
460
+ const ScreenViewBuilderArgs = extend(UniversalEventBuilderArgs, {
461
+ name: string(),
462
+ properties: __rspack_external__contentful_optimization_api_schemas_66dcf407.Properties
463
+ });
464
+ const TrackBuilderArgs = extend(UniversalEventBuilderArgs, {
465
+ event: string(),
466
+ properties: optional(prefault(__rspack_external__contentful_optimization_api_schemas_66dcf407.Properties, {}))
467
+ });
468
+ const DEFAULT_PAGE_PROPERTIES = {
469
+ path: '',
470
+ query: {},
471
+ referrer: '',
472
+ search: '',
473
+ title: '',
474
+ url: ''
475
+ };
476
+ class EventBuilder {
477
+ app;
478
+ channel;
479
+ library;
480
+ getLocale;
481
+ getPageProperties;
482
+ getUserAgent;
483
+ constructor(config){
484
+ const { app, channel, library, getLocale, getPageProperties, getUserAgent } = config;
485
+ this.app = app;
486
+ this.channel = channel;
487
+ this.library = library;
488
+ this.getLocale = getLocale ?? (()=>'en-US');
489
+ this.getPageProperties = getPageProperties ?? (()=>DEFAULT_PAGE_PROPERTIES);
490
+ this.getUserAgent = getUserAgent ?? (()=>void 0);
491
+ }
492
+ buildUniversalEventProperties({ campaign = {}, locale, location, page, screen, userAgent }) {
493
+ const timestamp = new Date().toISOString();
494
+ return {
495
+ channel: this.channel,
496
+ context: {
497
+ app: this.app,
498
+ campaign,
499
+ gdpr: {
500
+ isConsentGiven: true
501
+ },
502
+ library: this.library,
503
+ locale: locale ?? this.getLocale() ?? 'en-US',
504
+ location,
505
+ page: page ?? this.getPageProperties(),
506
+ screen,
507
+ userAgent: userAgent ?? this.getUserAgent()
508
+ },
509
+ messageId: crypto.randomUUID(),
510
+ originalTimestamp: timestamp,
511
+ sentAt: timestamp,
512
+ timestamp
513
+ };
514
+ }
515
+ buildComponentView(args) {
516
+ const { componentId, experienceId, variantIndex, ...universal } = ComponentViewBuilderArgs.parse(args);
517
+ return {
518
+ ...this.buildUniversalEventProperties(universal),
519
+ type: 'component',
520
+ componentType: 'Entry',
521
+ componentId,
522
+ experienceId,
523
+ variantIndex: variantIndex ?? 0
524
+ };
525
+ }
526
+ buildFlagView(args) {
527
+ return {
528
+ ...this.buildComponentView(args),
529
+ componentType: 'Variable'
530
+ };
531
+ }
532
+ buildIdentify(args) {
533
+ const { traits = {}, userId, ...universal } = IdentifyBuilderArgs.parse(args);
534
+ return {
535
+ ...this.buildUniversalEventProperties(universal),
536
+ type: 'identify',
537
+ traits,
538
+ userId
539
+ };
540
+ }
541
+ buildPageView(args = {}) {
542
+ const { properties = {}, ...universal } = PageViewBuilderArgs.parse(args);
543
+ const pageProperties = this.getPageProperties();
544
+ const merged = merge({
545
+ ...pageProperties,
546
+ title: pageProperties.title ?? DEFAULT_PAGE_PROPERTIES.title
547
+ }, properties);
548
+ const { context: { screen: _, ...universalContext }, ...universalProperties } = this.buildUniversalEventProperties(universal);
549
+ const context = __rspack_external__contentful_optimization_api_schemas_66dcf407.PageEventContext.parse(universalContext);
550
+ return {
551
+ ...universalProperties,
552
+ context,
553
+ type: 'page',
554
+ properties: merged
555
+ };
556
+ }
557
+ buildScreenView(args) {
558
+ const { name, properties, ...universal } = ScreenViewBuilderArgs.parse(args);
559
+ const { context: { page: _, ...universalContext }, ...universalProperties } = this.buildUniversalEventProperties(universal);
560
+ const context = __rspack_external__contentful_optimization_api_schemas_66dcf407.ScreenEventContext.parse(universalContext);
561
+ return {
562
+ ...universalProperties,
563
+ context,
564
+ type: 'screen',
565
+ name,
566
+ properties
567
+ };
568
+ }
569
+ buildTrack(args) {
570
+ const { event, properties = {}, ...universal } = TrackBuilderArgs.parse(args);
571
+ return {
572
+ ...this.buildUniversalEventProperties(universal),
573
+ type: 'track',
574
+ event,
575
+ properties
576
+ };
577
+ }
578
+ }
579
+ const builders_EventBuilder = EventBuilder;
580
+ export * from "@contentful/optimization-api-schemas";
581
+ export { ApiClient, DEFAULT_PAGE_PROPERTIES, EXPERIENCE_BASE_URL, INSIGHTS_BASE_URL, builders_EventBuilder as EventBuilder };
582
+
583
+ //# sourceMappingURL=index.mjs.map