@levo-so/core 0.1.59 → 0.1.61

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 (55) hide show
  1. package/dist/index.d.ts +1789 -8
  2. package/dist/index.js +262 -881
  3. package/package.json +3 -9
  4. package/dist/client.d.ts +0 -82
  5. package/dist/constants/collection/defaultByKind.d.ts +0 -3
  6. package/dist/constants/collection/fieldInterfaceFormat.d.ts +0 -3
  7. package/dist/constants/collection/fieldInterfaces.d.ts +0 -6
  8. package/dist/constants/collection/fieldKind.d.ts +0 -26
  9. package/dist/constants/index.d.ts +0 -8
  10. package/dist/constants/integration.d.ts +0 -23
  11. package/dist/constants/media.d.ts +0 -3
  12. package/dist/constants/oauthProvider.d.ts +0 -3
  13. package/dist/control/audience.d.ts +0 -22
  14. package/dist/control/index.d.ts +0 -23
  15. package/dist/httpClient.d.ts +0 -13
  16. package/dist/logger/batch.d.ts +0 -9
  17. package/dist/logger/index.d.ts +0 -22
  18. package/dist/modules/blog.d.ts +0 -10
  19. package/dist/modules/collection.d.ts +0 -26
  20. package/dist/modules/media.d.ts +0 -11
  21. package/dist/modules/membership.d.ts +0 -21
  22. package/dist/types/audience.d.ts +0 -100
  23. package/dist/types/blog/author.d.ts +0 -30
  24. package/dist/types/blog/blogClient.d.ts +0 -51
  25. package/dist/types/blog/category.d.ts +0 -20
  26. package/dist/types/blog/index.d.ts +0 -64
  27. package/dist/types/blog/post.d.ts +0 -63
  28. package/dist/types/blog/tag.d.ts +0 -19
  29. package/dist/types/collection/collectionView.d.ts +0 -36
  30. package/dist/types/collection/draft.d.ts +0 -9
  31. package/dist/types/collection/index.d.ts +0 -7
  32. package/dist/types/collection/lemaCollection.d.ts +0 -95
  33. package/dist/types/collection/lemaField.d.ts +0 -55
  34. package/dist/types/collection/lemaSection.d.ts +0 -10
  35. package/dist/types/collection/relation.d.ts +0 -11
  36. package/dist/types/emoji.d.ts +0 -22
  37. package/dist/types/event.d.ts +0 -225
  38. package/dist/types/index.d.ts +0 -14
  39. package/dist/types/levo-query.d.ts +0 -104
  40. package/dist/types/location.d.ts +0 -6
  41. package/dist/types/media.d.ts +0 -56
  42. package/dist/types/membership/index.d.ts +0 -182
  43. package/dist/types/query.d.ts +0 -46
  44. package/dist/types/schema/field.d.ts +0 -56
  45. package/dist/types/schema/index.d.ts +0 -3
  46. package/dist/types/schema/schema.d.ts +0 -58
  47. package/dist/types/utils.d.ts +0 -8
  48. package/dist/types/workspace.d.ts +0 -172
  49. package/dist/utils/LevoError.d.ts +0 -21
  50. package/dist/utils/formatImagePath.d.ts +0 -3
  51. package/dist/utils/getLevoError.d.ts +0 -3
  52. package/dist/utils/getUserProperties.d.ts +0 -8
  53. package/dist/utils/isIncognito.d.ts +0 -9
  54. package/dist/utils/listToX.d.ts +0 -3
  55. package/dist/utils/lock.d.ts +0 -21
package/dist/index.js CHANGED
@@ -1,698 +1,6 @@
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';
6
1
  import wretch from 'wretch';
7
2
  import queryStringAddon from 'wretch/addons/queryString';
