@levo-so/core 0.1.34 → 0.1.36
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/dist/client.d.ts +72 -0
- package/dist/constants/media.d.ts +1 -1
- package/dist/control/audience.d.ts +13 -0
- package/dist/control/audience.d.ts.map +1 -0
- package/dist/control/index.d.ts +23 -0
- package/dist/control/index.d.ts.map +1 -0
- package/dist/httpClient.d.ts +13 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1124 -70
- package/dist/logger/batch.d.ts +3 -10
- package/dist/logger/batch.d.ts.map +1 -1
- package/dist/logger/index.d.ts +22 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/modules/blog.d.ts +10 -0
- package/dist/modules/blog.d.ts.map +1 -0
- package/dist/modules/collection.d.ts +25 -0
- package/dist/modules/collection.d.ts.map +1 -0
- package/dist/{plugins/LevoMedia.d.ts → modules/media.d.ts} +6 -4
- package/dist/modules/media.d.ts.map +1 -0
- package/dist/modules/membership.d.ts +21 -0
- package/dist/modules/membership.d.ts.map +1 -0
- package/package.json +3 -1
- package/dist/LevoClient.d.ts +0 -38
- package/dist/chunk-QJSKNLTV.js +0 -9
- package/dist/chunk-VQMSBMEM.js +0 -40
- package/dist/chunk-ZLLCLSGE.js +0 -8
- package/dist/plugins/LevoAudience.d.ts +0 -32
- package/dist/plugins/LevoAudience.d.ts.map +0 -1
- package/dist/plugins/LevoAudience.js +0 -589
- package/dist/plugins/LevoBlog.d.ts +0 -8
- package/dist/plugins/LevoBlog.d.ts.map +0 -1
- package/dist/plugins/LevoBlog.js +0 -21
- package/dist/plugins/LevoCollection.d.ts +0 -23
- package/dist/plugins/LevoCollection.d.ts.map +0 -1
- package/dist/plugins/LevoCollection.js +0 -47
- package/dist/plugins/LevoLogger.d.ts +0 -32
- package/dist/plugins/LevoLogger.d.ts.map +0 -1
- package/dist/plugins/LevoLogger.js +0 -193
- package/dist/plugins/LevoMedia.d.ts.map +0 -1
- package/dist/plugins/LevoMedia.js +0 -13
- package/dist/plugins/LevoMembership.d.ts +0 -38
- package/dist/plugins/LevoMembership.d.ts.map +0 -1
- package/dist/plugins/LevoMembership.js +0 -104
- package/dist/plugins/LevoPlugin.d.ts +0 -6
- package/dist/plugins/LevoPlugin.d.ts.map +0 -1
- package/dist/plugins/LevoPlugin.js +0 -1
package/dist/index.js
CHANGED
|
@@ -1,92 +1,1146 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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
|
|
7
|
+
import queryStringAddon from 'wretch/addons/queryString';
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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"));
|
|
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;
|
|
34
241
|
}
|
|
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
242
|
}
|
|
42
|
-
|
|
43
|
-
|
|
243
|
+
if (navigator && "deviceMemory" in navigator) {
|
|
244
|
+
properties.device_memory = navigator?.deviceMemory;
|
|
44
245
|
}
|
|
45
|
-
|
|
46
|
-
|
|
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;
|
|
47
250
|
}
|
|
48
|
-
|
|
49
|
-
|
|
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;
|
|
50
260
|
}
|
|
51
|
-
|
|
52
|
-
|
|
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;
|
|
53
284
|
}
|
|
54
|
-
|
|
55
|
-
|
|
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
|
+
}
|
|
295
|
+
}
|
|
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;
|
|
301
|
+
}
|
|
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 = `lock_${lockKey}`;
|
|
56
315
|
}
|
|
57
|
-
|
|
58
|
-
|
|
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
|
+
return true;
|
|
59
327
|
}
|
|
60
|
-
|
|
61
|
-
|
|
328
|
+
releaseLock() {
|
|
329
|
+
localStorage.removeItem(this.key);
|
|
62
330
|
}
|
|
63
|
-
|
|
64
|
-
|
|
331
|
+
isLocked(expiryMs = 5e3) {
|
|
332
|
+
const lockValue = localStorage.getItem(this.key);
|
|
333
|
+
if (!lockValue) return false;
|
|
334
|
+
const timestamp = Number(lockValue);
|
|
335
|
+
return Date.now() - timestamp < expiryMs;
|
|
65
336
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
// src/control/audience.ts
|
|
340
|
+
var createLevoAudienceModule = (core, httpClient) => {
|
|
341
|
+
const _IDLE_THROTTLE = 1 * 1e3;
|
|
342
|
+
const _IDLE_TIMEOUT = 60 * 1e3;
|
|
343
|
+
let instance = null;
|
|
344
|
+
let idle_listener = null;
|
|
345
|
+
let _session = "";
|
|
346
|
+
let _device = "";
|
|
347
|
+
let _is_identified = false;
|
|
348
|
+
let _batch = [];
|
|
349
|
+
const request = (url, data) => {
|
|
350
|
+
const headers = {
|
|
351
|
+
Accept: "application/json",
|
|
352
|
+
"Content-Type": "application/json"
|
|
72
353
|
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
354
|
+
return httpClient.instance.url(core?.insightsUrl, true).url(url).options({
|
|
355
|
+
keepAlive: true
|
|
356
|
+
}).headers(headers).post(data).json();
|
|
357
|
+
};
|
|
358
|
+
const getReferrer = () => {
|
|
359
|
+
if (typeof document === "undefined") {
|
|
360
|
+
return {};
|
|
361
|
+
}
|
|
362
|
+
const {
|
|
363
|
+
type,
|
|
364
|
+
referrer,
|
|
365
|
+
data = {}
|
|
366
|
+
} = getVisitorSource({
|
|
367
|
+
referrer: document.referrer,
|
|
368
|
+
currentUrl: window.location.href,
|
|
369
|
+
mapper: null
|
|
370
|
+
});
|
|
371
|
+
const dataKeys = Object.keys(data);
|
|
372
|
+
for (const key of dataKeys) {
|
|
373
|
+
if (data[key] && Array.isArray(data[key]) && data[key].length > 0) {
|
|
374
|
+
data[key] = data[key]?.[0];
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return { type, referrer, data, raw: document.referrer };
|
|
378
|
+
};
|
|
379
|
+
const getCurrentTabId = () => {
|
|
380
|
+
try {
|
|
381
|
+
if (typeof window === "undefined" || !("sessionStorage" in window)) {
|
|
382
|
+
return "";
|
|
383
|
+
}
|
|
384
|
+
const CURRENT_TAB_LOCAL_STORAGE_KEY = "lv_insights_ct";
|
|
385
|
+
return window.sessionStorage.getItem(CURRENT_TAB_LOCAL_STORAGE_KEY) || "";
|
|
386
|
+
} catch (_) {
|
|
387
|
+
return "";
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
const getTabCount = () => {
|
|
391
|
+
try {
|
|
392
|
+
if (typeof window === "undefined" || !("localStorage" in window)) {
|
|
393
|
+
return 0;
|
|
394
|
+
}
|
|
395
|
+
const OT_LOCAL_STORAGE_KEY = "lv_insights_ot";
|
|
396
|
+
return Number(window.localStorage.getItem(OT_LOCAL_STORAGE_KEY)) || 0;
|
|
397
|
+
} catch (_) {
|
|
398
|
+
return 0;
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
const startActivityListener = () => {
|
|
402
|
+
if (typeof document !== "undefined" && !idle_listener) {
|
|
403
|
+
idle_listener = onUserActivity({
|
|
404
|
+
timeout: _IDLE_TIMEOUT,
|
|
405
|
+
throttle: _IDLE_THROTTLE,
|
|
406
|
+
onIdle: (activeForSeconds) => {
|
|
407
|
+
track("user.idle", {
|
|
408
|
+
seconds_active: activeForSeconds
|
|
409
|
+
});
|
|
410
|
+
},
|
|
411
|
+
onWakeUp: (idleForSeconds) => {
|
|
412
|
+
track("user.active", {
|
|
413
|
+
seconds_idle: idleForSeconds
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
return null;
|
|
419
|
+
};
|
|
420
|
+
const getActivityStatus = () => {
|
|
421
|
+
const status = idle_listener?.getStatus();
|
|
422
|
+
if (!status) {
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
return {
|
|
426
|
+
status: status.isIdle ? "idle" : "active",
|
|
427
|
+
seconds: status.isIdle ? status.idle : status.active
|
|
428
|
+
};
|
|
429
|
+
};
|
|
430
|
+
const initiate = async (properties) => {
|
|
431
|
+
if (core.NODE_ENV === "development") {
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
const plugin = {
|
|
435
|
+
name: core.workspace,
|
|
436
|
+
track: ({ payload }) => {
|
|
437
|
+
if (!core?.insightsUrl || !core.workspace) {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
const payloadProperties = payload?.properties || {};
|
|
441
|
+
const collectInput = {
|
|
442
|
+
session_id: _session,
|
|
443
|
+
device_id: _device,
|
|
444
|
+
event: payload.event,
|
|
445
|
+
version: payload.version || 1,
|
|
446
|
+
workspace_id: core.workspace,
|
|
447
|
+
properties: {
|
|
448
|
+
...properties,
|
|
449
|
+
...payloadProperties,
|
|
450
|
+
version: void 0,
|
|
451
|
+
resource: void 0,
|
|
452
|
+
identifier: void 0,
|
|
453
|
+
hostname: void 0,
|
|
454
|
+
pathname: void 0,
|
|
455
|
+
url: void 0,
|
|
456
|
+
page_title: void 0,
|
|
457
|
+
created_at: void 0
|
|
458
|
+
},
|
|
459
|
+
hostname: payload?.hostname || window.location.hostname,
|
|
460
|
+
pathname: payload?.pathname || window.location.pathname,
|
|
461
|
+
url: payload?.url || window.location.href,
|
|
462
|
+
page_title: payload?.page_title || document.title,
|
|
463
|
+
resource: payloadProperties?.resource || "page",
|
|
464
|
+
identifier: payloadProperties?.identifier || properties?.id,
|
|
465
|
+
created_at: payload?.created_at || (/* @__PURE__ */ new Date()).toISOString(),
|
|
466
|
+
tab_id: getCurrentTabId(),
|
|
467
|
+
tab_count: getTabCount()
|
|
468
|
+
};
|
|
469
|
+
let isQueued = false;
|
|
470
|
+
try {
|
|
471
|
+
isQueued = navigator.sendBeacon(
|
|
472
|
+
`${core?.insightsUrl}/v1/insights/event/collect`,
|
|
473
|
+
JSON.stringify(collectInput)
|
|
474
|
+
);
|
|
475
|
+
} catch (e) {
|
|
476
|
+
}
|
|
477
|
+
if (!isQueued) {
|
|
478
|
+
request("/v1/insights/event/collect", collectInput);
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
page: ({ payload }) => {
|
|
482
|
+
if (!core?.insightsUrl) {
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
const payloadProperties = payload?.properties || {};
|
|
486
|
+
track("page.view", {
|
|
487
|
+
...properties,
|
|
488
|
+
...payloadProperties,
|
|
489
|
+
title: document.title,
|
|
490
|
+
identifier: properties.id,
|
|
491
|
+
resource: "page"
|
|
492
|
+
});
|
|
493
|
+
},
|
|
494
|
+
identify: ({ payload }) => {
|
|
495
|
+
if (!core?.insightsUrl || !core.workspace) {
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
const welcomeInput = {
|
|
499
|
+
private_mode: payload.traits.private_mode,
|
|
500
|
+
dark_mode: payload.traits.dark_mode,
|
|
501
|
+
timezone: payload.traits.timezone,
|
|
502
|
+
locale: payload.traits.locale,
|
|
503
|
+
referrer: payload.traits.referrer,
|
|
504
|
+
properties: payload.traits.properties,
|
|
505
|
+
workspace_id: core.workspace,
|
|
506
|
+
hostname: window.location.hostname,
|
|
507
|
+
pathname: window.location.pathname,
|
|
508
|
+
page_title: document.title,
|
|
509
|
+
url: window.location.href,
|
|
510
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
511
|
+
tab_id: getCurrentTabId(),
|
|
512
|
+
tab_count: getTabCount()
|
|
513
|
+
};
|
|
514
|
+
const identifyLock = new LocalStorageLock("lv_aud_identify");
|
|
515
|
+
if (identifyLock.acquireLock()) {
|
|
516
|
+
request(`/v1/insights/event/welcome`, welcomeInput).then((data) => {
|
|
517
|
+
_is_identified = true;
|
|
518
|
+
_session = data.content.data.session;
|
|
519
|
+
_device = data.content.data.device;
|
|
520
|
+
let isQueued = false;
|
|
521
|
+
try {
|
|
522
|
+
isQueued = navigator.sendBeacon(
|
|
523
|
+
`${core?.insightsUrl}/v1/insights/event/bulk?workspace=${core?.workspace}`,
|
|
524
|
+
JSON.stringify(_batch)
|
|
525
|
+
);
|
|
526
|
+
} catch (e) {
|
|
527
|
+
}
|
|
528
|
+
if (!isQueued) {
|
|
529
|
+
request("/v1/insights/event/bulk", _batch);
|
|
530
|
+
}
|
|
531
|
+
_batch = [];
|
|
532
|
+
identifyLock.releaseLock();
|
|
533
|
+
}).catch((e) => {
|
|
534
|
+
identifyLock.releaseLock();
|
|
535
|
+
return getLevoError(e);
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
instance = Analytics({
|
|
541
|
+
app: core.workspace || "",
|
|
542
|
+
plugins: [plugin]
|
|
543
|
+
});
|
|
544
|
+
await identify();
|
|
545
|
+
startActivityListener();
|
|
546
|
+
return instance.page({
|
|
547
|
+
resource: "page",
|
|
548
|
+
identifier: properties.id
|
|
549
|
+
});
|
|
550
|
+
};
|
|
551
|
+
const identify = async () => {
|
|
552
|
+
if (!instance) {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
const referrer = getReferrer();
|
|
556
|
+
const traits = await getUserProperties();
|
|
557
|
+
await instance.identify("", {
|
|
558
|
+
...traits,
|
|
559
|
+
referrer
|
|
560
|
+
});
|
|
561
|
+
};
|
|
562
|
+
const bounce = async (properties) => {
|
|
563
|
+
const activity_status = getActivityStatus();
|
|
564
|
+
if (activity_status) {
|
|
565
|
+
if (activity_status?.status === "idle") {
|
|
566
|
+
properties.seconds_idle = activity_status.seconds;
|
|
567
|
+
} else {
|
|
568
|
+
properties.seconds_active = activity_status.seconds;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
track("page.bounce", properties);
|
|
572
|
+
};
|
|
573
|
+
const track = async (event, properties) => {
|
|
574
|
+
if (!core.workspace) {
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
if (instance && _is_identified) {
|
|
578
|
+
return instance.track(event, properties);
|
|
579
|
+
}
|
|
580
|
+
return _batch.push({
|
|
581
|
+
event,
|
|
582
|
+
version: properties?.version || 1,
|
|
583
|
+
properties: {
|
|
584
|
+
...properties,
|
|
585
|
+
version: void 0,
|
|
586
|
+
resource: void 0,
|
|
587
|
+
identifier: void 0,
|
|
588
|
+
hostname: void 0,
|
|
589
|
+
pathname: void 0,
|
|
590
|
+
url: void 0,
|
|
591
|
+
page_title: void 0,
|
|
592
|
+
created_at: void 0
|
|
593
|
+
},
|
|
594
|
+
hostname: window.location.hostname,
|
|
595
|
+
pathname: window.location.pathname,
|
|
596
|
+
url: window.location.href,
|
|
597
|
+
page_title: document.title,
|
|
598
|
+
resource: properties?.resource || "page",
|
|
599
|
+
identifier: properties?.identifier || properties?.id,
|
|
600
|
+
workspace_id: core.workspace,
|
|
601
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
602
|
+
tab_id: getCurrentTabId(),
|
|
603
|
+
tab_count: getTabCount()
|
|
604
|
+
});
|
|
605
|
+
};
|
|
606
|
+
return {
|
|
607
|
+
get instance() {
|
|
608
|
+
return instance;
|
|
609
|
+
},
|
|
610
|
+
initiate,
|
|
611
|
+
identify,
|
|
612
|
+
track,
|
|
613
|
+
bounce
|
|
614
|
+
};
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
// src/control/index.ts
|
|
618
|
+
var workspaceIdRegex = /^W[A-Z0-9]{7}$/;
|
|
619
|
+
var createLevoControl = (options) => {
|
|
620
|
+
const {
|
|
621
|
+
appName,
|
|
622
|
+
workspace = null,
|
|
623
|
+
apiUrl = "https://public-api.levo.so",
|
|
624
|
+
insightsUrl = "/.levo/insights/api",
|
|
625
|
+
NODE_ENV = "",
|
|
626
|
+
APP_MODE = "production"
|
|
627
|
+
} = options;
|
|
628
|
+
if (workspace) {
|
|
629
|
+
if (!workspaceIdRegex.test(workspace)) {
|
|
630
|
+
throw new Error(
|
|
631
|
+
`Invalid workspace ID: ${workspace}. Workspace ID must be a string of the format "W[A-Z0-9]{7}".`
|
|
632
|
+
);
|
|
78
633
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
634
|
+
}
|
|
635
|
+
let _workspace = workspace;
|
|
636
|
+
return {
|
|
637
|
+
get workspace() {
|
|
638
|
+
return _workspace;
|
|
639
|
+
},
|
|
640
|
+
set workspace(value) {
|
|
641
|
+
if (value) {
|
|
642
|
+
if (!workspaceIdRegex.test(value)) {
|
|
643
|
+
throw new Error(
|
|
644
|
+
`Invalid workspace ID: ${value}. Workspace ID must be a string of the format "W[A-Z0-9]{7}".`
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
_workspace = value;
|
|
649
|
+
},
|
|
650
|
+
get appName() {
|
|
651
|
+
return appName;
|
|
652
|
+
},
|
|
653
|
+
get apiUrl() {
|
|
654
|
+
return apiUrl;
|
|
655
|
+
},
|
|
656
|
+
get insightsUrl() {
|
|
657
|
+
return insightsUrl;
|
|
658
|
+
},
|
|
659
|
+
get NODE_ENV() {
|
|
660
|
+
return NODE_ENV;
|
|
661
|
+
},
|
|
662
|
+
get APP_MODE() {
|
|
663
|
+
return APP_MODE;
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
};
|
|
667
|
+
var createHttpClient = (core, pageContext) => {
|
|
668
|
+
const wr = wretch(core.apiUrl).addon(queryStringAddon);
|
|
669
|
+
return {
|
|
670
|
+
get instance() {
|
|
671
|
+
const options = {
|
|
672
|
+
credentials: "include",
|
|
673
|
+
signal: AbortSignal.timeout(3e4),
|
|
674
|
+
// 30 seconds timeout,
|
|
675
|
+
headers: {}
|
|
85
676
|
};
|
|
677
|
+
if (core.workspace) {
|
|
678
|
+
options.headers = {
|
|
679
|
+
...options?.headers || {},
|
|
680
|
+
"Levo-Workspace": core.workspace
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
if (pageContext && typeof pageContext === "object" && Object.keys(pageContext).length > 0) {
|
|
684
|
+
options.headers = {
|
|
685
|
+
...options?.headers || {},
|
|
686
|
+
"Levo-Page-Context": encodeURIComponent(JSON.stringify(pageContext))
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
return wr.options(options);
|
|
690
|
+
},
|
|
691
|
+
pageContext
|
|
692
|
+
};
|
|
693
|
+
};
|
|
694
|
+
var createLogBatch = (options = {}) => {
|
|
695
|
+
const { logApiUrl = "https://public-api.levo.so" } = options;
|
|
696
|
+
const _logApiUrl = logApiUrl;
|
|
697
|
+
const _logs = /* @__PURE__ */ new Map();
|
|
698
|
+
let activeFlush = Promise.resolve();
|
|
699
|
+
let nextFlush = setTimeout(() => {
|
|
700
|
+
}, 0);
|
|
701
|
+
let lastFlush = /* @__PURE__ */ new Date();
|
|
702
|
+
const addUniqueLog = (newLog) => {
|
|
703
|
+
const contentKey = JSON.stringify(newLog?.content ?? "{}");
|
|
704
|
+
const messageKey = newLog?.message ?? "";
|
|
705
|
+
_logs.set(`${messageKey}${contentKey}`, newLog);
|
|
706
|
+
};
|
|
707
|
+
const sendLogs = async (logs) => {
|
|
708
|
+
const url = `${_logApiUrl}/v1/apm/logs/json`;
|
|
709
|
+
const sendFallback = () => {
|
|
710
|
+
return wretch().url(url).post(logs).res().catch((e) => console.error(e));
|
|
711
|
+
};
|
|
712
|
+
try {
|
|
713
|
+
if (typeof fetch === "undefined") {
|
|
714
|
+
throw new Error("fetch is not defined");
|
|
715
|
+
} else if (typeof window !== "undefined" && navigator.sendBeacon) {
|
|
716
|
+
try {
|
|
717
|
+
if (!navigator.sendBeacon.bind(navigator)(url, JSON.stringify(logs))) {
|
|
718
|
+
return sendFallback();
|
|
719
|
+
}
|
|
720
|
+
} catch {
|
|
721
|
+
return sendFallback();
|
|
722
|
+
}
|
|
723
|
+
} else {
|
|
724
|
+
return sendFallback();
|
|
725
|
+
}
|
|
726
|
+
} catch (e) {
|
|
727
|
+
console.warn(`Failed to send logs to server: ${e}`);
|
|
728
|
+
logs.forEach((log) => addUniqueLog(log));
|
|
86
729
|
}
|
|
87
|
-
|
|
730
|
+
};
|
|
731
|
+
const flush = async () => {
|
|
732
|
+
const tasks = Array.from(_logs.values());
|
|
733
|
+
_logs.clear();
|
|
734
|
+
clearTimeout(nextFlush);
|
|
735
|
+
await activeFlush;
|
|
736
|
+
if (tasks.length === 0) {
|
|
737
|
+
lastFlush = /* @__PURE__ */ new Date();
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
try {
|
|
741
|
+
await sendLogs(tasks);
|
|
742
|
+
} catch (e) {
|
|
743
|
+
console.log("error sending logs", e);
|
|
744
|
+
} finally {
|
|
745
|
+
lastFlush = /* @__PURE__ */ new Date();
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
const ingest = (log) => {
|
|
749
|
+
if (!logApiUrl) return;
|
|
750
|
+
const tasks = Array.isArray(log) ? log : [log];
|
|
751
|
+
tasks.forEach((task) => addUniqueLog(task));
|
|
752
|
+
if (_logs.size >= 50 || lastFlush.getTime() < Date.now() - 1500) {
|
|
753
|
+
clearTimeout(nextFlush);
|
|
754
|
+
activeFlush = flush();
|
|
755
|
+
} else {
|
|
756
|
+
clearTimeout(nextFlush);
|
|
757
|
+
nextFlush = setTimeout(() => {
|
|
758
|
+
activeFlush = flush();
|
|
759
|
+
}, 1500);
|
|
760
|
+
}
|
|
761
|
+
};
|
|
762
|
+
return {
|
|
763
|
+
ingest,
|
|
764
|
+
flush
|
|
765
|
+
};
|
|
766
|
+
};
|
|
767
|
+
|
|
768
|
+
// src/logger/index.ts
|
|
769
|
+
var isBrowser = typeof window !== "undefined";
|
|
770
|
+
var getMethodName = (level) => {
|
|
771
|
+
switch (level) {
|
|
772
|
+
case 0 /* debug */:
|
|
773
|
+
return "log";
|
|
774
|
+
case 1 /* info */:
|
|
775
|
+
return "info";
|
|
776
|
+
case 2 /* warn */:
|
|
777
|
+
return "warn";
|
|
778
|
+
case 3 /* error */:
|
|
779
|
+
return "error";
|
|
780
|
+
default:
|
|
781
|
+
return "log";
|
|
88
782
|
}
|
|
89
783
|
};
|
|
784
|
+
var createLevoLogger = (core, options = {}) => {
|
|
785
|
+
const {
|
|
786
|
+
enableRemote = core.NODE_ENV !== "development",
|
|
787
|
+
level: logLevel = core.NODE_ENV !== "development" ? 2 /* warn */ : 0 /* debug */,
|
|
788
|
+
context = {},
|
|
789
|
+
logApiUrl
|
|
790
|
+
} = options;
|
|
791
|
+
const batch = createLogBatch({ logApiUrl });
|
|
792
|
+
const format = (messages) => {
|
|
793
|
+
let message = "";
|
|
794
|
+
const formattedMessages = messages.map((arg) => {
|
|
795
|
+
let payload = "";
|
|
796
|
+
const isMessageEmpty = !message;
|
|
797
|
+
if (typeof arg === "string") {
|
|
798
|
+
payload = arg;
|
|
799
|
+
if (isMessageEmpty) {
|
|
800
|
+
message = arg;
|
|
801
|
+
}
|
|
802
|
+
} else if (arg instanceof Error) {
|
|
803
|
+
payload = {
|
|
804
|
+
message: arg.message,
|
|
805
|
+
name: arg.name,
|
|
806
|
+
stack: arg.stack
|
|
807
|
+
};
|
|
808
|
+
if (isMessageEmpty) {
|
|
809
|
+
message = arg.message;
|
|
810
|
+
}
|
|
811
|
+
} else if (typeof arg === "object") {
|
|
812
|
+
payload = arg;
|
|
813
|
+
} else {
|
|
814
|
+
payload = String(arg);
|
|
815
|
+
if (isMessageEmpty) {
|
|
816
|
+
message = String(arg);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
return payload;
|
|
820
|
+
}).filter(Boolean);
|
|
821
|
+
if (!message && formattedMessages.length > 0) {
|
|
822
|
+
message = "Default message (Check content for details)";
|
|
823
|
+
}
|
|
824
|
+
if (formattedMessages?.length === 1 && formattedMessages[0] === message) {
|
|
825
|
+
return { message, content: {} };
|
|
826
|
+
}
|
|
827
|
+
return {
|
|
828
|
+
message,
|
|
829
|
+
content: formattedMessages
|
|
830
|
+
};
|
|
831
|
+
};
|
|
832
|
+
const log = (level, args) => {
|
|
833
|
+
const messages = Array.isArray(args) ? args : [args];
|
|
834
|
+
if (level < logLevel) {
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
if (enableRemote && level === 3 /* error */) {
|
|
838
|
+
const { content = {}, message } = format(messages);
|
|
839
|
+
if (message) {
|
|
840
|
+
const log2 = {
|
|
841
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
842
|
+
level: "error",
|
|
843
|
+
workspace: core.workspace,
|
|
844
|
+
appName: core?.appName,
|
|
845
|
+
isBrowser,
|
|
846
|
+
...context,
|
|
847
|
+
message,
|
|
848
|
+
content
|
|
849
|
+
};
|
|
850
|
+
if (isBrowser) {
|
|
851
|
+
log2.hostname = window.location.hostname;
|
|
852
|
+
log2.pathname = window.location.pathname;
|
|
853
|
+
log2.url = window.location.href;
|
|
854
|
+
log2.page_title = window.document.title;
|
|
855
|
+
log2.userAgent = window.navigator.userAgent;
|
|
856
|
+
}
|
|
857
|
+
batch.ingest(log2);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
const method = getMethodName(level);
|
|
861
|
+
console[method](...messages);
|
|
862
|
+
};
|
|
863
|
+
const debug = (...args) => {
|
|
864
|
+
log(0 /* debug */, args);
|
|
865
|
+
};
|
|
866
|
+
const info = (...args) => {
|
|
867
|
+
log(1 /* info */, args);
|
|
868
|
+
};
|
|
869
|
+
const warn = (...args) => {
|
|
870
|
+
log(2 /* warn */, args);
|
|
871
|
+
};
|
|
872
|
+
const error = (...args) => {
|
|
873
|
+
log(3 /* error */, args);
|
|
874
|
+
};
|
|
875
|
+
return {
|
|
876
|
+
debug,
|
|
877
|
+
info,
|
|
878
|
+
warn,
|
|
879
|
+
error
|
|
880
|
+
};
|
|
881
|
+
};
|
|
882
|
+
|
|
883
|
+
// src/modules/blog.ts
|
|
884
|
+
var createLevoBlogModule = (core, httpClient, audience = null) => {
|
|
885
|
+
const getAllBlogs = (blog_key, data = {}, options) => {
|
|
886
|
+
return httpClient.instance.url(`/v1/blog/${blog_key}/post/query`).query({ ...options?.params || {} }).options({
|
|
887
|
+
headers: {
|
|
888
|
+
"Levo-Workspace": options?.workspace_id || void 0
|
|
889
|
+
}
|
|
890
|
+
}).post(data).json();
|
|
891
|
+
};
|
|
892
|
+
const getSingleBlog = (blog_key, slug, options) => {
|
|
893
|
+
return httpClient.instance.url(`/v1/blog/${blog_key}/post/${slug}`).query({ ...options?.params || {} }).options({
|
|
894
|
+
headers: {
|
|
895
|
+
"Levo-Workspace": options?.workspace_id || void 0
|
|
896
|
+
}
|
|
897
|
+
}).get().json();
|
|
898
|
+
};
|
|
899
|
+
return {
|
|
900
|
+
getAllBlogs,
|
|
901
|
+
getSingleBlog
|
|
902
|
+
};
|
|
903
|
+
};
|
|
904
|
+
|
|
905
|
+
// src/modules/collection.ts
|
|
906
|
+
var createLevoCollectionModule = (core, httpsClient, audience = null) => {
|
|
907
|
+
const getAllCollections = async (data = {}, options = {}) => {
|
|
908
|
+
return httpsClient.instance.url("/v1/bevy/collection/query").options(options).post(data).json();
|
|
909
|
+
};
|
|
910
|
+
const getCollectionByIDExpanded = async (id, options = {}) => {
|
|
911
|
+
return httpsClient.instance.url(`/v1/bevy/collection/${id}`).options(options).get().json();
|
|
912
|
+
};
|
|
913
|
+
const createCollection = async (data) => {
|
|
914
|
+
return httpsClient.instance.url("/v1/bevy/collection").post(data).json();
|
|
915
|
+
};
|
|
916
|
+
const saveCollectionData = async ({
|
|
917
|
+
collection_id,
|
|
918
|
+
data,
|
|
919
|
+
options = {}
|
|
920
|
+
}) => {
|
|
921
|
+
return httpsClient.instance.url(`/v1/bevy/content/${collection_id}`).options(options).post(data).json();
|
|
922
|
+
};
|
|
923
|
+
const getCollectionContentList = async ({
|
|
924
|
+
collection_key,
|
|
925
|
+
page,
|
|
926
|
+
search,
|
|
927
|
+
limit = 10,
|
|
928
|
+
where
|
|
929
|
+
}) => {
|
|
930
|
+
return httpsClient.instance.url(`/v1/bevy/content/${collection_key}/query`).post({
|
|
931
|
+
page,
|
|
932
|
+
limit,
|
|
933
|
+
search,
|
|
934
|
+
where
|
|
935
|
+
}).json();
|
|
936
|
+
};
|
|
937
|
+
const saveDraftEntry = async (collection_key, data) => {
|
|
938
|
+
return httpsClient.instance.url(`/v1/bevy/content/${collection_key}/save-entry`).post(data).json();
|
|
939
|
+
};
|
|
940
|
+
const getDraftEntry = async (collection_key) => {
|
|
941
|
+
return httpsClient.instance.url(`/v1/bevy/content/${collection_key}/list-entry`).get().json();
|
|
942
|
+
};
|
|
943
|
+
const submitDraftEntry = async (collection_key, data) => {
|
|
944
|
+
return httpsClient.instance.url(`/v1/bevy/content/${collection_key}/submit-entry`).post(data).json();
|
|
945
|
+
};
|
|
946
|
+
return {
|
|
947
|
+
getAllCollections,
|
|
948
|
+
getCollectionByIDExpanded,
|
|
949
|
+
createCollection,
|
|
950
|
+
saveCollectionData,
|
|
951
|
+
getCollectionContentList,
|
|
952
|
+
saveDraftEntry,
|
|
953
|
+
getDraftEntry,
|
|
954
|
+
submitDraftEntry
|
|
955
|
+
};
|
|
956
|
+
};
|
|
957
|
+
|
|
958
|
+
// src/modules/media.ts
|
|
959
|
+
var createLevoMediaModule = (core, httpsClient, audience = null) => {
|
|
960
|
+
const mediaBulkUpload = (formData, options = {}) => {
|
|
961
|
+
return httpsClient.instance.url("/v1/assets/media/bulk").options(options).post(formData).json();
|
|
962
|
+
};
|
|
963
|
+
const getAllMedia = async (data = {}) => {
|
|
964
|
+
return await httpsClient.instance.url("/v1/assets/media/query").post(data).json();
|
|
965
|
+
};
|
|
966
|
+
return {
|
|
967
|
+
mediaBulkUpload,
|
|
968
|
+
getAllMedia
|
|
969
|
+
};
|
|
970
|
+
};
|
|
971
|
+
|
|
972
|
+
// src/constants/oauthProvider.ts
|
|
973
|
+
var LevoOAuthProviderList = [
|
|
974
|
+
"google",
|
|
975
|
+
"linkedin",
|
|
976
|
+
"microsoft"
|
|
977
|
+
];
|
|
978
|
+
|
|
979
|
+
// src/modules/membership.ts
|
|
980
|
+
var createLevoMembershipModule = (core, httpsClient, audience = null) => {
|
|
981
|
+
const getOAuthURL = async (options = {}) => {
|
|
982
|
+
try {
|
|
983
|
+
const response = await httpsClient.instance.url("/v1/membership/auth/oauth/get-redirect-url").options(options).get().json();
|
|
984
|
+
const result = response?.content?.data;
|
|
985
|
+
const providers = Object.keys(result);
|
|
986
|
+
if (typeof window !== "undefined") {
|
|
987
|
+
for (const provider of providers) {
|
|
988
|
+
const raw_url = result[provider];
|
|
989
|
+
if (raw_url) {
|
|
990
|
+
const url = new URL(raw_url);
|
|
991
|
+
const url_params = url.searchParams;
|
|
992
|
+
url_params.set("redirect_uri", window.location.href);
|
|
993
|
+
if (core.workspace) {
|
|
994
|
+
url_params.set("workspace_id", core.workspace);
|
|
995
|
+
}
|
|
996
|
+
if (httpsClient.pageContext) {
|
|
997
|
+
url_params.set(
|
|
998
|
+
"page_context",
|
|
999
|
+
JSON.stringify(httpsClient.pageContext)
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
1002
|
+
result[provider] = `${url.origin}${url.pathname}?${url_params.toString()}`;
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
return result;
|
|
1007
|
+
} catch (_) {
|
|
1008
|
+
return LevoOAuthProviderList.reduce((acc, provider) => {
|
|
1009
|
+
acc[provider] = null;
|
|
1010
|
+
return acc;
|
|
1011
|
+
}, {});
|
|
1012
|
+
}
|
|
1013
|
+
};
|
|
1014
|
+
const signOut = async (options = {}) => {
|
|
1015
|
+
return httpsClient.instance.url("/v1/membership/auth/sign-out").options(options).post("").json();
|
|
1016
|
+
};
|
|
1017
|
+
const getMe = async (options = {}) => {
|
|
1018
|
+
const response = await httpsClient.instance.url("/v1/membership/auth/get-me").options(options).get().json();
|
|
1019
|
+
return response?.content?.data;
|
|
1020
|
+
};
|
|
1021
|
+
const updateMe = async (data, options = {}) => {
|
|
1022
|
+
const response = await httpsClient.instance.url("/v1/membership/auth/update-me").options(options).put(data).json();
|
|
1023
|
+
return response?.content?.data;
|
|
1024
|
+
};
|
|
1025
|
+
const createPassword = async (data, options = {}) => {
|
|
1026
|
+
const response = await httpsClient.instance.url("/v1/membership/auth/change-password").options(options).put(data).json();
|
|
1027
|
+
return response?.content?.data;
|
|
1028
|
+
};
|
|
1029
|
+
const isLoggedIn = async (options = {}) => {
|
|
1030
|
+
try {
|
|
1031
|
+
const account = await getMe(options);
|
|
1032
|
+
return account;
|
|
1033
|
+
} catch (_) {
|
|
1034
|
+
return null;
|
|
1035
|
+
}
|
|
1036
|
+
};
|
|
1037
|
+
const requestMagicLink = async (data, options = {}) => {
|
|
1038
|
+
if (typeof window !== "undefined" && !data.redirect_uri) {
|
|
1039
|
+
data.redirect_uri = window.location.href;
|
|
1040
|
+
}
|
|
1041
|
+
const response = await httpsClient.instance.url("/v1/membership/auth/request-magic-link").options(options).post(data).json();
|
|
1042
|
+
return response?.content?.data;
|
|
1043
|
+
};
|
|
1044
|
+
const requestOtp = async (data, options = {}) => {
|
|
1045
|
+
const response = await httpsClient.instance.url("/v1/membership/auth/request-otp").options(options).post(data).json();
|
|
1046
|
+
return response?.content?.data;
|
|
1047
|
+
};
|
|
1048
|
+
const signInWithOtp = async (data, options = {}) => {
|
|
1049
|
+
const response = await httpsClient.instance.url("/v1/membership/auth/signin-with-otp").options(options).post(data).json();
|
|
1050
|
+
return response?.content?.data;
|
|
1051
|
+
};
|
|
1052
|
+
const signInWithPassword = async (data, options = {}) => {
|
|
1053
|
+
const response = await httpsClient.instance.url("/v1/membership/auth/signin-with-password").options(options).post(data).json();
|
|
1054
|
+
return response?.content?.data;
|
|
1055
|
+
};
|
|
1056
|
+
const signUpWithPassword = async (data, options = {}) => {
|
|
1057
|
+
const response = await httpsClient.instance.url("/v1/membership/auth/signup-with-password").options(options).post(data).json();
|
|
1058
|
+
return response?.content?.data;
|
|
1059
|
+
};
|
|
1060
|
+
return {
|
|
1061
|
+
getOAuthURL,
|
|
1062
|
+
signOut,
|
|
1063
|
+
getMe,
|
|
1064
|
+
updateMe,
|
|
1065
|
+
createPassword,
|
|
1066
|
+
isLoggedIn,
|
|
1067
|
+
requestMagicLink,
|
|
1068
|
+
requestOtp,
|
|
1069
|
+
signInWithOtp,
|
|
1070
|
+
signInWithPassword,
|
|
1071
|
+
signUpWithPassword
|
|
1072
|
+
};
|
|
1073
|
+
};
|
|
1074
|
+
|
|
1075
|
+
// src/client.ts
|
|
1076
|
+
var createLevoClient = (options) => {
|
|
1077
|
+
const {
|
|
1078
|
+
pageContext = {
|
|
1079
|
+
url: typeof window !== "undefined" ? window?.location?.href : "",
|
|
1080
|
+
referrer: typeof document !== "undefined" ? document?.referrer : "",
|
|
1081
|
+
title: typeof document !== "undefined" ? document?.title : ""
|
|
1082
|
+
},
|
|
1083
|
+
loggerOptions = {
|
|
1084
|
+
logApiUrl: "https://public-api.levo.so"
|
|
1085
|
+
},
|
|
1086
|
+
...coreOptions
|
|
1087
|
+
} = options;
|
|
1088
|
+
let _pageContext = pageContext;
|
|
1089
|
+
const core = createLevoControl(coreOptions);
|
|
1090
|
+
const httpsClient = createHttpClient(core, _pageContext);
|
|
1091
|
+
const audience = createLevoAudienceModule(core, httpsClient);
|
|
1092
|
+
const blog = createLevoBlogModule(core, httpsClient, audience);
|
|
1093
|
+
const membership = createLevoMembershipModule(core, httpsClient, audience);
|
|
1094
|
+
const collection = createLevoCollectionModule(core, httpsClient, audience);
|
|
1095
|
+
const media = createLevoMediaModule(core, httpsClient, audience);
|
|
1096
|
+
const logger = createLevoLogger(core, loggerOptions);
|
|
1097
|
+
const updatePageContext = (newContext) => {
|
|
1098
|
+
_pageContext = Object.assign({}, _pageContext, newContext);
|
|
1099
|
+
};
|
|
1100
|
+
const updateWorkspace = (workspace) => {
|
|
1101
|
+
core.workspace = workspace;
|
|
1102
|
+
};
|
|
1103
|
+
return {
|
|
1104
|
+
get apiUrl() {
|
|
1105
|
+
return core.apiUrl;
|
|
1106
|
+
},
|
|
1107
|
+
get insightsUrl() {
|
|
1108
|
+
return core.insightsUrl;
|
|
1109
|
+
},
|
|
1110
|
+
get workspace() {
|
|
1111
|
+
return core.workspace;
|
|
1112
|
+
},
|
|
1113
|
+
get audience() {
|
|
1114
|
+
return audience;
|
|
1115
|
+
},
|
|
1116
|
+
get blog() {
|
|
1117
|
+
return blog;
|
|
1118
|
+
},
|
|
1119
|
+
get membership() {
|
|
1120
|
+
return membership;
|
|
1121
|
+
},
|
|
1122
|
+
get collection() {
|
|
1123
|
+
return collection;
|
|
1124
|
+
},
|
|
1125
|
+
get media() {
|
|
1126
|
+
return media;
|
|
1127
|
+
},
|
|
1128
|
+
get logger() {
|
|
1129
|
+
return logger;
|
|
1130
|
+
},
|
|
1131
|
+
get fetch() {
|
|
1132
|
+
return httpsClient.instance;
|
|
1133
|
+
},
|
|
1134
|
+
get APP_MODE() {
|
|
1135
|
+
return core.APP_MODE;
|
|
1136
|
+
},
|
|
1137
|
+
get pageContext() {
|
|
1138
|
+
return _pageContext;
|
|
1139
|
+
},
|
|
1140
|
+
updatePageContext,
|
|
1141
|
+
updateWorkspace
|
|
1142
|
+
};
|
|
1143
|
+
};
|
|
90
1144
|
|
|
91
1145
|
// src/constants/collection/fieldInterfaceFormat.ts
|
|
92
1146
|
var formatsByInterface = {
|
|
@@ -297,4 +1351,4 @@ var formatImagePath = (string) => {
|
|
|
297
1351
|
return "";
|
|
298
1352
|
};
|
|
299
1353
|
|
|
300
|
-
export { FieldInterfaces, FieldInterfacesList, FieldKind, FieldKindList,
|
|
1354
|
+
export { FieldInterfaces, FieldInterfacesList, FieldKind, FieldKindList, LevoError, LevoOAuthProviderList, LocalStorageLock, MediaKind, MediaKindList, createLevoClient, defaultByKinds, formatImagePath, formatsByInterface, getLevoError, interfaceKinds };
|