@contentful/optimization-api-client 0.1.0-alpha8 → 0.1.0-alpha9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -24
- package/dist/199.mjs +2 -0
- package/dist/649.mjs +131 -0
- package/dist/649.mjs.map +1 -0
- package/dist/api-schemas.cjs +60 -0
- package/dist/api-schemas.cjs.map +1 -0
- package/dist/api-schemas.d.cts +4 -0
- package/dist/api-schemas.d.mts +4 -0
- package/dist/api-schemas.d.ts +4 -0
- package/dist/api-schemas.mjs +2 -0
- package/dist/index.cjs +588 -575
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +327 -68
- package/dist/index.d.mts +327 -68
- package/dist/index.d.ts +1649 -8
- package/dist/index.mjs +103 -136
- package/dist/index.mjs.map +1 -1
- package/dist/logger.cjs +207 -0
- package/dist/logger.cjs.map +1 -0
- package/dist/logger.d.cts +287 -0
- package/dist/logger.d.mts +287 -0
- package/dist/logger.d.ts +287 -0
- package/dist/logger.mjs +1 -0
- package/package.json +24 -6
- package/dist/ApiClient.d.ts +0 -74
- package/dist/ApiClient.d.ts.map +0 -1
- package/dist/ApiClient.js +0 -61
- package/dist/ApiClient.js.map +0 -1
- package/dist/ApiClientBase.d.ts +0 -113
- package/dist/ApiClientBase.d.ts.map +0 -1
- package/dist/ApiClientBase.js +0 -94
- package/dist/ApiClientBase.js.map +0 -1
- package/dist/builders/EventBuilder.d.ts +0 -589
- package/dist/builders/EventBuilder.d.ts.map +0 -1
- package/dist/builders/EventBuilder.js +0 -349
- package/dist/builders/EventBuilder.js.map +0 -1
- package/dist/builders/index.d.ts +0 -3
- package/dist/builders/index.d.ts.map +0 -1
- package/dist/builders/index.js +0 -3
- package/dist/builders/index.js.map +0 -1
- package/dist/experience/ExperienceApiClient.d.ts +0 -267
- package/dist/experience/ExperienceApiClient.d.ts.map +0 -1
- package/dist/experience/ExperienceApiClient.js +0 -324
- package/dist/experience/ExperienceApiClient.js.map +0 -1
- package/dist/experience/index.d.ts +0 -4
- package/dist/experience/index.d.ts.map +0 -1
- package/dist/experience/index.js +0 -4
- package/dist/experience/index.js.map +0 -1
- package/dist/fetch/Fetch.d.ts +0 -96
- package/dist/fetch/Fetch.d.ts.map +0 -1
- package/dist/fetch/Fetch.js +0 -27
- package/dist/fetch/Fetch.js.map +0 -1
- package/dist/fetch/createProtectedFetchMethod.d.ts +0 -40
- package/dist/fetch/createProtectedFetchMethod.d.ts.map +0 -1
- package/dist/fetch/createProtectedFetchMethod.js +0 -53
- package/dist/fetch/createProtectedFetchMethod.js.map +0 -1
- package/dist/fetch/createRetryFetchMethod.d.ts +0 -60
- package/dist/fetch/createRetryFetchMethod.d.ts.map +0 -1
- package/dist/fetch/createRetryFetchMethod.js +0 -138
- package/dist/fetch/createRetryFetchMethod.js.map +0 -1
- package/dist/fetch/createTimeoutFetchMethod.d.ts +0 -51
- package/dist/fetch/createTimeoutFetchMethod.d.ts.map +0 -1
- package/dist/fetch/createTimeoutFetchMethod.js +0 -51
- package/dist/fetch/createTimeoutFetchMethod.js.map +0 -1
- package/dist/fetch/index.d.ts +0 -7
- package/dist/fetch/index.d.ts.map +0 -1
- package/dist/fetch/index.js +0 -7
- package/dist/fetch/index.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -8
- package/dist/index.js.map +0 -1
- package/dist/insights/InsightsApiClient.d.ts +0 -130
- package/dist/insights/InsightsApiClient.d.ts.map +0 -1
- package/dist/insights/InsightsApiClient.js +0 -143
- package/dist/insights/InsightsApiClient.js.map +0 -1
- package/dist/insights/index.d.ts +0 -4
- package/dist/insights/index.d.ts.map +0 -1
- package/dist/insights/index.js +0 -4
- 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/
|
|
3
|
+
"./src/lib/logger/LogSink.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
4
4
|
__webpack_require__.d(__webpack_exports__, {
|
|
5
|
-
A: ()=>
|
|
5
|
+
A: ()=>__rspack_default_export
|
|
6
6
|
});
|
|
7
|
-
|
|
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/
|
|
11
|
+
"./src/lib/logger/logging.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
28
12
|
__webpack_require__.d(__webpack_exports__, {
|
|
29
|
-
A: ()=>
|
|
13
|
+
A: ()=>logLevelSeverity
|
|
30
14
|
});
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
},
|
|
157
|
-
"./src/builders/index.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
158
|
-
__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, {}))
|
|
193
|
-
});
|
|
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
23
|
},
|
|
307
|
-
"./src/
|
|
24
|
+
"./src/logger.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
308
25
|
__webpack_require__.d(__webpack_exports__, {
|
|
309
|
-
|
|
310
|
-
A: ()=>experience
|
|
26
|
+
createScopedLogger: ()=>createScopedLogger
|
|
311
27
|
});
|
|
312
|
-
|
|
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.
|
|
55
|
+
this.emit('debug', logLocation, message, ...args);
|
|
582
56
|
}
|
|
583
57
|
info(logLocation, message, ...args) {
|
|
584
|
-
this.
|
|
58
|
+
this.emit('info', logLocation, message, ...args);
|
|
585
59
|
}
|
|
586
60
|
log(logLocation, message, ...args) {
|
|
587
|
-
this.
|
|
61
|
+
this.emit('log', logLocation, message, ...args);
|
|
588
62
|
}
|
|
589
63
|
warn(logLocation, message, ...args) {
|
|
590
|
-
this.
|
|
64
|
+
this.emit('warn', logLocation, message, ...args);
|
|
591
65
|
}
|
|
592
66
|
error(logLocation, message, ...args) {
|
|
593
|
-
this.
|
|
67
|
+
this.emit('error', logLocation, message, ...args);
|
|
594
68
|
}
|
|
595
69
|
fatal(logLocation, message, ...args) {
|
|
596
|
-
this.
|
|
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
|
|
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,24 +148,559 @@ var __webpack_exports__ = {};
|
|
|
670
148
|
(()=>{
|
|
671
149
|
__webpack_require__.r(__webpack_exports__);
|
|
672
150
|
__webpack_require__.d(__webpack_exports__, {
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
151
|
+
EXPERIENCE_BASE_URL: ()=>EXPERIENCE_BASE_URL,
|
|
152
|
+
ApiClient: ()=>ApiClient,
|
|
153
|
+
INSIGHTS_BASE_URL: ()=>INSIGHTS_BASE_URL,
|
|
154
|
+
DEFAULT_PAGE_PROPERTIES: ()=>DEFAULT_PAGE_PROPERTIES,
|
|
155
|
+
EventBuilder: ()=>builders_EventBuilder
|
|
156
|
+
});
|
|
157
|
+
const optimization_api_schemas_namespaceObject = require("@contentful/optimization-api-schemas");
|
|
158
|
+
var logger = __webpack_require__("./src/logger.ts");
|
|
159
|
+
const createRetryFetchMethod_logger = (0, logger.createScopedLogger)('ApiClient:Retry');
|
|
160
|
+
const DEFAULT_INTERVAL_TIMEOUT = 0;
|
|
161
|
+
const DEFAULT_RETRY_COUNT = 1;
|
|
162
|
+
const RETRY_RESPONSE_STATUS = 503;
|
|
163
|
+
const HTTP_ERROR_RESPONSE_STATUS = 500;
|
|
164
|
+
class HttpError extends Error {
|
|
165
|
+
status;
|
|
166
|
+
constructor(message, status = HTTP_ERROR_RESPONSE_STATUS){
|
|
167
|
+
super(message);
|
|
168
|
+
Object.setPrototypeOf(this, HttpError.prototype);
|
|
169
|
+
this.status = status;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function createRetryFetchCallback({ apiName = 'Optimization', controller, fetchMethod = fetch, init, url }) {
|
|
173
|
+
return async ()=>{
|
|
174
|
+
try {
|
|
175
|
+
const response = await fetchMethod(url, init);
|
|
176
|
+
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);
|
|
177
|
+
if (!response.ok) {
|
|
178
|
+
const httpError = new Error(`Request to "${url.toString()}" failed with status: [${response.status}] ${response.statusText} - traceparent: ${response.headers.get('traceparent')}`);
|
|
179
|
+
createRetryFetchMethod_logger.error('Request failed with non-OK status:', httpError);
|
|
180
|
+
controller.abort();
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
createRetryFetchMethod_logger.debug(`Response from "${url.toString()}":`, response);
|
|
184
|
+
return response;
|
|
185
|
+
} catch (error) {
|
|
186
|
+
if (error instanceof HttpError && error.status === RETRY_RESPONSE_STATUS) throw error;
|
|
187
|
+
createRetryFetchMethod_logger.error(`Request to "${url.toString()}" failed:`, error);
|
|
188
|
+
controller.abort();
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
async function delayRetry(intervalTimeout) {
|
|
193
|
+
if (intervalTimeout <= 0) return;
|
|
194
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
195
|
+
setTimeout(()=>{
|
|
196
|
+
resolve(void 0);
|
|
197
|
+
}, intervalTimeout);
|
|
198
|
+
await promise;
|
|
199
|
+
}
|
|
200
|
+
function createRetryFetchMethod({ apiName = 'Optimization', fetchMethod = fetch, intervalTimeout = DEFAULT_INTERVAL_TIMEOUT, onFailedAttempt, retries = DEFAULT_RETRY_COUNT } = {}) {
|
|
201
|
+
return async (url, init)=>{
|
|
202
|
+
const controller = new AbortController();
|
|
203
|
+
const maxAttempts = retries + 1;
|
|
204
|
+
const attemptFetch = createRetryFetchCallback({
|
|
205
|
+
apiName,
|
|
206
|
+
controller,
|
|
207
|
+
fetchMethod,
|
|
208
|
+
init,
|
|
209
|
+
url
|
|
210
|
+
});
|
|
211
|
+
for(let attemptNumber = 1; attemptNumber <= maxAttempts; attemptNumber++)try {
|
|
212
|
+
const response = await attemptFetch();
|
|
213
|
+
if (response) return response;
|
|
214
|
+
break;
|
|
215
|
+
} catch (error) {
|
|
216
|
+
if (!(error instanceof HttpError) || error.status !== RETRY_RESPONSE_STATUS) throw error;
|
|
217
|
+
const retriesLeft = maxAttempts - attemptNumber;
|
|
218
|
+
onFailedAttempt?.({
|
|
219
|
+
apiName,
|
|
220
|
+
error,
|
|
221
|
+
attemptNumber,
|
|
222
|
+
retriesLeft
|
|
223
|
+
});
|
|
224
|
+
if (0 === retriesLeft) throw error;
|
|
225
|
+
await delayRetry(intervalTimeout);
|
|
226
|
+
}
|
|
227
|
+
throw new Error(`${apiName} API request to "${url.toString()}" may not be retried.`);
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
const createTimeoutFetchMethod_logger = (0, logger.createScopedLogger)('ApiClient:Timeout');
|
|
231
|
+
const DEFAULT_REQUEST_TIMEOUT = 3000;
|
|
232
|
+
function createTimeoutFetchMethod({ apiName = 'Optimization', fetchMethod = fetch, onRequestTimeout, requestTimeout = DEFAULT_REQUEST_TIMEOUT } = {}) {
|
|
233
|
+
return async (url, init)=>{
|
|
234
|
+
const controller = new AbortController();
|
|
235
|
+
const id = setTimeout(()=>{
|
|
236
|
+
if ('function' == typeof onRequestTimeout) onRequestTimeout({
|
|
237
|
+
apiName
|
|
238
|
+
});
|
|
239
|
+
else createTimeoutFetchMethod_logger.error(`Request to "${url.toString()}" timed out`, new Error('Request timeout'));
|
|
240
|
+
controller.abort();
|
|
241
|
+
}, requestTimeout);
|
|
242
|
+
const response = await fetchMethod(url, {
|
|
243
|
+
...init,
|
|
244
|
+
signal: controller.signal
|
|
245
|
+
});
|
|
246
|
+
clearTimeout(id);
|
|
247
|
+
return response;
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
const createProtectedFetchMethod_logger = (0, logger.createScopedLogger)('ApiClient:Fetch');
|
|
251
|
+
function createProtectedFetchMethod(options) {
|
|
252
|
+
try {
|
|
253
|
+
const timeoutFetchMethod = createTimeoutFetchMethod(options);
|
|
254
|
+
const retryFetchMethod = createRetryFetchMethod({
|
|
255
|
+
...options,
|
|
256
|
+
fetchMethod: timeoutFetchMethod
|
|
257
|
+
});
|
|
258
|
+
return retryFetchMethod;
|
|
259
|
+
} catch (error) {
|
|
260
|
+
if (error instanceof Error) if ('AbortError' === error.name) createProtectedFetchMethod_logger.warn('Request aborted due to network issues. This request may not be retried.');
|
|
261
|
+
else createProtectedFetchMethod_logger.error('Request failed:', error);
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const Fetch = {
|
|
266
|
+
create: createProtectedFetchMethod
|
|
267
|
+
};
|
|
268
|
+
const fetch_Fetch = Fetch;
|
|
269
|
+
const src_fetch = fetch_Fetch;
|
|
270
|
+
const ApiClientBase_logger = (0, logger.createScopedLogger)('ApiClient');
|
|
271
|
+
const DEFAULT_ENVIRONMENT = 'main';
|
|
272
|
+
class ApiClientBase {
|
|
273
|
+
name;
|
|
274
|
+
clientId;
|
|
275
|
+
environment;
|
|
276
|
+
fetch;
|
|
277
|
+
constructor(name, { fetchOptions, clientId, environment }){
|
|
278
|
+
this.clientId = clientId;
|
|
279
|
+
this.environment = environment ?? DEFAULT_ENVIRONMENT;
|
|
280
|
+
this.name = name;
|
|
281
|
+
this.fetch = src_fetch.create({
|
|
282
|
+
...fetchOptions ?? {},
|
|
283
|
+
apiName: name
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
logRequestError(error, { requestName }) {
|
|
287
|
+
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.`);
|
|
288
|
+
else ApiClientBase_logger.error(`[${this.name}] "${requestName}" request failed:`, error);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
const src_ApiClientBase = ApiClientBase;
|
|
292
|
+
const ExperienceApiClient_logger = (0, logger.createScopedLogger)('ApiClient:Experience');
|
|
293
|
+
const EXPERIENCE_BASE_URL = 'https://experience.ninetailed.co/';
|
|
294
|
+
class ExperienceApiClient extends src_ApiClientBase {
|
|
295
|
+
baseUrl;
|
|
296
|
+
enabledFeatures;
|
|
297
|
+
ip;
|
|
298
|
+
locale;
|
|
299
|
+
plainText;
|
|
300
|
+
preflight;
|
|
301
|
+
constructor(config){
|
|
302
|
+
super('Experience', config);
|
|
303
|
+
const { baseUrl, enabledFeatures, ip, locale, plainText, preflight } = config;
|
|
304
|
+
this.baseUrl = baseUrl || EXPERIENCE_BASE_URL;
|
|
305
|
+
this.enabledFeatures = enabledFeatures;
|
|
306
|
+
this.ip = ip;
|
|
307
|
+
this.locale = locale;
|
|
308
|
+
this.plainText = plainText;
|
|
309
|
+
this.preflight = preflight;
|
|
310
|
+
}
|
|
311
|
+
async getProfile(id, options = {}) {
|
|
312
|
+
if (!id) throw new Error('Valid profile ID required.');
|
|
313
|
+
const requestName = 'Get Profile';
|
|
314
|
+
ExperienceApiClient_logger.info(`Sending "${requestName}" request`);
|
|
315
|
+
try {
|
|
316
|
+
const response = await this.fetch(this.constructUrl(`v2/organizations/${this.clientId}/environments/${this.environment}/profiles/${id}`, options), {
|
|
317
|
+
method: 'GET'
|
|
318
|
+
});
|
|
319
|
+
const { data: { changes, experiences, profile } } = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(optimization_api_schemas_namespaceObject.ExperienceResponse, await response.json());
|
|
320
|
+
const data = {
|
|
321
|
+
changes,
|
|
322
|
+
personalizations: experiences,
|
|
323
|
+
profile
|
|
324
|
+
};
|
|
325
|
+
ExperienceApiClient_logger.debug(`"${requestName}" request successfully completed`);
|
|
326
|
+
return data;
|
|
327
|
+
} catch (error) {
|
|
328
|
+
this.logRequestError(error, {
|
|
329
|
+
requestName
|
|
330
|
+
});
|
|
331
|
+
throw error;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
async makeProfileMutationRequest({ url, body, options }) {
|
|
335
|
+
return await this.fetch(this.constructUrl(url, options), {
|
|
336
|
+
method: 'POST',
|
|
337
|
+
headers: this.constructHeaders(options),
|
|
338
|
+
body: JSON.stringify(body),
|
|
339
|
+
keepalive: true
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
async createProfile({ events }, options = {}) {
|
|
343
|
+
const requestName = 'Create Profile';
|
|
344
|
+
ExperienceApiClient_logger.info(`Sending "${requestName}" request`);
|
|
345
|
+
const body = this.constructExperienceRequestBody(events, options);
|
|
346
|
+
ExperienceApiClient_logger.debug(`"${requestName}" request body:`, body);
|
|
347
|
+
try {
|
|
348
|
+
const response = await this.makeProfileMutationRequest({
|
|
349
|
+
url: `v2/organizations/${this.clientId}/environments/${this.environment}/profiles`,
|
|
350
|
+
body,
|
|
351
|
+
options
|
|
352
|
+
});
|
|
353
|
+
const { data: { changes, experiences, profile } } = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(optimization_api_schemas_namespaceObject.ExperienceResponse, await response.json());
|
|
354
|
+
const data = {
|
|
355
|
+
changes,
|
|
356
|
+
personalizations: experiences,
|
|
357
|
+
profile
|
|
358
|
+
};
|
|
359
|
+
ExperienceApiClient_logger.debug(`"${requestName}" request successfully completed`);
|
|
360
|
+
return data;
|
|
361
|
+
} catch (error) {
|
|
362
|
+
this.logRequestError(error, {
|
|
363
|
+
requestName
|
|
364
|
+
});
|
|
365
|
+
throw error;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
async updateProfile({ profileId, events }, options = {}) {
|
|
369
|
+
if (!profileId) throw new Error('Valid profile ID required.');
|
|
370
|
+
const requestName = 'Update Profile';
|
|
371
|
+
ExperienceApiClient_logger.info(`Sending "${requestName}" request`);
|
|
372
|
+
const body = this.constructExperienceRequestBody(events, options);
|
|
373
|
+
ExperienceApiClient_logger.debug(`"${requestName}" request body:`, body);
|
|
374
|
+
try {
|
|
375
|
+
const response = await this.makeProfileMutationRequest({
|
|
376
|
+
url: `v2/organizations/${this.clientId}/environments/${this.environment}/profiles/${profileId}`,
|
|
377
|
+
body,
|
|
378
|
+
options
|
|
379
|
+
});
|
|
380
|
+
const { data: { changes, experiences, profile } } = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(optimization_api_schemas_namespaceObject.ExperienceResponse, await response.json());
|
|
381
|
+
const data = {
|
|
382
|
+
changes,
|
|
383
|
+
personalizations: experiences,
|
|
384
|
+
profile
|
|
385
|
+
};
|
|
386
|
+
ExperienceApiClient_logger.debug(`"${requestName}" request successfully completed`);
|
|
387
|
+
return data;
|
|
388
|
+
} catch (error) {
|
|
389
|
+
this.logRequestError(error, {
|
|
390
|
+
requestName
|
|
391
|
+
});
|
|
392
|
+
throw error;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
async upsertProfile({ profileId, events }, options) {
|
|
396
|
+
if (!profileId) return await this.createProfile({
|
|
397
|
+
events
|
|
398
|
+
}, options);
|
|
399
|
+
return await this.updateProfile({
|
|
400
|
+
profileId,
|
|
401
|
+
events
|
|
402
|
+
}, options);
|
|
403
|
+
}
|
|
404
|
+
async upsertManyProfiles({ events }, options = {}) {
|
|
405
|
+
const requestName = 'Upsert Many Profiles';
|
|
406
|
+
ExperienceApiClient_logger.info(`Sending "${requestName}" request`);
|
|
407
|
+
const body = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(optimization_api_schemas_namespaceObject.BatchExperienceRequestData, {
|
|
408
|
+
events,
|
|
409
|
+
options: this.constructBodyOptions(options)
|
|
410
|
+
});
|
|
411
|
+
ExperienceApiClient_logger.debug(`"${requestName}" request body:`, body);
|
|
412
|
+
try {
|
|
413
|
+
const response = await this.makeProfileMutationRequest({
|
|
414
|
+
url: `v2/organizations/${this.clientId}/environments/${this.environment}/events`,
|
|
415
|
+
body,
|
|
416
|
+
options: {
|
|
417
|
+
plainText: false,
|
|
418
|
+
...options
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
const { data: { profiles } } = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(optimization_api_schemas_namespaceObject.BatchExperienceResponse, await response.json());
|
|
422
|
+
ExperienceApiClient_logger.debug(`"${requestName}" request successfully completed`);
|
|
423
|
+
return profiles;
|
|
424
|
+
} catch (error) {
|
|
425
|
+
this.logRequestError(error, {
|
|
426
|
+
requestName
|
|
427
|
+
});
|
|
428
|
+
throw error;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
constructUrl(path, options) {
|
|
432
|
+
const url = new URL(path, this.baseUrl);
|
|
433
|
+
const locale = options.locale ?? this.locale;
|
|
434
|
+
const preflight = options.preflight ?? this.preflight;
|
|
435
|
+
if (locale) url.searchParams.set('locale', locale);
|
|
436
|
+
if (preflight) url.searchParams.set('type', 'preflight');
|
|
437
|
+
return url.toString();
|
|
438
|
+
}
|
|
439
|
+
constructHeaders({ ip = this.ip, plainText = this.plainText }) {
|
|
440
|
+
const headers = new Map();
|
|
441
|
+
if (ip) headers.set('X-Force-IP', ip);
|
|
442
|
+
if (plainText ?? this.plainText ?? true) headers.set('Content-Type', 'text/plain');
|
|
443
|
+
else headers.set('Content-Type', 'application/json');
|
|
444
|
+
return Object.fromEntries(headers);
|
|
445
|
+
}
|
|
446
|
+
constructBodyOptions = ({ enabledFeatures = this.enabledFeatures })=>{
|
|
447
|
+
const bodyOptions = {};
|
|
448
|
+
if (enabledFeatures && Array.isArray(enabledFeatures) && enabledFeatures.length > 0) bodyOptions.features = enabledFeatures;
|
|
449
|
+
else bodyOptions.features = [
|
|
450
|
+
'ip-enrichment',
|
|
451
|
+
'location'
|
|
452
|
+
];
|
|
453
|
+
return bodyOptions;
|
|
454
|
+
};
|
|
455
|
+
constructExperienceRequestBody(events, options) {
|
|
456
|
+
return optimization_api_schemas_namespaceObject.ExperienceRequestData.parse({
|
|
457
|
+
events: (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(optimization_api_schemas_namespaceObject.ExperienceEventArray, events),
|
|
458
|
+
options: this.constructBodyOptions(options)
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
const experience = ExperienceApiClient;
|
|
463
|
+
const InsightsApiClient_logger = (0, logger.createScopedLogger)('ApiClient:Insights');
|
|
464
|
+
const INSIGHTS_BASE_URL = 'https://ingest.insights.ninetailed.co/';
|
|
465
|
+
class InsightsApiClient extends src_ApiClientBase {
|
|
466
|
+
baseUrl;
|
|
467
|
+
beaconHandler;
|
|
468
|
+
constructor(config){
|
|
469
|
+
super('Insights', config);
|
|
470
|
+
const { baseUrl, beaconHandler } = config;
|
|
471
|
+
this.baseUrl = baseUrl || INSIGHTS_BASE_URL;
|
|
472
|
+
this.beaconHandler = beaconHandler;
|
|
473
|
+
}
|
|
474
|
+
async sendBatchEvents(batches, options = {}) {
|
|
475
|
+
const { beaconHandler = this.beaconHandler } = options;
|
|
476
|
+
const url = new URL(`v1/organizations/${this.clientId}/environments/${this.environment}/events`, this.baseUrl);
|
|
477
|
+
const body = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(optimization_api_schemas_namespaceObject.BatchInsightsEventArray, batches);
|
|
478
|
+
if ('function' == typeof beaconHandler) {
|
|
479
|
+
InsightsApiClient_logger.debug('Queueing events via beaconHandler');
|
|
480
|
+
const beaconSuccessfullyQueued = beaconHandler(url, body);
|
|
481
|
+
if (beaconSuccessfullyQueued) return true;
|
|
482
|
+
InsightsApiClient_logger.warn('beaconHandler failed to queue events; events will be emitted immediately via fetch');
|
|
483
|
+
}
|
|
484
|
+
const requestName = 'Event Batches';
|
|
485
|
+
InsightsApiClient_logger.info(`Sending "${requestName}" request`);
|
|
486
|
+
InsightsApiClient_logger.debug(`"${requestName}" request body:`, body);
|
|
487
|
+
try {
|
|
488
|
+
await this.fetch(url, {
|
|
489
|
+
method: 'POST',
|
|
490
|
+
headers: {
|
|
491
|
+
'Content-Type': 'application/json'
|
|
492
|
+
},
|
|
493
|
+
body: JSON.stringify(body),
|
|
494
|
+
keepalive: true
|
|
495
|
+
});
|
|
496
|
+
InsightsApiClient_logger.debug(`"${requestName}" request successfully completed`);
|
|
497
|
+
return true;
|
|
498
|
+
} catch (error) {
|
|
499
|
+
this.logRequestError(error, {
|
|
500
|
+
requestName
|
|
501
|
+
});
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
const insights = InsightsApiClient;
|
|
507
|
+
class ApiClient {
|
|
508
|
+
config;
|
|
509
|
+
experience;
|
|
510
|
+
insights;
|
|
511
|
+
constructor(config){
|
|
512
|
+
const { personalization, analytics, clientId, environment, fetchOptions } = config;
|
|
513
|
+
const apiConfig = {
|
|
514
|
+
clientId,
|
|
515
|
+
environment,
|
|
516
|
+
fetchOptions
|
|
517
|
+
};
|
|
518
|
+
this.config = apiConfig;
|
|
519
|
+
this.experience = new experience({
|
|
520
|
+
...apiConfig,
|
|
521
|
+
...personalization
|
|
522
|
+
});
|
|
523
|
+
this.insights = new insights({
|
|
524
|
+
...apiConfig,
|
|
525
|
+
...analytics
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
const object_namespaceObject = require("es-toolkit/object");
|
|
530
|
+
const mini_namespaceObject = require("zod/mini");
|
|
531
|
+
const UniversalEventBuilderArgs = mini_namespaceObject.object({
|
|
532
|
+
campaign: mini_namespaceObject.optional(optimization_api_schemas_namespaceObject.Campaign),
|
|
533
|
+
locale: mini_namespaceObject.optional(mini_namespaceObject.string()),
|
|
534
|
+
location: mini_namespaceObject.optional(optimization_api_schemas_namespaceObject.GeoLocation),
|
|
535
|
+
page: mini_namespaceObject.optional(optimization_api_schemas_namespaceObject.Page),
|
|
536
|
+
screen: mini_namespaceObject.optional(optimization_api_schemas_namespaceObject.Screen),
|
|
537
|
+
userAgent: mini_namespaceObject.optional(mini_namespaceObject.string())
|
|
538
|
+
});
|
|
539
|
+
const ComponentInteractionBuilderArgsBase = mini_namespaceObject.extend(UniversalEventBuilderArgs, {
|
|
540
|
+
componentId: mini_namespaceObject.string(),
|
|
541
|
+
experienceId: mini_namespaceObject.optional(mini_namespaceObject.string()),
|
|
542
|
+
variantIndex: mini_namespaceObject.optional(mini_namespaceObject.number())
|
|
678
543
|
});
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
544
|
+
const ComponentViewBuilderArgs = mini_namespaceObject.extend(ComponentInteractionBuilderArgsBase, {
|
|
545
|
+
sticky: mini_namespaceObject.optional(mini_namespaceObject.boolean()),
|
|
546
|
+
componentViewId: mini_namespaceObject.string(),
|
|
547
|
+
viewDurationMs: mini_namespaceObject.number()
|
|
548
|
+
});
|
|
549
|
+
const ComponentClickBuilderArgs = ComponentInteractionBuilderArgsBase;
|
|
550
|
+
const ComponentHoverBuilderArgs = mini_namespaceObject.extend(ComponentInteractionBuilderArgsBase, {
|
|
551
|
+
componentHoverId: mini_namespaceObject.string(),
|
|
552
|
+
hoverDurationMs: mini_namespaceObject.number()
|
|
553
|
+
});
|
|
554
|
+
const IdentifyBuilderArgs = mini_namespaceObject.extend(UniversalEventBuilderArgs, {
|
|
555
|
+
traits: mini_namespaceObject.optional(optimization_api_schemas_namespaceObject.Traits),
|
|
556
|
+
userId: mini_namespaceObject.string()
|
|
557
|
+
});
|
|
558
|
+
const PageViewBuilderArgs = mini_namespaceObject.extend(UniversalEventBuilderArgs, {
|
|
559
|
+
properties: mini_namespaceObject.optional(mini_namespaceObject.partial(optimization_api_schemas_namespaceObject.Page))
|
|
560
|
+
});
|
|
561
|
+
const ScreenViewBuilderArgs = mini_namespaceObject.extend(UniversalEventBuilderArgs, {
|
|
562
|
+
name: mini_namespaceObject.string(),
|
|
563
|
+
properties: optimization_api_schemas_namespaceObject.Properties
|
|
564
|
+
});
|
|
565
|
+
const TrackBuilderArgs = mini_namespaceObject.extend(UniversalEventBuilderArgs, {
|
|
566
|
+
event: mini_namespaceObject.string(),
|
|
567
|
+
properties: mini_namespaceObject.optional(mini_namespaceObject.prefault(optimization_api_schemas_namespaceObject.Properties, {}))
|
|
568
|
+
});
|
|
569
|
+
const DEFAULT_PAGE_PROPERTIES = {
|
|
570
|
+
path: '',
|
|
571
|
+
query: {},
|
|
572
|
+
referrer: '',
|
|
573
|
+
search: '',
|
|
574
|
+
title: '',
|
|
575
|
+
url: ''
|
|
576
|
+
};
|
|
577
|
+
class EventBuilder {
|
|
578
|
+
app;
|
|
579
|
+
channel;
|
|
580
|
+
library;
|
|
581
|
+
getLocale;
|
|
582
|
+
getPageProperties;
|
|
583
|
+
getUserAgent;
|
|
584
|
+
constructor(config){
|
|
585
|
+
const { app, channel, library, getLocale, getPageProperties, getUserAgent } = config;
|
|
586
|
+
this.app = app;
|
|
587
|
+
this.channel = channel;
|
|
588
|
+
this.library = library;
|
|
589
|
+
this.getLocale = getLocale ?? (()=>'en-US');
|
|
590
|
+
this.getPageProperties = getPageProperties ?? (()=>DEFAULT_PAGE_PROPERTIES);
|
|
591
|
+
this.getUserAgent = getUserAgent ?? (()=>void 0);
|
|
592
|
+
}
|
|
593
|
+
buildUniversalEventProperties({ campaign = {}, locale, location, page, screen, userAgent }) {
|
|
594
|
+
const timestamp = new Date().toISOString();
|
|
595
|
+
return {
|
|
596
|
+
channel: this.channel,
|
|
597
|
+
context: {
|
|
598
|
+
app: this.app,
|
|
599
|
+
campaign,
|
|
600
|
+
gdpr: {
|
|
601
|
+
isConsentGiven: true
|
|
602
|
+
},
|
|
603
|
+
library: this.library,
|
|
604
|
+
locale: locale ?? this.getLocale() ?? 'en-US',
|
|
605
|
+
location,
|
|
606
|
+
page: page ?? this.getPageProperties(),
|
|
607
|
+
screen,
|
|
608
|
+
userAgent: userAgent ?? this.getUserAgent()
|
|
609
|
+
},
|
|
610
|
+
messageId: crypto.randomUUID(),
|
|
611
|
+
originalTimestamp: timestamp,
|
|
612
|
+
sentAt: timestamp,
|
|
613
|
+
timestamp
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
buildEntryComponentBase(universal, componentId, experienceId, variantIndex) {
|
|
617
|
+
return {
|
|
618
|
+
...this.buildUniversalEventProperties(universal),
|
|
619
|
+
componentType: 'Entry',
|
|
620
|
+
componentId,
|
|
621
|
+
experienceId,
|
|
622
|
+
variantIndex: variantIndex ?? 0
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
buildComponentView(args) {
|
|
626
|
+
const { componentId, componentViewId, experienceId, variantIndex, viewDurationMs, ...universal } = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(ComponentViewBuilderArgs, args);
|
|
627
|
+
return {
|
|
628
|
+
...this.buildEntryComponentBase(universal, componentId, experienceId, variantIndex),
|
|
629
|
+
type: 'component',
|
|
630
|
+
componentViewId,
|
|
631
|
+
viewDurationMs
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
buildComponentClick(args) {
|
|
635
|
+
const { componentId, experienceId, variantIndex, ...universal } = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(ComponentClickBuilderArgs, args);
|
|
636
|
+
return {
|
|
637
|
+
...this.buildEntryComponentBase(universal, componentId, experienceId, variantIndex),
|
|
638
|
+
type: 'component_click'
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
buildComponentHover(args) {
|
|
642
|
+
const { componentHoverId, componentId, experienceId, hoverDurationMs, variantIndex, ...universal } = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(ComponentHoverBuilderArgs, args);
|
|
643
|
+
return {
|
|
644
|
+
...this.buildEntryComponentBase(universal, componentId, experienceId, variantIndex),
|
|
645
|
+
type: 'component_hover',
|
|
646
|
+
componentHoverId,
|
|
647
|
+
hoverDurationMs
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
buildFlagView(args) {
|
|
651
|
+
return {
|
|
652
|
+
...this.buildComponentView(args),
|
|
653
|
+
componentType: 'Variable'
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
buildIdentify(args) {
|
|
657
|
+
const { traits = {}, userId, ...universal } = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(IdentifyBuilderArgs, args);
|
|
658
|
+
return {
|
|
659
|
+
...this.buildUniversalEventProperties(universal),
|
|
660
|
+
type: 'identify',
|
|
661
|
+
traits,
|
|
662
|
+
userId
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
buildPageView(args = {}) {
|
|
666
|
+
const { properties = {}, ...universal } = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(PageViewBuilderArgs, args);
|
|
667
|
+
const pageProperties = this.getPageProperties();
|
|
668
|
+
const merged = (0, object_namespaceObject.merge)({
|
|
669
|
+
...pageProperties,
|
|
670
|
+
title: pageProperties.title ?? DEFAULT_PAGE_PROPERTIES.title
|
|
671
|
+
}, properties);
|
|
672
|
+
const { context: { screen: _, ...universalContext }, ...universalProperties } = this.buildUniversalEventProperties(universal);
|
|
673
|
+
const context = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(optimization_api_schemas_namespaceObject.PageEventContext, universalContext);
|
|
674
|
+
return {
|
|
675
|
+
...universalProperties,
|
|
676
|
+
context,
|
|
677
|
+
type: 'page',
|
|
678
|
+
properties: merged
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
buildScreenView(args) {
|
|
682
|
+
const { name, properties, ...universal } = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(ScreenViewBuilderArgs, args);
|
|
683
|
+
const { context: { page: _, ...universalContext }, ...universalProperties } = this.buildUniversalEventProperties(universal);
|
|
684
|
+
const context = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(optimization_api_schemas_namespaceObject.ScreenEventContext, universalContext);
|
|
685
|
+
return {
|
|
686
|
+
...universalProperties,
|
|
687
|
+
context,
|
|
688
|
+
type: 'screen',
|
|
689
|
+
name,
|
|
690
|
+
properties
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
buildTrack(args) {
|
|
694
|
+
const { event, properties = {}, ...universal } = (0, optimization_api_schemas_namespaceObject.parseWithFriendlyError)(TrackBuilderArgs, args);
|
|
695
|
+
return {
|
|
696
|
+
...this.buildUniversalEventProperties(universal),
|
|
697
|
+
type: 'track',
|
|
698
|
+
event,
|
|
699
|
+
properties
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
const builders_EventBuilder = EventBuilder;
|
|
691
704
|
})();
|
|
692
705
|
exports.ApiClient = __webpack_exports__.ApiClient;
|
|
693
706
|
exports.DEFAULT_PAGE_PROPERTIES = __webpack_exports__.DEFAULT_PAGE_PROPERTIES;
|