8
-
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
- )
127
- );
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"));
169
- }
170
- }
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;
250
- }
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;
260
- }
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
- status;
276
- type;
277
- errors;
278
- constructor(data) {
279
- super(data.description);
280
- this.name = "Levo Request Error";
281
- this.status = data.status;
282
- this.code = data.code;
283
- this.title = data.title;
284
- this.type = data.type;
285
- this.errors = data.errors;
286
- }
287
- /**
288
- * Get validation errors for form fields
289
- */
290
- get fieldErrors() {
291
- return this.errors || [];
292
- }
293
- /**
294
- * Check if this is a validation error with field-specific errors
295
- */
296
- get hasFieldErrors() {
297
- return Boolean(this.errors?.length);
298
- }
299
- };
300
-
301
- // src/utils/getLevoError.ts
302
- var getLevoError = (error) => {
303
- if (error instanceof LevoError) {
304
- return error;
305
- }
306
- if (error instanceof WretchError && error?.json) {
307
- const errorResponse = error?.json;
308
- return new LevoError({
309
- status: errorResponse?.content?.status || 500,
310
- code: errorResponse?.content?.code || `Unknown`,
311
- title: errorResponse?.content?.title || `HTTP ${error?.status || 500} Error`,
312
- description: errorResponse?.content?.description || `Request failed with status ${error?.status || 500}`,
313
- type: errorResponse?.content?.type,
314
- errors: errorResponse?.content?.errors
315
- });
316
- }
317
- if (error instanceof TypeError) {
318
- if (error?.message.includes("Failed to fetch") || error?.message.includes("Network request failed") || error?.message.includes("fetch")) {
319
- return new LevoError({
320
- status: 0,
321
- code: "NETWORK_ERROR",
322
- title: "Network Error",
323
- description: "Unable to connect to the server. Please check your internet connection."
324
- });
325
- }
326
- if (error?.message.includes("CORS") || error?.message.includes("cross-origin")) {
327
- return new LevoError({
328
- status: 0,
329
- code: "CORS_ERROR",
330
- title: "CORS Error",
331
- description: "Cross-origin request blocked. Please contact support."
332
- });
333
- }
334
- }
335
- if (error?.name === "AbortError" || error instanceof DOMException) {
336
- return new LevoError({
337
- status: 408,
338
- code: "REQUEST_TIMEOUT",
339
- title: "Request Timeout",
340
- description: "The request was cancelled or timed out. Please try again."
341
- });
342
- }
343
- if (error?.request) {
344
- return new LevoError({
345
- status: error?.response?.status || 500,
346
- code: error?.code || "REQUEST_ERROR",
347
- title: "Request Error",
348
- description: error?.message || "An error occurred while making the request"
349
- });
350
- }
351
- return new LevoError({
352
- status: 500,
353
- code: "UNKNOWN_ERROR",
354
- title: "Unexpected Error",
355
- description: error?.message || "Something unexpected happened"
356
- });
357
- };
358
-
359
- // src/utils/lock.ts
360
- var LocalStorageLock = class {
361
- key;
362
- constructor(lockKey) {
363
- this.key = lockKey;
364
- }
365
- acquireLock(expiryMs = 5e3) {
366
- const now = Date.now();
367
- const lockValue = localStorage.getItem(this.key);
368
- if (lockValue) {
369
- const timestamp = Number(lockValue);
370
- if (now - timestamp < expiryMs) {
371
- return false;
372
- }
373
- }
374
- localStorage.setItem(this.key, now.toString());
375
- setTimeout(() => {
376
- if (this.isLocked(expiryMs)) {
377
- this.releaseLock();
378
- }
379
- }, expiryMs);
380
- return true;
381
- }
382
- releaseLock() {
383
- localStorage.removeItem(this.key);
384
- }
385
- isLocked(expiryMs = 5e3) {
386
- const lockValue = localStorage.getItem(this.key);
387
- if (!lockValue) {
388
- return false;
389
- }
390
- const timestamp = Number(lockValue);
391
- return Date.now() - timestamp < expiryMs;
392
- }
393
- };
394
-
395
- // src/control/audience.ts
396
- var createLevoAudienceModule = (core, httpClient) => {
397
- const _IDLE_THROTTLE = 1 * 1e3;
398
- const _IDLE_TIMEOUT = 60 * 1e3;
399
- let instance = null;
400
- let idle_listener = null;
401
- const storage_keys = {
402
- identify: "lock:lv_aud_identify",
403
- open_tabs: "lv_insights_ot",
404
- current_tab: "lv_insights_ct",
405
- all_tabs: "lv_insights_at"
406
- };
407
- let _session = "";
408
- let _device = "";
409
- let is_identified = false;
410
- let _batch = [];
411
- const getReferrer = () => {
412
- if (typeof document === "undefined") {
413
- return {};
414
- }
415
- const {
416
- type,
417
- referrer,
418
- data = {}
419
- } = getVisitorSource({
420
- referrer: document.referrer,
421
- currentUrl: window.location.href,
422
- mapper: null
423
- });
424
- const dataKeys = Object.keys(data);
425
- for (const key of dataKeys) {
426
- if (data[key] && Array.isArray(data[key]) && data[key].length > 0) {
427
- data[key] = data[key]?.[0];
428
- }
429
- }
430
- return { type, referrer, data, raw: document.referrer };
431
- };
432
- const getCurrentTabId = () => {
433
- try {
434
- if (typeof window === "undefined" || !("sessionStorage" in window)) {
435
- return "";
436
- }
437
- const CURRENT_TAB_LOCAL_STORAGE_KEY = storage_keys.current_tab;
438
- return window.sessionStorage.getItem(CURRENT_TAB_LOCAL_STORAGE_KEY) || "";
439
- } catch (_) {
440
- return "";
441
- }
442
- };
443
- const getTabCount = () => {
444
- try {
445
- if (typeof window === "undefined" || !("localStorage" in window)) {
446
- return 0;
447
- }
448
- const OT_LOCAL_STORAGE_KEY = storage_keys.open_tabs;
449
- return Number(window.localStorage.getItem(OT_LOCAL_STORAGE_KEY)) || 0;
450
- } catch (_) {
451
- return 0;
452
- }
453
- };
454
- const getActivityStatus = () => {
455
- const status = idle_listener?.getStatus();
456
- if (!status) {
457
- return null;
458
- }
459
- return {
460
- status: status.isIdle ? "idle" : "active",
461
- seconds: status.isIdle ? status.idle : status.active
462
- };
463
- };
464
- const identify = async (options) => {
465
- if (!instance) {
466
- return;
467
- }
468
- const withLock = options?.withLock ?? true;
469
- const referrer = getReferrer();
470
- const traits = await getUserProperties();
471
- await instance.identify("", {
472
- ...traits,
473
- referrer,
474
- withLock
475
- });
476
- };
477
- const request = async (url, data) => {
478
- const headers = {
479
- Accept: "application/json",
480
- "Content-Type": "application/json"
481
- };
482
- try {
483
- const response = await httpClient.instance.url(core?.insightsUrl, true).url(url).options({
484
- keepAlive: true
485
- }).headers(headers).post(data).json();
486
- return response;
487
- } catch (error) {
488
- console.warn(`Analytics request failed for ${url}:`, error);
489
- return null;
490
- }
491
- };
492
- const initiate = async (properties) => {
493
- if (core.NODE_ENV === "development") {
494
- return;
495
- }
496
- const plugin = {
497
- name: core.workspace,
498
- track: ({ payload }) => {
499
- if (!core?.insightsUrl || !core.workspace) {
500
- return;
501
- }
502
- const payloadProperties = payload?.properties || {};
503
- const collectInput = {
504
- session_id: _session,
505
- device_id: _device,
506
- event: payload.event,
507
- version: payload.version || 1,
508
- workspace_id: core.workspace,
509
- properties: {
510
- ...properties,
511
- ...payloadProperties,
512
- version: void 0,
513
- resource: void 0,
514
- identifier: void 0,
515
- hostname: void 0,
516
- pathname: void 0,
517
- url: void 0,
518
- page_title: void 0,
519
- created_at: void 0
520
- },
521
- hostname: payload?.hostname || window.location.hostname,
522
- pathname: payload?.pathname || window.location.pathname,
523
- url: payload?.url || window.location.href,
524
- page_title: payload?.page_title || document.title,
525
- resource: payloadProperties?.resource || "page",
526
- identifier: payloadProperties?.identifier || properties?.id,
527
- created_at: payload?.created_at || (/* @__PURE__ */ new Date()).toISOString(),
528
- tab_id: getCurrentTabId(),
529
- tab_count: getTabCount()
530
- };
531
- let isQueued = false;
532
- if (navigator.sendBeacon) {
533
- isQueued = navigator.sendBeacon(
534
- `${core?.insightsUrl}/v1/insights/event/collect`,
535
- JSON.stringify(collectInput)
536
- );
537
- }
538
- if (!isQueued) {
539
- request("/v1/insights/event/collect", collectInput);
540
- }
541
- },
542
- page: ({ payload }) => {
543
- if (!core?.insightsUrl) {
544
- return;
545
- }
546
- const payloadProperties = payload?.properties || {};
547
- track("page.view", {
548
- ...properties,
549
- ...payloadProperties,
550
- title: document.title,
551
- identifier: properties.id,
552
- resource: "page"
553
- });
554
- },
555
- identify: ({ payload }) => {
556
- if (!core?.insightsUrl || !core.workspace) {
557
- return;
558
- }
559
- const withLock = payload?.traits?.withLock ?? true;
560
- const welcomeInput = {
561
- private_mode: payload.traits.private_mode,
562
- dark_mode: payload.traits.dark_mode,
563
- timezone: payload.traits.timezone,
564
- locale: payload.traits.locale,
565
- referrer: payload.traits.referrer,
566
- properties: payload.traits.properties,
567
- workspace_id: core.workspace,
568
- hostname: window.location.hostname,
569
- pathname: window.location.pathname,
570
- page_title: document.title,
571
- url: window.location.href,
572
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
573
- tab_id: getCurrentTabId(),
574
- tab_count: getTabCount()
575
- };
576
- let identifyLock = null;
577
- if (withLock) {
578
- identifyLock = new LocalStorageLock(storage_keys.identify);
579
- }
580
- if (!identifyLock || identifyLock.acquireLock()) {
581
- request(`/v1/insights/event/welcome`, welcomeInput).then((data) => {
582
- is_identified = true;
583
- if (data?.content?.data?.session) {
584
- _session = data?.content.data.session;
585
- }
586
- if (data?.content?.data?.device) {
587
- _device = data?.content.data.device;
588
- }
589
- let isQueued = false;
590
- if (navigator.sendBeacon) {
591
- isQueued = navigator.sendBeacon(
592
- `${core?.insightsUrl}/v1/insights/event/bulk?workspace=${core?.workspace}`,
593
- JSON.stringify(_batch)
594
- );
595
- }
596
- if (!isQueued) {
597
- request("/v1/insights/event/bulk", _batch);
598
- }
599
- _batch = [];
600
- identifyLock?.releaseLock();
601
- }).catch((e) => {
602
- identifyLock?.releaseLock();
603
- return getLevoError(e);
604
- });
605
- }
606
- }
607
- };
608
- instance = Analytics({
609
- app: core.workspace || "",
610
- plugins: [plugin]
611
- });
612
- await identify();
613
- startActivityListener();
614
- return instance.page({
615
- resource: "page",
616
- identifier: properties.id
617
- });
618
- };
619
- const startActivityListener = () => {
620
- if (typeof document !== "undefined" && !idle_listener) {
621
- idle_listener = onUserActivity({
622
- timeout: _IDLE_TIMEOUT,
623
- throttle: _IDLE_THROTTLE,
624
- onIdle: (activeForSeconds) => {
625
- track("user.idle", {
626
- seconds_active: activeForSeconds
627
- });
628
- },
629
- onWakeUp: (idleForSeconds) => {
630
- track("user.active", {
631
- seconds_idle: idleForSeconds
632
- });
633
- }
634
- });
635
- }
636
- return null;
637
- };
638
- const bounce = async (properties) => {
639
- const activity_status = getActivityStatus();
640
- if (activity_status) {
641
- if (activity_status?.status === "idle") {
642
- properties.seconds_idle = activity_status.seconds;
643
- } else {
644
- properties.seconds_active = activity_status.seconds;
645
- }
646
- }
647
- track("page.bounce", properties);
648
- };
649
- const track = async (event, properties) => {
650
- if (!core.workspace) {
651
- return;
652
- }
653
- if (instance && is_identified) {
654
- return instance.track(event, properties);
655
- }
656
- return _batch.push({
657
- event,
658
- version: properties?.version || 1,
659
- properties: {
660
- ...properties,
661
- version: void 0,
662
- resource: void 0,
663
- identifier: void 0,
664
- hostname: void 0,
665
- pathname: void 0,
666
- url: void 0,
667
- page_title: void 0,
668
- created_at: void 0
669
- },
670
- hostname: window.location.hostname,
671
- pathname: window.location.pathname,
672
- url: window.location.href,
673
- page_title: document.title,
674
- resource: properties?.resource || "page",
675
- identifier: properties?.identifier || properties?.id,
676
- workspace_id: core.workspace,
677
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
678
- tab_id: getCurrentTabId(),
679
- tab_count: getTabCount()
680
- });
681
- };
682
- return {
683
- get instance() {
684
- return instance;
685
- },
686
- get is_identified() {
687
- return is_identified;
688
- },
689
- storage_keys,
690
- initiate,
691
- identify,
692
- track,
693
- bounce
694
- };
695
- };
3
+ import { WretchError } from 'wretch/resolver';
696
4
 
