@levo-so/core 0.1.35 → 0.1.37

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 (51) hide show
  1. package/dist/client.d.ts +81 -0
  2. package/dist/constants/media.d.ts +1 -1
  3. package/dist/control/audience.d.ts +22 -0
  4. package/dist/control/audience.d.ts.map +1 -0
  5. package/dist/control/index.d.ts +23 -0
  6. package/dist/control/index.d.ts.map +1 -0
  7. package/dist/httpClient.d.ts +13 -0
  8. package/dist/index.d.ts +1 -2
  9. package/dist/index.js +1196 -70
  10. package/dist/logger/batch.d.ts +3 -10
  11. package/dist/logger/batch.d.ts.map +1 -1
  12. package/dist/logger/index.d.ts +22 -0
  13. package/dist/logger/index.d.ts.map +1 -0
  14. package/dist/modules/blog.d.ts +10 -0
  15. package/dist/modules/blog.d.ts.map +1 -0
  16. package/dist/modules/collection.d.ts +25 -0
  17. package/dist/modules/collection.d.ts.map +1 -0
  18. package/dist/{plugins/LevoMedia.d.ts → modules/media.d.ts} +6 -4
  19. package/dist/modules/media.d.ts.map +1 -0
  20. package/dist/modules/membership.d.ts +21 -0
  21. package/dist/modules/membership.d.ts.map +1 -0
  22. package/dist/types/audience.d.ts +35 -2
  23. package/dist/types/audience.d.ts.map +1 -1
  24. package/dist/utils/listToX.d.ts +3 -0
  25. package/dist/utils/listToX.d.ts.map +1 -0
  26. package/dist/utils/lock.d.ts.map +1 -1
  27. package/package.json +5 -3
  28. package/dist/LevoClient.d.ts +0 -38
  29. package/dist/chunk-OT564SO4.js +0 -69
  30. package/dist/chunk-QJSKNLTV.js +0 -9
  31. package/dist/chunk-ZLLCLSGE.js +0 -8
  32. package/dist/plugins/LevoAudience.d.ts +0 -32
  33. package/dist/plugins/LevoAudience.d.ts.map +0 -1
  34. package/dist/plugins/LevoAudience.js +0 -561
  35. package/dist/plugins/LevoBlog.d.ts +0 -8
  36. package/dist/plugins/LevoBlog.d.ts.map +0 -1
  37. package/dist/plugins/LevoBlog.js +0 -21
  38. package/dist/plugins/LevoCollection.d.ts +0 -23
  39. package/dist/plugins/LevoCollection.d.ts.map +0 -1
  40. package/dist/plugins/LevoCollection.js +0 -47
  41. package/dist/plugins/LevoLogger.d.ts +0 -32
  42. package/dist/plugins/LevoLogger.d.ts.map +0 -1
  43. package/dist/plugins/LevoLogger.js +0 -193
  44. package/dist/plugins/LevoMedia.d.ts.map +0 -1
  45. package/dist/plugins/LevoMedia.js +0 -13
  46. package/dist/plugins/LevoMembership.d.ts +0 -38
  47. package/dist/plugins/LevoMembership.d.ts.map +0 -1
  48. package/dist/plugins/LevoMembership.js +0 -104
  49. package/dist/plugins/LevoPlugin.d.ts +0 -6
  50. package/dist/plugins/LevoPlugin.d.ts.map +0 -1
  51. package/dist/plugins/LevoPlugin.js +0 -1
package/dist/index.js CHANGED
@@ -1,92 +1,1218 @@
1
- export { LevoError, LocalStorageLock, getLevoError } from './chunk-OT564SO4.js';
2
- export { LevoOAuthProviderList } from './chunk-ZLLCLSGE.js';
3
- export { LevoPlugin } from './chunk-QJSKNLTV.js';
1
+ import { onUserActivity } from '@analytics/activity-utils';
2
+ import { getVisitorSource } from '@analytics/visitor-source';
3
+ import { Analytics } from 'analytics';
4
+ import getUserLocale from 'get-user-locale';
5
+ import { WretchError } from 'wretch/resolver';
4
6
  import wretch from 'wretch';
5
- import QueryStringAddon from 'wretch/addons/queryString';
7
+ import queryStringAddon from 'wretch/addons/queryString';
6
8
 
