@contentful/optimization-api-client 0.1.0-alpha → 0.1.0-alpha11

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