697
5
  // src/control/index.ts
698
6
  var workspaceIdRegex = /^W[A-Z0-9]{7}$/;
@@ -701,7 +9,6 @@ var createLevoControl = (options) => {
701
9
  appName,
702
10
  workspace = null,
703
11
  apiUrl = "https://public-api.levo.so",
704
- insightsUrl = "/.levo/insights/api",
705
12
  NODE_ENV = "",
706
13
  APP_MODE = "production"
707
14
  } = options;
@@ -733,9 +40,6 @@ var createLevoControl = (options) => {
733
40
  get apiUrl() {
734
41
  return apiUrl;
735
42
  },
736
- get insightsUrl() {
737
- return insightsUrl;
738
- },
739
43
  get NODE_ENV() {
740
44
  return NODE_ENV;
741
45
  },
@@ -937,31 +241,119 @@ var createLevoLogger = (core, options = {}) => {
937
241
  batch.ingest(log2);
938
242
  }
939
243
  }
940
- const method = getMethodName(level);
941
- console[method](...messages);
942
- };
943
- const debug = (...args) => {
944
- log(0 /* debug */, args);
945
- };
946
- const info = (...args) => {
947
- log(1 /* info */, args);
948
- };
949
- const warn = (...args) => {
950
- log(2 /* warn */, args);
951
- };
952
- const error = (...args) => {
953
- log(3 /* error */, args);
954
- };
955
- return {
956
- debug,
957
- info,
958
- warn,
959
- error
960
- };
244
+ const method = getMethodName(level);
245
+ console[method](...messages);
246
+ };
247
+ const debug = (...args) => {
248
+ log(0 /* debug */, args);
249
+ };
250
+ const info = (...args) => {
251
+ log(1 /* info */, args);
252
+ };
253
+ const warn = (...args) => {
254
+ log(2 /* warn */, args);
255
+ };
256
+ const error = (...args) => {
257
+ log(3 /* error */, args);
258
+ };
259
+ return {
260
+ debug,
261
+ info,
262
+ warn,
263
+ error
264
+ };
265
+ };
266
+
267
+ // src/utils/LevoError.ts
268
+ var LevoError = class extends Error {
269
+ code;
270
+ title;
271
+ status;
272
+ type;
273
+ errors;
274
+ constructor(data) {
275
+ super(data.description);
276
+ this.name = "Levo Request Error";
277
+ this.status = data.status;
278
+ this.code = data.code;
279
+ this.title = data.title;
280
+ this.type = data.type;
281
+ this.errors = data.errors;
282
+ }
283
+ /**
284
+ * Get validation errors for form fields
285
+ */
286
+ get fieldErrors() {
287
+ return this.errors || [];
288
+ }
289
+ /**
290
+ * Check if this is a validation error with field-specific errors
291
+ */
292
+ get hasFieldErrors() {
293
+ return Boolean(this.errors?.length);
294
+ }
295
+ };
296
+
297
+ // src/utils/getLevoError.ts
298
+ var getLevoError = (error) => {
299
+ if (error instanceof LevoError) {
300
+ return error;
301
+ }
302
+ if (error instanceof WretchError && error?.json) {
303
+ const errorResponse = error?.json;
304
+ return new LevoError({
305
+ status: errorResponse?.content?.status || 500,
306
+ code: errorResponse?.content?.code || `Unknown`,
307
+ title: errorResponse?.content?.title || `HTTP ${error?.status || 500} Error`,
308
+ description: errorResponse?.content?.description || `Request failed with status ${error?.status || 500}`,
309
+ type: errorResponse?.content?.type,
310
+ errors: errorResponse?.content?.errors
311
+ });
312
+ }
313
+ if (error instanceof TypeError) {
314
+ if (error?.message.includes("Failed to fetch") || error?.message.includes("Network request failed") || error?.message.includes("fetch")) {
315
+ return new LevoError({
316
+ status: 0,
317
+ code: "NETWORK_ERROR",
318
+ title: "Network Error",
319
+ description: "Unable to connect to the server. Please check your internet connection."
320
+ });
321
+ }
322
+ if (error?.message.includes("CORS") || error?.message.includes("cross-origin")) {
323
+ return new LevoError({
324
+ status: 0,
325
+ code: "CORS_ERROR",
326
+ title: "CORS Error",
327
+ description: "Cross-origin request blocked. Please contact support."
328
+ });
329
+ }
330
+ }
331
+ if (error?.name === "AbortError" || error instanceof DOMException) {
332
+ return new LevoError({
333
+ status: 408,
334
+ code: "REQUEST_TIMEOUT",
335
+ title: "Request Timeout",
336
+ description: "The request was cancelled or timed out. Please try again."
337
+ });
338
+ }
339
+ if (error?.request) {
340
+ return new LevoError({
341
+ status: error?.response?.status || 500,
342
+ code: error?.code || "REQUEST_ERROR",
343
+ title: "Request Error",
344
+ description: error?.message || "An error occurred while making the request"
345
+ });
346
+ }
347
+ return new LevoError({
348
+ status: 500,
349
+ code: "UNKNOWN_ERROR",
350
+ title: "Unexpected Error",
351
+ description: error?.message || "Something unexpected happened"
352
+ });
961
353
  };