7
- var workspaceIdRegex = /^W[A-Z0-9]{7}$/;
8
- var LevoClient = class {
9
- appName;
10
- #workspace;
11
- #apiUrl;
12
- #insightsUrl;
13
- #NODE_ENV;
14
- #APP_MODE;
15
- #pageContext = {
16
- url: typeof window !== "undefined" ? window?.location?.href : "",
17
- referrer: typeof document !== "undefined" ? document?.referrer : "",
18
- title: typeof document !== "undefined" ? document?.title : ""
19
- };
20
- constructor(props) {
21
- const defaultProps = {
22
- workspace: null,
23
- apiUrl: "https://public-api.levo.so",
24
- insightsUrl: "/.levo/insights/api",
25
- NODE_ENV: "production"
26
- };
27
- const finalProps = { ...defaultProps, ...props };
28
- if (props.workspace) {
29
- if (!workspaceIdRegex.test(props.workspace)) {
30
- throw new Error(
31
- `Invalid workspace ID: ${props.workspace}. Workspace ID must be a string of the format "W[A-Z0-9]{7}".`
9
+ // src/control/audience.ts
10
+
11
+ // src/utils/isIncognito.ts
12
+ var isIncognito = () => new Promise((resolve, reject) => {
13
+ let browserName = "Unknown";
14
+ function __callback(isPrivate) {
15
+ resolve({
16
+ isPrivate,
17
+ browserName
18
+ });
19
+ }
20
+ function identifyChromium() {
21
+ const ua = navigator.userAgent;
22
+ if (ua.match(/Chrome/)) {
23
+ if (navigator.brave !== void 0) {
24
+ return "Brave";
25
+ }
26
+ if (ua.match(/Edg/)) {
27
+ return "Edge";
28
+ }
29
+ if (ua.match(/OPR/)) {
30
+ return "Opera";
31
+ }
32
+ return "Chrome";
33
+ }
34
+ return "Chromium";
35
+ }
36
+ function assertEvalToString(value) {
37
+ return value === eval.toString().length;
38
+ }
39
+ function isSafari() {
40
+ const v = navigator.vendor;
41
+ return v !== void 0 && v.indexOf("Apple") === 0 && assertEvalToString(37);
42
+ }
43
+ function isChrome() {
44
+ const v = navigator.vendor;
45
+ return v !== void 0 && v.indexOf("Google") === 0 && assertEvalToString(33);
46
+ }
47
+ function isFirefox() {
48
+ return document.documentElement !== void 0 && document.documentElement.style.MozAppearance !== void 0 && assertEvalToString(37);
49
+ }
50
+ function isMSIE() {
51
+ return navigator.msSaveBlob !== void 0 && assertEvalToString(39);
52
+ }
53
+ function newSafariTest() {
54
+ const tmp_name = String(Math.random());
55
+ try {
56
+ const db = window.indexedDB.open(tmp_name, 1);
57
+ db.onupgradeneeded = (i) => {
58
+ const res = i.target?.result;
59
+ try {
60
+ res.createObjectStore("test", {
61
+ autoIncrement: true
62
+ }).put(new Blob());
63
+ __callback(false);
64
+ } catch (e) {
65
+ let message = e;
66
+ if (e instanceof Error) {
67
+ message = e.message ?? e;
68
+ }
69
+ if (typeof message !== "string") {
70
+ return __callback(false);
71
+ }
72
+ const matchesExpectedError = /BlobURLs are not yet supported/.test(
73
+ message
74
+ );
75
+ return __callback(matchesExpectedError);
76
+ } finally {
77
+ res.close();
78
+ window.indexedDB.deleteDatabase(tmp_name);
79
+ }
80
+ };
81
+ } catch (e) {
82
+ return __callback(false);
83
+ }
84
+ }
85
+ function oldSafariTest() {
86
+ const openDB = window.openDatabase;
87
+ const storage = window.localStorage;
88
+ try {
89
+ openDB(null, null, null, null);
90
+ } catch (e) {
91
+ return __callback(true);
92
+ }
93
+ try {
94
+ storage.setItem("test", "1");
95
+ storage.removeItem("test");
96
+ } catch (e) {
97
+ return __callback(true);
98
+ }
99
+ return __callback(false);
100
+ }
101
+ function safariPrivateTest() {
102
+ if (navigator.maxTouchPoints !== void 0) {
103
+ newSafariTest();
104
+ } else {
105
+ oldSafariTest();
106
+ }
107
+ }
108
+ function getQuotaLimit() {
109
+ const w = window;
110
+ if (w.performance !== void 0 && w.performance.memory !== void 0 && w.performance.memory.jsHeapSizeLimit !== void 0) {
111
+ return performance.memory.jsHeapSizeLimit;
112
+ }
113
+ return 1073741824;
114
+ }
115
+ function storageQuotaChromePrivateTest() {
116
+ navigator.webkitTemporaryStorage.queryUsageAndQuota(
117
+ (_, quota) => {
118
+ const quotaInMib = Math.round(quota / (1024 * 1024));
119
+ const quotaLimitInMib = Math.round(getQuotaLimit() / (1024 * 1024)) * 2;
120
+ __callback(quotaInMib < quotaLimitInMib);
121
+ },
122
+ (e) => {
123
+ reject(
124
+ new Error(
125
+ `detectIncognito somehow failed to query storage quota: ${e.message}`
126
+ )
32
127
  );
33
128
  }
129
+ );
130
+ }
131
+ function oldChromePrivateTest() {
132
+ const fs = window.webkitRequestFileSystem;
133
+ const success = () => {
134
+ __callback(false);
135
+ };
136
+ const error = () => {
137
+ __callback(true);
138
+ };
139
+ fs(0, 1, success, error);
140
+ }
141
+ function chromePrivateTest() {
142
+ if (self.Promise !== void 0 && self.Promise.allSettled !== void 0) {
143
+ storageQuotaChromePrivateTest();
144
+ } else {
145
+ oldChromePrivateTest();
146
+ }
147
+ }
148
+ function firefoxPrivateTest() {
149
+ __callback(navigator.serviceWorker === void 0);
150
+ }
151
+ function msiePrivateTest() {
152
+ __callback(window.indexedDB === void 0);
153
+ }
154
+ function main() {
155
+ if (isSafari()) {
156
+ browserName = "Safari";
157
+ safariPrivateTest();
158
+ } else if (isChrome()) {
159
+ browserName = identifyChromium();
160
+ chromePrivateTest();
161
+ } else if (isFirefox()) {
162
+ browserName = "Firefox";
163
+ firefoxPrivateTest();
164
+ } else if (isMSIE()) {
165
+ browserName = "Internet Explorer";
166
+ msiePrivateTest();
167
+ } else {
168
+ reject(new Error("detectIncognito cannot determine the browser"));
34
169
  }
35
- this.#workspace = finalProps.workspace;
36
- this.#apiUrl = finalProps.apiUrl;
37
- this.#insightsUrl = finalProps.insightsUrl;
38
- this.#NODE_ENV = finalProps.NODE_ENV;
39
- this.#APP_MODE = finalProps.APP_MODE;
40
- this.appName = finalProps.appName;
41
170
  }
42
- get workspace() {
43
- return this.#workspace;
171
+ main();
172
+ });
173
+ var isIncognito_default = isIncognito;
174
+
175
+ // src/utils/getUserProperties.ts
176
+ var getGPUInfo = () => {
177
+ const canvas = document.createElement("canvas");
178
+ const gl = canvas?.getContext("webgl") || canvas?.getContext("experimental-webgl");
179
+ if (!gl) {
180
+ return null;
181
+ }
182
+ const debugInfo = gl?.getExtension("WEBGL_debug_renderer_info");
183
+ return debugInfo ? gl?.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) : null;
184
+ };
185
+ var getUserProperties = async () => {
186
+ let locale = "";
187
+ let timezone = "";
188
+ let dark_mode = false;
189
+ let private_mode = false;
190
+ const properties = {};
191
+ if (!window) {
192
+ return {
193
+ locale,
194
+ timezone,
195
+ dark_mode,
196
+ private_mode,
197
+ properties
198
+ };
199
+ }
200
+ try {
201
+ ({ isPrivate: private_mode } = await isIncognito_default());
202
+ } catch (e) {
203
+ console.error(e);
204
+ }
205
+ try {
206
+ dark_mode = window.matchMedia?.("(prefers-color-scheme: dark)").matches;
207
+ } catch (e) {
208
+ console.error(e);
209
+ }
210
+ try {
211
+ timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
212
+ } catch (e) {
213
+ console.error(e);
214
+ }
215
+ try {
216
+ locale = getUserLocale();
217
+ } catch (e) {
218
+ console.error(e);
219
+ }
220
+ if (navigator && "connection" in navigator) {
221
+ const connection = navigator.connection || navigator?.mozConnection || navigator.webkitConnection;
222
+ properties.network_type = connection.effectiveType;
223
+ }
224
+ properties.width = window?.innerWidth;
225
+ properties.height = window?.innerHeight;
226
+ properties.pixel_ratio = window?.devicePixelRatio;
227
+ if (screen) {
228
+ properties.screen_width = screen?.width;
229
+ properties.screen_height = screen?.height;
230
+ properties.color_depth = screen?.colorDepth;
231
+ properties.orientation = screen?.orientation?.type;
232
+ }
233
+ if (navigator && "getBattery" in navigator) {
234
+ const battery = await navigator?.getBattery();
235
+ if (battery) {
236
+ properties.battery_level = Number((battery?.level * 100).toFixed(0));
237
+ properties.battery_charging = battery?.charging;
238
+ properties.battery_discharging_time = battery?.dischargingTime;
239
+ properties.battery_full_charge_capacity = battery?.fullChargeCapacity;
240
+ properties.battery_charging_time = battery?.chargingTime;
241
+ }
242
+ }
243
+ if (navigator && "deviceMemory" in navigator) {
244
+ properties.device_memory = navigator?.deviceMemory;
245
+ }
246
+ const supportsTouch = "ontouchstart" in window || typeof navigator?.maxTouchPoints !== "undefined" && navigator?.maxTouchPoints > 0;
247
+ properties.touch_supported = supportsTouch;
248
+ if ("hardwareConcurrency" in navigator) {
249
+ properties.hardware_concurrency = navigator?.hardwareConcurrency;
44
250
  }
45
- get apiUrl() {
46
- return this.#apiUrl;
251
+ if (navigator && "mediaDevices" in navigator) {
252
+ const mediaDevices = navigator?.mediaDevices;
253
+ const devices = await mediaDevices?.enumerateDevices();
254
+ const hasCamera = devices.some((device) => device?.kind === "videoinput");
255
+ properties.camera_supported = hasCamera;
256
+ const hasMicrophone = devices.some(
257
+ (device) => device?.kind === "audioinput"
258
+ );
259
+ properties.microphone_supported = hasMicrophone;
47
260
  }
48
- get insightsUrl() {
49
- return this.#insightsUrl;
261
+ properties.gpu = getGPUInfo();
262
+ return {
263
+ locale,
264
+ timezone,
265
+ dark_mode,
266
+ private_mode,
267
+ properties
268
+ };
269
+ };
270
+
271
+ // src/utils/LevoError.ts
272
+ var LevoError = class extends Error {
273
+ code;
274
+ title;
275
+ message;
276
+ status;
277
+ constructor(data) {
278
+ super(data?.message || data?.description);
279
+ this.name = "Levo Request Error";
280
+ this.status = data?.status;
281
+ this.code = data?.code;
282
+ this.message = data?.message || data?.description;
283
+ this.title = data?.title;
50
284
  }
51
- get NODE_ENV() {
52
- return this.#NODE_ENV;
285
+ };
286
+
287
+ // src/utils/getLevoError.ts
288
+ var getLevoError = (error) => {
289
+ if (error instanceof WretchError) {
290
+ const errorResponse = error?.json;
291
+ if (typeof errorResponse === "object" && errorResponse?.content) {
292
+ const errorMessage = errorResponse?.content;
293
+ return new LevoError(errorMessage);
294
+ }
53
295
  }
54
- get APP_MODE() {
55
- return this.#APP_MODE;
296
+ let displayMessage = error?.message || "Something unexpected happened.";
297
+ switch (error?.message) {
298
+ case "Network Error":
299
+ displayMessage = "Couldn't connect to our servers.";
300
+ break;
56
301
  }
57
- updateWorkspace(workspace) {
58
- this.#workspace = workspace;
302
+ return new LevoError({
303
+ status: "500",
304
+ title: "Network Error",
305
+ description: displayMessage,
306
+ code: "UNKNOWN_ERROR"
307
+ });
308
+ };
309
+
310
+ // src/utils/lock.ts
311
+ var LocalStorageLock = class {
312
+ key;
313
+ constructor(lockKey) {
314
+ this.key = lockKey;
59
315
  }
60
- getPageContext() {
61
- return this.#pageContext;
316
+ acquireLock(expiryMs = 5e3) {
317
+ const now = Date.now();
318
+ const lockValue = localStorage.getItem(this.key);
319
+ if (lockValue) {
320
+ const timestamp = Number(lockValue);
321
+ if (now - timestamp < expiryMs) {
322
+ return false;
323
+ }
324
+ }
325
+ localStorage.setItem(this.key, now.toString());
326
+ setTimeout(() => {
327
+ if (this.isLocked(expiryMs)) {
328
+ this.releaseLock();
329
+ }
330
+ }, expiryMs);
331
+ return true;
62
332
  }
63
- updatePageContext(pageContext) {
64
- this.#pageContext = pageContext;
333
+ releaseLock() {
334
+ localStorage.removeItem(this.key);
65
335
  }
66
- get fetch() {
67
- const options = {
68
- credentials: "include",
69
- signal: AbortSignal.timeout(3e4),
70
- // 30 seconds timeout,
71
- headers: {}
336
+ isLocked(expiryMs = 5e3) {
337
+ const lockValue = localStorage.getItem(this.key);
338
+ if (!lockValue) {
339
+ return false;
340
+ }
341
+ const timestamp = Number(lockValue);
342
+ return Date.now() - timestamp < expiryMs;
343
+ }
344
+ };
345
+
346
+ // src/control/audience.ts
347
+ var createLevoAudienceModule = (core, httpClient) => {
348
+ const _IDLE_THROTTLE = 1 * 1e3;
349
+ const _IDLE_TIMEOUT = 60 * 1e3;
350
+ let instance = null;
351
+ let idle_listener = null;
352
+ const storage_keys = {
353
+ identify: "lock:lv_aud_identify",
354
+ open_tabs: "lv_insights_ot",
355
+ current_tab: "lv_insights_ct",
356
+ all_tabs: "lv_insights_at"
357
+ };
358
+ let _session = "";
359
+ let _device = "";
360
+ let is_identified = false;
361
+ let _batch = [];
362
+ const getReferrer = () => {
363
+ if (typeof document === "undefined") {
364
+ return {};
365
+ }
366
+ const {
367
+ type,
368
+ referrer,
369
+ data = {}
370
+ } = getVisitorSource({
371
+ referrer: document.referrer,
372
+ currentUrl: window.location.href,
373
+ mapper: null
374
+ });
375
+ const dataKeys = Object.keys(data);
376
+ for (const key of dataKeys) {
377
+ if (data[key] && Array.isArray(data[key]) && data[key].length > 0) {
378
+ data[key] = data[key]?.[0];
379
+ }
380
+ }
381
+ return { type, referrer, data, raw: document.referrer };
382
+ };
383
+ const getCurrentTabId = () => {
384
+ try {
385
+ if (typeof window === "undefined" || !("sessionStorage" in window)) {
386
+ return "";
387
+ }
388
+ const CURRENT_TAB_LOCAL_STORAGE_KEY = storage_keys.current_tab;
389
+ return window.sessionStorage.getItem(CURRENT_TAB_LOCAL_STORAGE_KEY) || "";
390
+ } catch (_) {
391
+ return "";
392
+ }
393
+ };
394
+ const getTabCount = () => {
395
+ try {
396
+ if (typeof window === "undefined" || !("localStorage" in window)) {
397
+ return 0;
398
+ }
399
+ const OT_LOCAL_STORAGE_KEY = storage_keys.open_tabs;
400
+ return Number(window.localStorage.getItem(OT_LOCAL_STORAGE_KEY)) || 0;
401
+ } catch (_) {
402
+ return 0;
403
+ }
404
+ };
405
+ const getActivityStatus = () => {
406
+ const status = idle_listener?.getStatus();
407
+ if (!status) {
408
+ return null;
409
+ }
410
+ return {
411
+ status: status.isIdle ? "idle" : "active",
412
+ seconds: status.isIdle ? status.idle : status.active
72
413
  };
73
- if (this.workspace) {
74
- options.headers = {
75
- ...options?.headers || {},
76
- "Levo-Workspace": this.workspace
77
- };
414
+ };
415
+ const identify = async (options) => {
416
+ if (!instance) {
417
+ return;
78
418
  }
79
- if (this.#pageContext && typeof this.#pageContext === "object" && Object.keys(this.#pageContext).length > 0) {
80
- options.headers = {
81
- ...options?.headers || {},
82
- "Levo-Page-Context": encodeURIComponent(
83
- JSON.stringify(this.#pageContext)
84
- )
419
+ const withLock = options?.withLock ?? true;
420
+ const referrer = getReferrer();
421
+ const traits = await getUserProperties();
422
+ await instance.identify("", {
423
+ ...traits,
424
+ referrer,
425
+ withLock
426
+ });
427
+ };
428
+ const request = (url, data) => {
429
+ const headers = {
430
+ Accept: "application/json",
431
+ "Content-Type": "application/json"
432
+ };
433
+ return httpClient.instance.url(core?.insightsUrl, true).url(url).options({
434
+ keepAlive: true
435
+ }).headers(headers).post(data).json();
436
+ };
437
+ const initiate = async (properties) => {
438
+ if (core.NODE_ENV === "development") {
439
+ return;
440
+ }
441
+ const plugin = {
442
+ name: core.workspace,
443
+ track: ({ payload }) => {
444
+ if (!core?.insightsUrl || !core.workspace) {
445
+ return;
446
+ }
447
+ const payloadProperties = payload?.properties || {};
448
+ const collectInput = {
449
+ session_id: _session,
450
+ device_id: _device,
451
+ event: payload.event,
452
+ version: payload.version || 1,
453
+ workspace_id: core.workspace,
454
+ properties: {
455
+ ...properties,
456
+ ...payloadProperties,
457
+ version: void 0,
458
+ resource: void 0,
459
+ identifier: void 0,
460
+ hostname: void 0,
461
+ pathname: void 0,
462
+ url: void 0,
463
+ page_title: void 0,
464
+ created_at: void 0
465
+ },
466
+ hostname: payload?.hostname || window.location.hostname,
467
+ pathname: payload?.pathname || window.location.pathname,
468
+ url: payload?.url || window.location.href,
469
+ page_title: payload?.page_title || document.title,
470
+ resource: payloadProperties?.resource || "page",
471
+ identifier: payloadProperties?.identifier || properties?.id,
472
+ created_at: payload?.created_at || (/* @__PURE__ */ new Date()).toISOString(),
473
+ tab_id: getCurrentTabId(),
474
+ tab_count: getTabCount()
475
+ };
476
+ let isQueued = false;
477
+ try {
478
+ isQueued = navigator.sendBeacon(
479
+ `${core?.insightsUrl}/v1/insights/event/collect`,
480
+ JSON.stringify(collectInput)
481
+ );
482
+ } catch (e) {
483
+ }
484
+ if (!isQueued) {
485
+ request("/v1/insights/event/collect", collectInput);
486
+ }
487
+ },
488
+ page: ({ payload }) => {
489
+ if (!core?.insightsUrl) {
490
+ return;
491
+ }
492
+ const payloadProperties = payload?.properties || {};
493
+ track("page.view", {
494
+ ...properties,
495
+ ...payloadProperties,
496
+ title: document.title,
497
+ identifier: properties.id,
498
+ resource: "page"
499
+ });
500
+ },
501
+ identify: ({ payload }) => {
502
+ if (!core?.insightsUrl || !core.workspace) {
503
+ return;
504
+ }
505
+ const withLock = payload?.traits?.withLock ?? true;
506
+ const welcomeInput = {
507
+ private_mode: payload.traits.private_mode,
508
+ dark_mode: payload.traits.dark_mode,
509
+ timezone: payload.traits.timezone,
510
+ locale: payload.traits.locale,
511
+ referrer: payload.traits.referrer,
512
+ properties: payload.traits.properties,
513
+ workspace_id: core.workspace,
514
+ hostname: window.location.hostname,
515
+ pathname: window.location.pathname,
516
+ page_title: document.title,
517
+ url: window.location.href,
518
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
519
+ tab_id: getCurrentTabId(),
520
+ tab_count: getTabCount()
521
+ };
522
+ let identifyLock = null;
523
+ if (withLock) {
524
+ identifyLock = new LocalStorageLock(storage_keys.identify);
525
+ }
526
+ if (!identifyLock || identifyLock.acquireLock()) {
527
+ request(`/v1/insights/event/welcome`, welcomeInput).then((data) => {
528
+ is_identified = true;
529
+ _session = data.content.data.session;
530
+ _device = data.content.data.device;
531
+ let isQueued = false;
532
+ try {
533
+ isQueued = navigator.sendBeacon(
534
+ `${core?.insightsUrl}/v1/insights/event/bulk?workspace=${core?.workspace}`,
535
+ JSON.stringify(_batch)
536
+ );
537
+ } catch (e) {
538
+ }
539
+ if (!isQueued) {
540
+ request("/v1/insights/event/bulk", _batch);
541
+ }
542
+ _batch = [];
543
+ identifyLock?.releaseLock();
544
+ }).catch((e) => {
545
+ identifyLock?.releaseLock();
546
+ return getLevoError(e);
547
+ });
548
+ }
549
+ }
550
+ };
551
+ instance = Analytics({
552
+ app: core.workspace || "",
553
+ plugins: [plugin]
554
+ });
555
+ await identify();
556
+ startActivityListener();
557
+ return instance.page({
558
+ resource: "page",
559
+ identifier: properties.id
560
+ });
561
+ };
562
+ const startActivityListener = () => {
563
+ if (typeof document !== "undefined" && !idle_listener) {
564
+ idle_listener = onUserActivity({
565
+ timeout: _IDLE_TIMEOUT,
566
+ throttle: _IDLE_THROTTLE,
567
+ onIdle: (activeForSeconds) => {
568
+ track("user.idle", {
569
+ seconds_active: activeForSeconds
570
+ });
571
+ },
572
+ onWakeUp: (idleForSeconds) => {
573
+ track("user.active", {
574
+ seconds_idle: idleForSeconds
575
+ });
576
+ }
577
+ });
578
+ }
579
+ return null;
580
+ };
581
+ const bounce = async (properties) => {
582
+ const activity_status = getActivityStatus();
583
+ if (activity_status) {
584
+ if (activity_status?.status === "idle") {
585
+ properties.seconds_idle = activity_status.seconds;
586
+ } else {
587
+ properties.seconds_active = activity_status.seconds;
588
+ }
589
+ }
590
+ track("page.bounce", properties);
591
+ };
592
+ const track = async (event, properties) => {
593
+ if (!core.workspace) {
594
+ return;
595
+ }
596
+ if (instance && is_identified) {
597
+ return instance.track(event, properties);
598
+ }
599
+ return _batch.push({
600
+ event,
601
+ version: properties?.version || 1,
602
+ properties: {
603
+ ...properties,
604
+ version: void 0,
605
+ resource: void 0,
606
+ identifier: void 0,
607
+ hostname: void 0,
608
+ pathname: void 0,
609
+ url: void 0,
610
+ page_title: void 0,
611
+ created_at: void 0
612
+ },
613
+ hostname: window.location.hostname,
614
+ pathname: window.location.pathname,
615
+ url: window.location.href,
616
+ page_title: document.title,
617
+ resource: properties?.resource || "page",
618
+ identifier: properties?.identifier || properties?.id,
619
+ workspace_id: core.workspace,
620
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
621
+ tab_id: getCurrentTabId(),
622
+ tab_count: getTabCount()
623
+ });
624
+ };
625
+ return {
626
+ get instance() {
627
+ return instance;
628
+ },
629
+ get is_identified() {
630
+ return is_identified;
631
+ },
632
+ storage_keys,
633
+ initiate,
634
+ identify,
635
+ track,
636
+ bounce
637
+ };
638
+ };
639
+
640
+ // src/control/index.ts
641
+ var workspaceIdRegex = /^W[A-Z0-9]{7}$/;
642
+ var createLevoControl = (options) => {
643
+ const {
644
+ appName,
645
+ workspace = null,
646
+ apiUrl = "https://public-api.levo.so",
647
+ insightsUrl = "/.levo/insights/api",
648
+ NODE_ENV = "",
649
+ APP_MODE = "production"
650
+ } = options;
651
+ if (workspace) {
652
+ if (!workspaceIdRegex.test(workspace)) {
653
+ throw new Error(
654
+ `Invalid workspace ID: ${workspace}. Workspace ID must be a string of the format "W[A-Z0-9]{7}".`
655
+ );
656
+ }
657
+ }
658
+ let _workspace = workspace;
659
+ return {
660
+ get workspace() {
661
+ return _workspace;
662
+ },
663
+ set workspace(value) {
664
+ if (value) {
665
+ if (!workspaceIdRegex.test(value)) {
666
+ throw new Error(
667
+ `Invalid workspace ID: ${value}. Workspace ID must be a string of the format "W[A-Z0-9]{7}".`
668
+ );
669
+ }
670
+ }
671
+ _workspace = value;
672
+ },
673
+ get appName() {
674
+ return appName;
675
+ },
676
+ get apiUrl() {
677
+ return apiUrl;
678
+ },
679
+ get insightsUrl() {
680
+ return insightsUrl;
681
+ },
682
+ get NODE_ENV() {
683
+ return NODE_ENV;
684
+ },
685
+ get APP_MODE() {
686
+ return APP_MODE;
687
+ }
688
+ };
689
+ };
690
+ var createHttpClient = (core, pageContext) => {
691
+ const wr = wretch(core.apiUrl).addon(queryStringAddon);
692
+ return {
693
+ get instance() {
694
+ const options = {
695
+ credentials: "include",
696
+ signal: AbortSignal.timeout(3e4),
697
+ // 30 seconds timeout,
698
+ headers: {}
85
699
  };
700
+ if (core.workspace) {
701
+ options.headers = {
702
+ ...options?.headers || {},
703
+ "Levo-Workspace": core.workspace
704
+ };
705
+ }
706
+ if (pageContext && typeof pageContext === "object" && Object.keys(pageContext).length > 0) {
707
+ options.headers = {
708
+ ...options?.headers || {},
709
+ "Levo-Page-Context": encodeURIComponent(JSON.stringify(pageContext))
710
+ };
711
+ }
712
+ return wr.options(options);
713
+ },
714
+ pageContext
715
+ };
716
+ };
717
+ var createLogBatch = (options = {}) => {
718
+ const { logApiUrl = "https://public-api.levo.so" } = options;
719
+ const _logApiUrl = logApiUrl;
720
+ const _logs = /* @__PURE__ */ new Map();
721
+ let activeFlush = Promise.resolve();
722
+ let nextFlush = setTimeout(() => {
723
+ }, 0);
724
+ let lastFlush = /* @__PURE__ */ new Date();
725
+ const addUniqueLog = (newLog) => {
726
+ const contentKey = JSON.stringify(newLog?.content ?? "{}");
727
+ const messageKey = newLog?.message ?? "";
728
+ _logs.set(`${messageKey}${contentKey}`, newLog);
729
+ };
730
+ const sendLogs = async (logs) => {
731
+ const url = `${_logApiUrl}/v1/apm/logs/json`;
732
+ const sendFallback = () => {
733
+ return wretch().url(url).post(logs).res().catch((e) => console.error(e));
734
+ };
735
+ try {
736
+ if (typeof fetch === "undefined") {
737
+ throw new Error("fetch is not defined");
738
+ } else if (typeof window !== "undefined" && navigator.sendBeacon) {
739
+ try {
740
+ if (!navigator.sendBeacon.bind(navigator)(url, JSON.stringify(logs))) {
741
+ return sendFallback();
742
+ }
743
+ } catch {
744
+ return sendFallback();
745
+ }
746
+ } else {
747
+ return sendFallback();
748
+ }
749
+ } catch (e) {
750
+ console.warn(`Failed to send logs to server: ${e}`);
751
+ logs.forEach((log) => addUniqueLog(log));
752
+ }
753
+ };
754
+ const flush = async () => {
755
+ const tasks = Array.from(_logs.values());
756
+ _logs.clear();
757
+ clearTimeout(nextFlush);
758
+ await activeFlush;
759
+ if (tasks.length === 0) {
760
+ lastFlush = /* @__PURE__ */ new Date();
761
+ return;
762
+ }
763
+ try {
764
+ await sendLogs(tasks);
765
+ } catch (e) {
766
+ console.log("error sending logs", e);
767
+ } finally {
768
+ lastFlush = /* @__PURE__ */ new Date();
86
769
  }
87
- return wretch(this.apiUrl, options).addon(QueryStringAddon);
770
+ };
771
+ const ingest = (log) => {
772
+ if (!logApiUrl) return;
773
+ const tasks = Array.isArray(log) ? log : [log];
774
+ tasks.forEach((task) => addUniqueLog(task));
775
+ if (_logs.size >= 50 || lastFlush.getTime() < Date.now() - 1500) {
776
+ clearTimeout(nextFlush);
777
+ activeFlush = flush();
778
+ } else {
779
+ clearTimeout(nextFlush);
780
+ nextFlush = setTimeout(() => {
781
+ activeFlush = flush();
782
+ }, 1500);
783
+ }
784
+ };
785
+ return {
786
+ ingest,
787
+ flush
788
+ };
789
+ };
790
+
791
+ // src/logger/index.ts
792
+ var isBrowser = typeof window !== "undefined";
793
+ var getMethodName = (level) => {
794
+ switch (level) {
795
+ case 0 /* debug */:
796
+ return "log";
797
+ case 1 /* info */:
798
+ return "info";
799
+ case 2 /* warn */:
800
+ return "warn";
801
+ case 3 /* error */:
802
+ return "error";
803
+ default:
804
+ return "log";
88
805
  }
89
806
  };
807
+ var createLevoLogger = (core, options = {}) => {
808
+ const {
809
+ enableRemote = core.NODE_ENV !== "development",
810
+ level: logLevel = core.NODE_ENV !== "development" ? 2 /* warn */ : 0 /* debug */,
811
+ context = {},
812
+ logApiUrl
813
+ } = options;
814
+ const batch = createLogBatch({ logApiUrl });
815
+ const format = (messages) => {
816
+ let message = "";
817
+ const formattedMessages = messages.map((arg) => {
818
+ let payload = "";
819
+ const isMessageEmpty = !message;
820
+ if (typeof arg === "string") {
821
+ payload = arg;
822
+ if (isMessageEmpty) {
823
+ message = arg;
824
+ }
825
+ } else if (arg instanceof Error) {
826
+ payload = {
827
+ message: arg.message,
828
+ name: arg.name,
829
+ stack: arg.stack
830
+ };
831
+ if (isMessageEmpty) {
832
+ message = arg.message;
833
+ }
834
+ } else if (typeof arg === "object") {
835
+ payload = arg;
836
+ } else {
837
+ payload = String(arg);
838
+ if (isMessageEmpty) {
839
+ message = String(arg);
840
+ }
841
+ }
842
+ return payload;
843
+ }).filter(Boolean);
844
+ if (!message && formattedMessages.length > 0) {
845
+ message = "Default message (Check content for details)";
846
+ }
847
+ if (formattedMessages?.length === 1 && formattedMessages[0] === message) {
848
+ return { message, content: {} };
849
+ }
850
+ return {
851
+ message,
852
+ content: formattedMessages
853
+ };
854
+ };
855
+ const log = (level, args) => {
856
+ const messages = Array.isArray(args) ? args : [args];
857
+ if (level < logLevel) {
858
+ return;
859
+ }
860
+ if (enableRemote && level === 3 /* error */) {
861
+ const { content = {}, message } = format(messages);
862
+ if (message) {
863
+ const log2 = {
864
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
865
+ level: "error",
866
+ workspace: core.workspace,
867
+ appName: core?.appName,
868
+ isBrowser,
869
+ ...context,
870
+ message,
871
+ content
872
+ };
873
+ if (isBrowser) {
874
+ log2.hostname = window.location.hostname;
875
+ log2.pathname = window.location.pathname;
876
+ log2.url = window.location.href;
877
+ log2.page_title = window.document.title;
878
+ log2.userAgent = window.navigator.userAgent;
879
+ }
880
+ batch.ingest(log2);
881
+ }
882
+ }
883
+ const method = getMethodName(level);
884
+ console[method](...messages);
885
+ };
886
+ const debug = (...args) => {
887
+ log(0 /* debug */, args);
888
+ };
889
+ const info = (...args) => {
890
+ log(1 /* info */, args);
891
+ };
892
+ const warn = (...args) => {
893
+ log(2 /* warn */, args);
894
+ };
895
+ const error = (...args) => {
896
+ log(3 /* error */, args);
897
+ };
898
+ return {
899
+ debug,
900
+ info,
901
+ warn,
902
+ error
903
+ };
904
+ };
905
+
906
+ // src/modules/blog.ts
907
+ var createLevoBlogModule = (core, httpClient, audience = null) => {
908
+ const getAllBlogs = (blog_key, data = {}, options) => {
909
+ return httpClient.instance.url(`/v1/blog/${blog_key}/post/query`).query({ ...options?.params || {} }).options({
910
+ headers: {
911
+ "Levo-Workspace": options?.workspace_id || void 0
912
+ }
913
+ }).post(data).json();
914
+ };
915
+ const getSingleBlog = (blog_key, slug, options) => {
916
+ return httpClient.instance.url(`/v1/blog/${blog_key}/post/${slug}`).query({ ...options?.params || {} }).options({
917
+ headers: {
918
+ "Levo-Workspace": options?.workspace_id || void 0
919
+ }
920
+ }).get().json();
921
+ };
922
+ return {
923
+ getAllBlogs,
924
+ getSingleBlog
925
+ };
926
+ };
927
+
928
+ // src/modules/collection.ts
929
+ var createLevoCollectionModule = (core, httpsClient, audience = null) => {
930
+ const getAllCollections = async (data = {}, options = {}) => {
931
+ return httpsClient.instance.url("/v1/bevy/collection/query").options(options).post(data).json();
932
+ };
933
+ const getCollectionByIDExpanded = async (id, options = {}) => {
934
+ return httpsClient.instance.url(`/v1/bevy/collection/${id}`).options(options).get().json();
935
+ };
936
+ const createCollection = async (data) => {
937
+ return httpsClient.instance.url("/v1/bevy/collection").post(data).json();
938
+ };
939
+ const saveCollectionData = async ({
940
+ collection_id,
941
+ data,
942
+ options = {}
943
+ }) => {
944
+ return httpsClient.instance.url(`/v1/bevy/content/${collection_id}`).options(options).post(data).json();
945
+ };
946
+ const getCollectionContentList = async ({
947
+ collection_key,
948
+ page,
949
+ search,
950
+ limit = 10,
951
+ where
952
+ }) => {
953
+ return httpsClient.instance.url(`/v1/bevy/content/${collection_key}/query`).post({
954
+ page,
955
+ limit,
956
+ search,
957
+ where
958
+ }).json();
959
+ };
960
+ const saveDraftEntry = async (collection_key, data) => {
961
+ return httpsClient.instance.url(`/v1/bevy/content/${collection_key}/save-entry`).post(data).json();
962
+ };
963
+ const getDraftEntry = async (collection_key) => {
964
+ return httpsClient.instance.url(`/v1/bevy/content/${collection_key}/list-entry`).get().json();
965
+ };
966
+ const submitDraftEntry = async (collection_key, data) => {
967
+ return httpsClient.instance.url(`/v1/bevy/content/${collection_key}/submit-entry`).post(data).json();
968
+ };
969
+ return {
970
+ getAllCollections,
971
+ getCollectionByIDExpanded,
972
+ createCollection,
973
+ saveCollectionData,
974
+ getCollectionContentList,
975
+ saveDraftEntry,
976
+ getDraftEntry,
977
+ submitDraftEntry
978
+ };
979
+ };
980
+
981
+ // src/modules/media.ts
982
+ var createLevoMediaModule = (core, httpsClient, audience = null) => {
983
+ const mediaBulkUpload = (formData, options = {}) => {
984
+ return httpsClient.instance.url("/v1/assets/media/bulk").options(options).post(formData).json();
985
+ };
986
+ const getAllMedia = async (data = {}) => {
987
+ return await httpsClient.instance.url("/v1/assets/media/query").post(data).json();
988
+ };
989
+ return {
990
+ mediaBulkUpload,
991
+ getAllMedia
992
+ };
993
+ };
994
+
995
+ // src/constants/oauthProvider.ts
996
+ var LevoOAuthProviderList = [
997
+ "google",
998
+ "linkedin",
999
+ "microsoft"
1000
+ ];
1001
+
1002
+ // src/modules/membership.ts
1003
+ var createLevoMembershipModule = (core, httpsClient, audience = null) => {
1004
+ const getOAuthURL = async (options = {}) => {
1005
+ try {
1006
+ const response = await httpsClient.instance.url("/v1/membership/auth/oauth/get-redirect-url").options(options).get().json();
1007
+ const result = response?.content?.data;
1008
+ const providers = Object.keys(result);
1009
+ if (typeof window !== "undefined") {
1010
+ for (const provider of providers) {
1011
+ const raw_url = result[provider];
1012
+ if (raw_url) {
1013
+ const url = new URL(raw_url);
1014
+ const url_params = url.searchParams;
1015
+ url_params.set("redirect_uri", window.location.href);
1016
+ if (core.workspace) {
1017
+ url_params.set("workspace_id", core.workspace);
1018
+ }
1019
+ if (httpsClient.pageContext) {
1020
+ url_params.set(
1021
+ "page_context",
1022
+ JSON.stringify(httpsClient.pageContext)
1023
+ );
1024
+ }
1025
+ result[provider] = `${url.origin}${url.pathname}?${url_params.toString()}`;
1026
+ }
1027
+ }
1028
+ }
1029
+ return result;
1030
+ } catch (_) {
1031
+ return LevoOAuthProviderList.reduce((acc, provider) => {
1032
+ acc[provider] = null;
1033
+ return acc;
1034
+ }, {});
1035
+ }
1036
+ };
1037
+ const signOut = async (options = {}) => {
1038
+ return httpsClient.instance.url("/v1/membership/auth/sign-out").options(options).post("").json();
1039
+ };
1040
+ const getMe = async (options = {}) => {
1041
+ const response = await httpsClient.instance.url("/v1/membership/auth/get-me").options(options).get().json();
1042
+ return response?.content?.data;
1043
+ };
1044
+ const updateMe = async (data, options = {}) => {
1045
+ const response = await httpsClient.instance.url("/v1/membership/auth/update-me").options(options).put(data).json();
1046
+ return response?.content?.data;
1047
+ };
1048
+ const createPassword = async (data, options = {}) => {
1049
+ const response = await httpsClient.instance.url("/v1/membership/auth/change-password").options(options).put(data).json();
1050
+ return response?.content?.data;
1051
+ };
1052
+ const isLoggedIn = async (options = {}) => {
1053
+ try {
1054
+ const account = await getMe(options);
1055
+ return account;
1056
+ } catch (_) {
1057
+ return null;
1058
+ }
1059
+ };
1060
+ const requestMagicLink = async (data, options = {}) => {
1061
+ if (typeof window !== "undefined" && !data.redirect_uri) {
1062
+ data.redirect_uri = window.location.href;
1063
+ }
1064
+ const response = await httpsClient.instance.url("/v1/membership/auth/request-magic-link").options(options).post(data).json();
1065
+ return response?.content?.data;
1066
+ };
1067
+ const requestOtp = async (data, options = {}) => {
1068
+ const response = await httpsClient.instance.url("/v1/membership/auth/request-otp").options(options).post(data).json();
1069
+ return response?.content?.data;
1070
+ };
1071
+ const signInWithOtp = async (data, options = {}) => {
1072
+ const response = await httpsClient.instance.url("/v1/membership/auth/signin-with-otp").options(options).post(data).json();
1073
+ return response?.content?.data;
1074
+ };
1075
+ const signInWithPassword = async (data, options = {}) => {
1076
+ const response = await httpsClient.instance.url("/v1/membership/auth/signin-with-password").options(options).post(data).json();
1077
+ return response?.content?.data;
1078
+ };
1079
+ const signUpWithPassword = async (data, options = {}) => {
1080
+ const response = await httpsClient.instance.url("/v1/membership/auth/signup-with-password").options(options).post(data).json();
1081
+ return response?.content?.data;
1082
+ };
1083
+ return {
1084
+ getOAuthURL,
1085
+ signOut,
1086
+ getMe,
1087
+ updateMe,
1088
+ createPassword,
1089
+ isLoggedIn,
1090
+ requestMagicLink,
1091
+ requestOtp,
1092
+ signInWithOtp,
1093
+ signInWithPassword,
1094
+ signUpWithPassword
1095
+ };
1096
+ };
1097
+
1098
+ // src/client.ts
1099
+ var createLevoClient = (options) => {
1100
+ const {
1101
+ pageContext = {
1102
+ url: typeof window !== "undefined" ? window?.location?.href : "",
1103
+ referrer: typeof document !== "undefined" ? document?.referrer : "",
1104
+ title: typeof document !== "undefined" ? document?.title : ""
1105
+ },
1106
+ loggerOptions = {
1107
+ logApiUrl: "https://public-api.levo.so"
1108
+ },
1109
+ ...coreOptions
1110
+ } = options;
1111
+ let _pageContext = pageContext;
1112
+ const core = createLevoControl(coreOptions);
1113
+ const httpsClient = createHttpClient(core, _pageContext);
1114
+ const audience = createLevoAudienceModule(core, httpsClient);
1115
+ const blog = createLevoBlogModule(core, httpsClient, audience);
1116
+ const membership = createLevoMembershipModule(core, httpsClient, audience);
1117
+ const collection = createLevoCollectionModule(core, httpsClient, audience);
1118
+ const media = createLevoMediaModule(core, httpsClient, audience);
1119
+ const logger = createLevoLogger(core, loggerOptions);
1120
+ const updatePageContext = (newContext) => {
1121
+ _pageContext = Object.assign({}, _pageContext, newContext);
1122
+ };
1123
+ const updateWorkspace = (workspace) => {
1124
+ core.workspace = workspace;
1125
+ };
1126
+ return {
1127
+ get apiUrl() {
1128
+ return core.apiUrl;
1129
+ },
1130
+ get insightsUrl() {
1131
+ return core.insightsUrl;
1132
+ },
1133
+ get workspace() {
1134
+ return core.workspace;
1135
+ },
1136
+ get audience() {
1137
+ return audience;
1138
+ },
1139
+ get blog() {
1140
+ return blog;
1141
+ },
1142
+ get membership() {
1143
+ return membership;
1144
+ },
1145
+ get collection() {
1146
+ return collection;
1147
+ },
1148
+ get media() {
1149
+ return media;
1150
+ },
1151
+ get logger() {
1152
+ return logger;
1153
+ },
1154
+ get fetch() {
1155
+ return httpsClient.instance;
1156
+ },
1157
+ get APP_MODE() {
1158
+ return core.APP_MODE;
1159
+ },
1160
+ get pageContext() {
1161
+ return _pageContext;
1162
+ },
1163
+ updatePageContext,
1164
+ updateWorkspace
1165
+ };
1166
+ };
1167
+
1168
+ // src/utils/listToX.ts
1169
+ var listToRecord = (columns) => {
1170
+ return columns.reduce((prev, current) => {
1171
+ prev[current] = current;
1172
+ return prev;
1173
+ }, {});
1174
+ };
1175
+
1176
+ // src/types/audience.ts
1177
+ var AnalyticsEventsList = [
1178
+ // Bevy Events
1179
+ "bevy.collection.filled",
1180
+ "bevy.collection.submitted",
1181
+ "bevy.collection.view",
1182
+ // Block Events
1183
+ "block.view",
1184
+ // Blog Events
1185
+ "blog.post.view",
1186
+ // Event Events
1187
+ "event.booking.confirmed",
1188
+ "event.booking.initiated",
1189
+ "event.booking.pending",
1190
+ "event.coupon.applied",
1191
+ "event.event.view",
1192
+ // Form Events
1193
+ "form.change",
1194
+ "form.submit",
1195
+ // Membership Events
1196
+ "membership.account.signin",
1197
+ "membership.account.signout",
1198
+ "membership.account.signup",
1199
+ // UI Events
1200
+ "button.click",
1201
+ "page.bounce",
1202
+ "page.click",
1203
+ "page.copy",
1204
+ "page.impression",
1205
+ "page.scroll",
1206
+ "page.view",
1207
+ "page.metrics",
1208
+ "page.selection",
1209
+ "page.speedtest",
1210
+ // User Activity Events
1211
+ "user.active",
1212
+ "user.speedtest",
1213
+ "user.idle"
1214
+ ];
1215
+ var AnalyticsEvents = listToRecord(AnalyticsEventsList);
90
1216
 
91
1217
  // src/constants/collection/fieldInterfaceFormat.ts
92
1218
  var formatsByInterface = {
@@ -297,4 +1423,4 @@ var formatImagePath = (string) => {
297
1423
  return "";
298
1424
  };
299
1425
 
300
- export { FieldInterfaces, FieldInterfacesList, FieldKind, FieldKindList, LevoClient, MediaKind, MediaKindList, defaultByKinds, formatImagePath, formatsByInterface, interfaceKinds, workspaceIdRegex };
1426
+ export { AnalyticsEvents, AnalyticsEventsList, FieldInterfaces, FieldInterfacesList, FieldKind, FieldKindList, LevoError, LevoOAuthProviderList, LocalStorageLock, MediaKind, MediaKindList, createLevoClient, defaultByKinds, formatImagePath, formatsByInterface, getLevoError, interfaceKinds };