962
354
 
963
355
  // src/modules/blog.ts
964
- var createLevoBlogModule = (core, httpClient, audience = null) => {
356
+ var createLevoBlogModule = (core, httpClient) => {
965
357
  const getAllBlogs = async (blog_key, data = {}, options) => {
966
358
  return httpClient.instance.url(`/v1/blog/${blog_key}/post/query`).query({ ...options?.params || {} }).options({
967
359
  headers: {
@@ -987,7 +379,7 @@ var createLevoBlogModule = (core, httpClient, audience = null) => {
987
379
  };
988
380
 
989
381
  // src/modules/collection.ts
990
- var createLevoCollectionModule = (core, httpsClient, audience = null) => {
382
+ var createLevoCollectionModule = (core, httpsClient) => {
991
383
  const getAllCollections = async (data = {}, options = {}) => {
992
384
  return httpsClient.instance.url("/v1/bevy/collection/query").options(options).post(data).json().then((response) => response).catch((error) => {
993
385
  throw getLevoError(error);
@@ -1043,6 +435,11 @@ var createLevoCollectionModule = (core, httpsClient, audience = null) => {
1043
435
  throw getLevoError(error);
1044
436
  });
1045
437
  };
438
+ const getFilters = async (collectionId, options = {}) => {
439
+ return httpsClient.instance.url(`/v1/bevy/collection/${collectionId}/get-filters`).options(options).get().json().then((response) => response).catch((error) => {
440
+ throw getLevoError(error);
441
+ });
442
+ };
1046
443
  const submitDraftEntry = async (collection_key, data) => {
1047
444
  return httpsClient.instance.url(`/v1/bevy/content/${collection_key}/submit-entry`).post(data).json().then((response) => response).catch((error) => {
1048
445
  throw getLevoError(error);
@@ -1057,12 +454,13 @@ var createLevoCollectionModule = (core, httpsClient, audience = null) => {
1057
454
  saveDraftEntry,
1058
455
  editDraftEntry,
1059
456
  getDraftEntry,
1060
- submitDraftEntry
457
+ submitDraftEntry,
458
+ getFilters
1061
459
  };
1062
460
  };
1063
461
 
1064
462
  // src/modules/media.ts
1065
- var createLevoMediaModule = (core, httpsClient, audience = null) => {
463
+ var createLevoMediaModule = (core, httpsClient) => {
1066
464
  const mediaBulkUpload = async (formData, options = {}) => {
1067
465
  return httpsClient.instance.url("/v1/assets/media/bulk").options(options).post(formData).json().then((response) => response).catch((error) => {
1068
466
  throw getLevoError(error);
@@ -1080,14 +478,10 @@ var createLevoMediaModule = (core, httpsClient, audience = null) => {
1080
478
  };
1081
479
 
1082
480
  // src/constants/oauthProvider.ts
1083
- var LevoOAuthProviderList = [
1084
- "google",
1085
- "linkedin",
1086
- "microsoft"
1087
- ];
481
+ var LevoOAuthProviderList = ["google", "linkedin", "microsoft"];
1088
482
 
1089
483
  // src/modules/membership.ts
1090
- var createLevoMembershipModule = (core, httpsClient, audience = null) => {
484
+ var createLevoMembershipModule = (core, httpsClient) => {
1091
485
  const getOAuthURL = async (options = {}) => {
1092
486
  return httpsClient.instance.url("/v1/membership/auth/oauth/get-redirect-url").options(options).get().json().then((response) => {
1093
487
  const result = response?.content?.data;
@@ -1103,10 +497,7 @@ var createLevoMembershipModule = (core, httpsClient, audience = null) => {
1103
497
  url_params.set("workspace_id", core.workspace);
1104
498
  }
1105
499
  if (httpsClient.pageContext) {
1106
- url_params.set(
1107
- "page_context",
1108
- JSON.stringify(httpsClient.pageContext)
1109
- );
500
+ url_params.set("page_context", JSON.stringify(httpsClient.pageContext));
1110
501
  }
1111
502
  result[provider] = url.toString();
1112
503
  }
@@ -1202,11 +593,10 @@ var createLevoClient = (options) => {
1202
593
  let _pageContext = pageContext;
1203
594
  const core = createLevoControl(coreOptions);
1204
595
  const httpsClient = createHttpClient(core, _pageContext);
1205
- const audience = createLevoAudienceModule(core, httpsClient);
1206
- const blog = createLevoBlogModule(core, httpsClient, audience);
1207
- const membership = createLevoMembershipModule(core, httpsClient, audience);
1208
- const collection = createLevoCollectionModule(core, httpsClient, audience);
1209
- const media = createLevoMediaModule(core, httpsClient, audience);
596
+ const blog = createLevoBlogModule(core, httpsClient);
597
+ const membership = createLevoMembershipModule(core, httpsClient);
598
+ const collection = createLevoCollectionModule(core, httpsClient);
599
+ const media = createLevoMediaModule(core, httpsClient);
1210
600
  const logger = createLevoLogger(core, loggerOptions);
1211
601
  const updatePageContext = (newContext) => {
1212
602
  _pageContext = Object.assign({}, _pageContext, newContext);
@@ -1218,15 +608,9 @@ var createLevoClient = (options) => {
1218
608
  get apiUrl() {
1219
609
  return core.apiUrl;
1220
610
  },
1221
- get insightsUrl() {
1222
- return core.insightsUrl;
1223
- },
1224
611
  get workspace() {
1225
612
  return core.workspace;
1226
613
  },
1227
- get audience() {
1228
- return audience;
1229
- },
1230
614
  get blog() {
1231
615
  return blog;
1232
616
  },
@@ -1248,6 +632,9 @@ var createLevoClient = (options) => {
1248
632
  get APP_MODE() {
1249
633
  return core.APP_MODE;
1250
634
  },
635
+ get NODE_ENV() {
636
+ return core.NODE_ENV;
637
+ },
1251
638
  get pageContext() {
1252
639
  return _pageContext;
1253
640
  },
@@ -1256,55 +643,38 @@ var createLevoClient = (options) => {
1256
643
  };
1257
644
  };
1258
645
 
1259
- // src/utils/listToX.ts
1260
- var listToRecord = (columns) => {
1261
- return columns.reduce((prev, current) => {
1262
- prev[current] = current;
1263
- return prev;
1264
- }, {});
646
+ // src/constants/collection/defaultByKind.ts
647
+ var defaultByKinds = {
648
+ "public-id": "",
649
+ string: "",
650
+ number: null,
651
+ boolean: false,
652
+ location: null,
653
+ file: null,
654
+ date: null,
655
+ identifier: null,
656
+ record: null,
657
+ group: [],
658
+ collection: {
659
+ m2o: null,
660
+ o2o: null,
661
+ m2m: []
662
+ },
663
+ richtext: {
664
+ html: "",
665
+ text: "",
666
+ json: []
667
+ },
668
+ json: {},
669
+ "array-string": [],
670
+ "array-number": [],
671
+ "array-file": [],
672
+ "array-json": [],
673
+ "array-date": [],
674
+ "array-boolean": [],
675
+ "array-location": []
1265
676
  };
1266
677
 
1267
- // src/types/audience.ts
1268
- var AnalyticsEventsList = [
1269
- // Bevy Events
1270
- "bevy.collection.filled",
1271
- "bevy.collection.submitted",
1272
- "bevy.collection.view",
1273
- // Block Events
1274
- "block.view",
1275
- // Blog Events
1276
- "blog.post.view",
1277
- // Event Events
1278
- "event.booking.confirmed",
1279
- "event.booking.initiated",
1280
- "event.booking.pending",
1281
- "event.coupon.applied",
1282
- "event.event.view",
1283
- // Form Events
1284
- "form.change",
1285
- "form.submit",
1286
- // Membership Events
1287
- "membership.account.signin",
1288
- "membership.account.signout",
1289
- "membership.account.signup",
1290
- // UI Events
1291
- "button.click",
1292
- "page.bounce",
1293
- "page.click",
1294
- "page.copy",
1295
- "page.impression",
1296
- "page.scroll",
1297
- "page.view",
1298
- "page.metrics",
1299
- "page.selection",
1300
- "page.speedtest",
1301
- // User Activity Events
1302
- "user.active",
1303
- "user.speedtest",
1304
- "user.idle"
1305
- ];
1306
- var AnalyticsEvents = listToRecord(AnalyticsEventsList);
1307
-
1308
678
  // src/constants/collection/fieldInterfaceFormat.ts
1309
679
  var formatsByInterface = {
1310
680
  ArrayWidget: [],
@@ -1322,6 +692,7 @@ var formatsByInterface = {
1322
692
  PhoneWidget: ["phone"],
1323
693
  URLWidget: ["url"],
1324
694
  DateWidget: [],
695
+ TimeWidget: [],
1325
696
  SwitchWidget: [],
1326
697
  RichTextWidget: [],
1327
698
  DateTimeWidget: [],
@@ -1337,38 +708,58 @@ var formatsByInterface = {
1337
708
  SlugWidget: []
1338
709
  };
1339
710
 
1340
- // src/constants/collection/defaultByKind.ts
1341
- var defaultByKinds = {
1342
- "public-id": "",
1343
- string: "",
1344
- number: null,
1345
- boolean: false,
1346
- location: null,
1347
- file: null,
1348
- date: null,
1349
- identifier: null,
1350
- record: null,
1351
- group: [],
1352
- collection: {
1353
- o2m: null,
1354
- m2o: null,
1355
- o2o: null,
1356
- m2m: []
711
+ // src/constants/collection/fieldInterfaces.ts
712
+ var CommonFieldInterfacesList = [
713
+ "TextWidget",
714
+ "CurrencyWidget",
715
+ "TextareaWidget",
716
+ "GeocoderWidget",
717
+ "MultiGeocoderWidget",
718
+ "DropdownWidget",
719
+ "ToggleCheckboxWidget",
720
+ "RadioWidget",
721
+ "NumberWidget",
722
+ "EmailWidget",
723
+ "PhoneWidget",
724
+ "URLWidget",
725
+ "DateWidget",
726
+ "TimeWidget",
727
+ "SwitchWidget",
728
+ "RichTextWidget",
729
+ "DateTimeWidget",
730
+ "CheckboxWidget",
731
+ "ImageUploadWidget",
732
+ "MultiImageUploadWidget",
733
+ "FileUploadWidget",
734
+ "MultiFileUploadWidget",
735
+ "MultiDropdownWidget",
736
+ "MultiTextWidget"
737
+ ];
738
+ var ComplexFieldInterfacesList = [
739
+ "CollectionWidget",
740
+ "ArrayWidget",
741
+ "RecordWidget",
742
+ "JSONWidget",
743
+ "SlugWidget"
744
+ ];
745
+ var FieldInterfacesList = [
746
+ ...CommonFieldInterfacesList,
747
+ ...ComplexFieldInterfacesList
748
+ ];
749
+ var CommonFieldIntefaces = CommonFieldInterfacesList.reduce(
750
+ (acc, curr) => {
751
+ acc[curr] = curr;
752
+ return acc;
1357
753
  },
1358
- richtext: {
1359
- html: "",
1360
- text: "",
1361
- json: []
754
+ {}
755
+ );
756
+ var FieldInterfaces = FieldInterfacesList.reduce(
757
+ (acc, curr) => {
758
+ acc[curr] = curr;
759
+ return acc;
1362
760
  },
1363
- json: {},
1364
- "array-string": [],
1365
- "array-number": [],
1366
- "array-file": [],
1367
- "array-json": [],
1368
- "array-date": [],
1369
- "array-boolean": [],
1370
- "array-location": []
1371
- };
761
+ {}
762
+ );
1372
763
 
1373
764
  // src/constants/collection/fieldKind.ts
1374
765
  var FieldKindList = [
@@ -1428,6 +819,7 @@ var interfaceKinds = {
1428
819
  SlugWidget: FieldKind.string,
1429
820
  RichTextWidget: FieldKind.string,
1430
821
  DateWidget: FieldKind.date,
822
+ TimeWidget: FieldKind.string,
1431
823
  DateTimeWidget: FieldKind.date,
1432
824
  RadioWidget: FieldKind.string,
1433
825
  CheckboxWidget: FieldKind["array-string"],
@@ -1446,57 +838,17 @@ var interfaceKinds = {
1446
838
  JSONWidget: FieldKind.json
1447
839
  };
1448
840
 
1449
- // src/constants/collection/fieldInterfaces.ts
1450
- var CommonFieldInterfacesList = [
1451
- "TextWidget",
1452
- "CurrencyWidget",
1453
- "TextareaWidget",
1454
- "GeocoderWidget",
1455
- "MultiGeocoderWidget",
1456
- "DropdownWidget",
1457
- "ToggleCheckboxWidget",
1458
- "RadioWidget",
1459
- "NumberWidget",
1460
- "EmailWidget",
1461
- "PhoneWidget",
1462
- "URLWidget",
1463
- "DateWidget",
1464
- "SwitchWidget",
1465
- "RichTextWidget",
1466
- "DateTimeWidget",
1467
- "CheckboxWidget",
1468
- "ImageUploadWidget",
1469
- "MultiImageUploadWidget",
1470
- "FileUploadWidget",
1471
- "MultiFileUploadWidget",
1472
- "MultiDropdownWidget",
1473
- "MultiTextWidget"
1474
- ];
1475
- var ComplexFieldInterfacesList = [
1476
- "CollectionWidget",
1477
- "ArrayWidget",
1478
- "RecordWidget",
1479
- "JSONWidget",
1480
- "SlugWidget"
1481
- ];
1482
- var FieldInterfacesList = [
1483
- ...CommonFieldInterfacesList,
1484
- ...ComplexFieldInterfacesList
1485
- ];
1486
- var CommonFieldIntefaces = CommonFieldInterfacesList.reduce(
1487
- (acc, curr) => {
1488
- acc[curr] = curr;
1489
- return acc;
1490
- },
1491
- {}
1492
- );
1493
- var FieldInterfaces = FieldInterfacesList.reduce(
1494
- (acc, curr) => {
1495
- acc[curr] = curr;
1496
- return acc;
1497
- },
1498
- {}
1499
- );
841
+ // src/constants/integration.ts
842
+ var LEVO_INTEGRATIONS = {
843
+ beacon: "so.levo.beacon",
844
+ blog: "so.levo.blog",
845
+ event: "so.levo.event",
846
+ membership: "so.levo.membership",
847
+ payment: "so.levo.payment",
848
+ community: "so.levo.community",
849
+ search_console: "com.google.search_console"
850
+ };
851
+ var LEVO_INTEGRATIONS_LIST = Object.values(LEVO_INTEGRATIONS);
1500
852
 
1501
853
  // src/constants/media.ts
1502
854
  var MediaKindList = ["image", "video", "audio", "document"];
@@ -1508,16 +860,31 @@ var MediaKind = MediaKindList.reduce(
1508
860
  {}
1509
861
  );
1510
862
 
1511
- // src/constants/integration.ts
1512
- var LEVO_INTEGRATIONS = {
1513
- beacon: "so.levo.beacon",
1514
- blog: "so.levo.blog",
1515
- event: "so.levo.event",
1516
- membership: "so.levo.membership",
1517
- payment: "so.levo.payment",
1518
- search_console: "com.google.search_console"
863
+ // src/types/forum/comment.ts
864
+ var COMMENT_STATUS = {
865
+ published: "published",
866
+ unpublished: "unpublished",
867
+ archived: "archived",
868
+ flagged: "flagged",
869
+ pending_moderation: "pending_moderation"
870
+ };
871
+
872
+ // src/types/forum/post.ts
873
+ var FORUM_POST_KIND = {
874
+ post: "post",
875
+ poll: "poll",
876
+ gallery: "gallery",
877
+ link: "link"
878
+ };
879
+ var ForumPostKindExpandedList = Object.keys(FORUM_POST_KIND);
880
+ var FORUM_POST_STATUS = {
881
+ draft: "draft",
882
+ published: "published",
883
+ unpublished: "unpublished",
884
+ archived: "archived",
885
+ flagged: "flagged",
886
+ pending_moderation: "pending_moderation"
1519
887
  };
1520
- var LEVO_INTEGRATIONS_LIST = Object.values(LEVO_INTEGRATIONS);
1521
888
 
1522
889
  // src/utils/formatImagePath.ts
1523
890
  var formatImagePath = (string) => {
@@ -1530,4 +897,18 @@ var formatImagePath = (string) => {
1530
897
  return "";
1531
898
  };
1532
899
 
1533
- export { AnalyticsEvents, AnalyticsEventsList, CommonFieldIntefaces, CommonFieldInterfacesList, ComplexFieldInterfacesList, FieldInterfaces, FieldInterfacesList, FieldKind, FieldKindList, LEVO_INTEGRATIONS, LEVO_INTEGRATIONS_LIST, LevoError, LevoOAuthProviderList, LocalStorageLock, MediaKind, MediaKindList, createLevoClient, defaultByKinds, formatImagePath, formatsByInterface, getLevoError, interfaceKinds };
900
+ // src/utils/listToX.ts
901
+ var listToColumn = (columns) => {
902
+ return columns.reduce((prev, current) => {
903
+ prev[current] = current;
904
+ return prev;
905
+ }, {});
906
+ };
907
+ var listToRecord = (columns) => {
908
+ return columns.reduce((prev, current) => {
909
+ prev[current] = current;
910
+ return prev;
911
+ }, {});
912
+ };
913
+
914
+ export { COMMENT_STATUS, CommonFieldIntefaces, CommonFieldInterfacesList, ComplexFieldInterfacesList, FORUM_POST_KIND, FORUM_POST_STATUS, FieldInterfaces, FieldInterfacesList, FieldKind, FieldKindList, ForumPostKindExpandedList, LEVO_INTEGRATIONS, LEVO_INTEGRATIONS_LIST, LevoError, LevoOAuthProviderList, MediaKind, MediaKindList, createLevoClient, defaultByKinds, formatImagePath, formatsByInterface, getLevoError, interfaceKinds, listToColumn, listToRecord };